Big feature batch driven by the super-audit findings and the user's follow-up requests. Schema migration 021 (folded into schema.sql Section 13): - forum_threads + polymorphic comments table keyed on (entity_type, entity_id). Entity types: forum_thread, proposal, incident, policy. Trigger maintains forum_threads.comment_count and last_comment_at. - space_tiers per-space with monthly_price_cents, billing_cadence, is_system, sort_order. Trigger seeds plus/basic/associate on every space INSERT and backfills existing spaces. space_members.tier_id FK added and backfilled from the legacy enum value. - space_role_labels (rename/recolor built-in roles per space). space_custom_roles + space_member_custom_roles for non-privileged extra labels. RLS gates by admin/board. - space_invites: multi-code invites with expires_at, max_uses, uses_count, is_enabled. Legacy spaces.invite_code backfilled as a permanent enabled invite. - secrets.encrypted_value bytea + encryption_version. Secrets RLS tightened. New comms_channels INSERT policy: any member can create; default channels are protected from deletion. - knowledge_base.render_markdown boolean (default true). Secrets encryption-at-rest: - AES-256-GCM in lib/secrets/crypto.ts. Master key from SECRETS_ENCRYPTION_KEY env (64 hex chars). - New revealSecret(id) server action: only path to plaintext, writes secret.revealed to activity_log. - /ops/page.tsx no longer selects value or encrypted_value on the list endpoint - the original screenshot bug where ciphertext was already in the page bundle before "Reveal" is fixed. UI: - /forum index, /forum/new, /forum/[id]. Pin/lock/delete actions for admin/board. - CommentThread component embedded on /proposals/[id], /incidents/[id], /policies/[slug]. Markdown rendering via react-markdown + remark-gfm. - /comms sidebar: inline "+ New channel" form. - /ops KB: row click opens markdown-rendering viewer modal. - /settings: new Tiers tab and Invites tab. Inline price edit and archive/delete on tiers; copy/enable/disable/delete on invites. - AtlasLogo replaces the terminal icon on the landing nav and footer. public/logo.svg wired as the favicon in app/layout.tsx metadata. - Sidebar has a Forum nav link. Server actions added: - lib/actions/forum.ts, comms.ts, tiers.ts, roles.ts, invites.ts. - lib/actions/secrets.ts rewritten with updateSecret + revealSecret. Auth flow: - joinSpace honors codes from space_invites first (enabled, expiry, use cap), falls back to legacy spaces.invite_code, increments uses_count on success. Env: - SECRETS_ENCRYPTION_KEY documented in .env.example and set on the Droplet's /opt/hackerspace-ops/.env.production. README: live site link added (https://hackerspace.sh). 266/266 unit tests pass. Production build clean. Migration 021 will be applied on the next deploy via /opt/hackerspace-ops/deploy.sh's idempotent migration runner.
Hackerspace.sh Documentation
Version: 1.0.0
Last Updated: 2026-03-10
Status: Pre-Production
Documentation Index
| Document | Description |
|---|---|
| ARCHITECTURE.md | System overview, tech stack, project structure, auth flows |
| DATABASE_SCHEMA.md | Complete schema reference, enums, relationships, RLS |
| API_REFERENCE.md | All server actions, parameters, return types |
| COMPONENT_REFERENCE.md | React components, props, usage patterns |
| PRODUCTION_AUDIT.md | Security audit, issues, action plan |
Quick Start
Development Setup
# Clone and install
git clone <repo>
cd hackerspace-sh
pnpm install
# Set environment variables
cp .env.example .env.local
# Edit .env.local with your Supabase credentials
# Run database migrations
# Execute scripts/001_create_schema.sql through scripts/011_*.sql in order
# Start development server
pnpm dev
Environment Variables
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key
SUPABASE_JWT_SECRET=your-jwt-secret
Application Overview
What is Hackerspace.sh?
A comprehensive member management platform for hackerspaces, makerspaces, and community workshops. Features include:
- Member Management - Registration, approval, roles, payment tracking
- Task System - One-time tasks and recurring chores
- Project Tracking - Kanban-style project management
- Payment Reconciliation - Multi-platform payment integration
- Communications - Real-time chat via Supabase Realtime
- Knowledge Base - Documentation and secrets management
- Contact Directory - Vendors, suppliers, partners
Tech Stack
| Layer | Technology |
|---|---|
| Frontend | Next.js 16, React 19, TypeScript, Tailwind CSS |
| UI | shadcn/ui component library |
| Backend | Next.js Server Actions |
| Database | Supabase PostgreSQL |
| Auth | Supabase Auth |
| Real-time | Supabase Realtime |
| Hosting | Self-hosted DigitalOcean Droplet (Docker, Caddy) |
Key Concepts
Spaces
A "space" represents a single hackerspace organization. Each space has:
- Unique slug and invite code
- Its own members, tasks, projects, etc.
- Independent settings and integrations
Membership
Users belong to spaces via the space_members table:
- A user can belong to multiple spaces
- Each membership has a role (admin, board, treasurer, member, associate)
- Status tracks account state (current, late, inactive, unverified)
Roles & Permissions
| Role | Capabilities |
|---|---|
| Admin | Full access to everything |
| Board | Members, payments, projects, board-level KB |
| Treasurer | Payments and financial data |
| Member | Tasks, projects, comms, public KB |
| Associate | Read-only, can claim chores |
Row Level Security
All database access is protected by RLS policies:
- Users can only see data from their space
- Role-based write permissions
- Enforced at the database level
Common Tasks
Add a New Feature
- Create page in
app/(app)/feature/page.tsx(Server Component) - Create client component in
app/(app)/feature/feature-client.tsx - Add server action in
lib/actions.ts - Add navigation link in
components/app-sidebar.tsx - Update types in
lib/types.tsif needed
Add Database Table
- Create migration script in
scripts/0XX_description.sql - Define table with RLS policies
- Run migration via Supabase SQL Editor
- Add TypeScript interface to
lib/types.ts - Update
docs/DATABASE_SCHEMA.md
Add Server Action
- Add function to
lib/actions.ts - Include auth check:
supabase.auth.getUser() - Include membership check
- Include role check if needed
- Add Zod validation (recommended)
- Call
revalidatePath()for cache - Update
docs/API_REFERENCE.md
Code Style
TypeScript
- Use strict types, avoid
any - Define interfaces in
lib/types.ts - Use Zod for runtime validation
React
- Server Components for data fetching
- Client Components for interactivity
- Use
'use client'directive explicitly
Styling
- Tailwind CSS utility classes
- shadcn/ui design tokens (
bg-background,text-foreground) - Monospace font for labels:
font-mono text-[10px]
File Naming
- Pages:
page.tsx - Client components:
feature-client.tsx - Server actions:
lib/actions.ts - Types:
lib/types.ts
Deployment
DigitalOcean Droplet (production)
See DEPLOYMENT.md for the at-a-glance flow and DEPLOY_DO_SELFHOSTED.md for the end-to-end provisioning procedure. Every push to main triggers GitHub Actions, which runs the deploy script on the Droplet over SSH.
Database Migrations
Migrations must be run manually via Supabase SQL Editor:
- Open Supabase Dashboard → SQL Editor
- Run migration scripts in order
- Verify with
SELECT * FROM pg_tables WHERE schemaname = 'public'
Troubleshooting
Common Issues
| Issue | Solution |
|---|---|
| "Not authenticated" | Check session, redirect to login |
| "No active membership" | User needs to create/join space |
| RLS policy error | Check user has correct role |
| Infinite redirect | Check middleware, layout redirects |
| Stale data | Call revalidatePath() or router.refresh() |
Debug Mode
Add console logs in server actions:
console.log('[app] User:', user?.id, 'Space:', member?.space_id)
View logs with journalctl -u hackerspace-app -f on the Droplet, or in the dev server terminal locally.
Support
- GitHub Issues: Report bugs and feature requests
- Documentation: This folder
- Code: Well-commented in key areas
License
[Add license information]