'use client' import { useState, useEffect } from 'react' import Link from 'next/link' // Icons function IcoUsers({ className }: { className?: string }) { return } function IcoTask({ className }: { className?: string }) { return } function IcoFolder({ className }: { className?: string }) { return } function IcoCreditCard({ className }: { className?: string }) { return } function IcoLock({ className }: { className?: string }) { return } function IcoDoc({ className }: { className?: string }) { return } function IcoArrow({ className }: { className?: string }) { return } function IcoTerminal({ className }: { className?: string }) { return } function IcoEye({ className }: { className?: string }) { return } function IcoPin({ className }: { className?: string }) { return } // ─── Mini UI Previews ────────────────────────────────────────────────────────── function MiniMemberTable() { const [activeRow, setActiveRow] = useState(0) const members = [ { name: 'Alex Chen', tier: 'PLUS', status: 'current' }, { name: 'Jordan Mills', tier: 'BASIC', status: 'current' }, { name: 'Sam Rivera', tier: 'PLUS', status: 'late' }, { name: 'Casey Wong', tier: 'BASIC', status: 'current' }, ] useEffect(() => { const t = setInterval(() => setActiveRow(p => (p + 1) % members.length), 2000) return () => clearInterval(t) }, [members.length]) return (
Members {members.length}
{members.map((m, i) => (
{m.name.split(' ').map(n => n[0]).join('')}
{m.name} {m.tier}
))}
) } function MiniTaskList() { const [checkedIndex, setCheckedIndex] = useState(-1) const tasks = [ { title: 'Clean laser cutter lens', area: 'Laser' }, { title: 'Restock filament', area: '3D Print' }, { title: 'Update wiki docs', area: 'Admin' }, ] useEffect(() => { const t = setInterval(() => { setCheckedIndex(p => (p >= tasks.length - 1 ? -1 : p + 1)) }, 1500) return () => clearInterval(t) }, [tasks.length]) return (
Tasks +
{tasks.map((t, i) => (
{i <= checkedIndex && ( )}
{t.title} {t.area}
))}
) } function MiniProjectBoard() { const [movingCard, setMovingCard] = useState(0) useEffect(() => { const t = setInterval(() => setMovingCard(p => (p + 1) % 3), 2500) return () => clearInterval(t) }, []) const columns = ['BACKLOG', 'IN PROGRESS', 'DONE'] return (
Projects
{columns.map((col, colIndex) => (
{col}
{colIndex === movingCard && (

CNC Upgrade

)} {colIndex === 1 && colIndex !== movingCard && (

Network rack

)}
))}
) } function MiniPayments() { const [linking, setLinking] = useState(false) useEffect(() => { const t = setInterval(() => setLinking(p => !p), 2000) return () => clearInterval(t) }, []) return (
Payments 2 unlinked
PAYPAL $50.00 {linking ? 'LINKED' : '+ LINK'}
VENMO $75.00 LINKED
) } function MiniOps() { const [revealedIndex, setRevealedIndex] = useState(-1) const [tab, setTab] = useState<'secrets' | 'kb'>('secrets') const secrets = [ { label: 'WiFi Password', area: 'Network' }, { label: 'Alarm Code', area: 'Security' }, { label: 'PayPal API Key', area: 'Finance' }, ] const kb = [ { title: 'Open / Close Procedure', area: 'Ops', pinned: true }, { title: 'Laser Cutter Safety', area: 'Laser', pinned: false }, { title: 'Board Meeting Runbook', area: 'Admin', pinned: true }, ] useEffect(() => { if (tab !== 'secrets') return const t = setInterval(() => { setRevealedIndex(p => (p >= secrets.length - 1 ? -1 : p + 1)) }, 1800) return () => clearInterval(t) }, [tab, secrets.length]) useEffect(() => { const t = setInterval(() => { setTab(p => (p === 'secrets' ? 'kb' : 'secrets')) setRevealedIndex(-1) }, 5000) return () => clearInterval(t) }, []) return (
Ops
{(['secrets', 'kb'] as const).map(t => ( ))}
{tab === 'secrets' && secrets.map((s, i) => (
{s.label} {s.area}
{i === revealedIndex ? ( ••••1234 ) : ( reveal )}
))} {tab === 'kb' && kb.map((k) => (
{k.title} {k.pinned && } {k.area}
))}
) } function MiniDashboard() { const [tick, setTick] = useState(0) useEffect(() => { const t = setInterval(() => setTick(p => p + 1), 3000) return () => clearInterval(t) }, []) const members = 47 + (tick % 3) return (
Members

{members}

Tasks

12

Due this week 3 late
{Array.from({ length: 12 }).map((_, i) => (
))}
) } // ─── Main Landing Page ───────────────────────────────────────────────────────── export default function LandingPage() { return (
{/* Nav */} {/* Hero */}

hackerspace management

Members, payments, tasks, projects, ops docs

Track who is in your space, what they owe, what needs doing, and where to find the WiFi password.

Get Started Log in
{/* Features */}

What it does

Six modules

{[ { Icon: IcoUsers, title: 'Member Directory', description: 'Track membership tiers, payment status, and contact info. Bulk actions for common operations. Know who is current and who is not.', preview: , }, { Icon: IcoTask, title: 'Task Board', description: 'Chores, maintenance, and one-off tasks with assignments, due dates, and recurring schedules. Claim and complete from anywhere.', preview: , }, { Icon: IcoFolder, title: 'Project Tracking', description: 'Kanban board for space projects. Track progress, assign areas, and keep the community informed about what is in motion.', preview: , }, { Icon: IcoCreditCard, title: 'Payment Reconciliation', description: 'Import from PayPal, Venmo, or Zeffy. Match transactions to members manually or let it auto-match by email.', preview: , }, { Icon: IcoLock, title: 'Ops: Secrets and KB', description: 'Store WiFi passwords, alarm codes, API keys, and procedures in one place. Role-based visibility. Reveal on demand.', preview: , }, { Icon: IcoDoc, title: 'Dashboard', description: 'At a glance status on membership, open tasks, payment issues, and recent activity. Know what needs attention when you log in.', preview: , }, ].map((feature) => (

{feature.title}

{feature.description}

{feature.preview}
))}
{/* How it works */}

Setup

From nothing to running in under an hour

{[ { step: '01', title: 'Import your members', description: 'Paste from a spreadsheet or add them one by one. Set tiers, statuses, and contact info.', }, { step: '02', title: 'Connect payments', description: 'Link your PayPal or Zeffy account. Import transactions and match them to members.', }, { step: '03', title: 'Seed your ops docs', description: 'Drop in your SOPs, credentials, and area leads. The whole board has one place to look things up.', }, ].map((item) => (

{item.step}

{item.title}

{item.description}

))}
{/* CTA */}
Get Started Log in
{/* Footer */}
) }