Created
March 8, 2026 03:42
-
-
Save samkeen/3957502a7e249a5a87275697e114dc3e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ❯ how does this app work | |
| ⏺ Bash(date '+%Y-%m-%d %H:%M:%S %z') | |
| ⎿ 2026-03-07 19:39:07 -0800 | |
| ⏺ Searched for 2 patterns, read 5 files (ctrl+o to expand) | |
| ⏺ Here's how Demo Kit works: | |
| The Big Picture | |
| Demo Kit is a platform for running structured demo nights — think hackathon showcases, team demo days, or community project showcases. It solves the "everyone fumbles with cables and | |
| screenshare" problem by giving demos a permanent, structured home. | |
| Core Concepts | |
| There are three main entities and the relationships between them drive everything: | |
| 1. Demos (reusable project assets) | |
| A demo is a structured description of a project: GitHub repo link, premise, problem statement, differentiating features, and an optional screencast. Demos are owned by teams (even solo | |
| creators get a team-of-one). They exist independently from events — one demo can be submitted to many events over time. | |
| Demos have a two-track state system: | |
| - Status: draft → complete (are the required fields filled in?) | |
| - Visibility: private → public (who can see it?) | |
| The completeness check (src/lib/demo-completeness.ts) is a pure function — it just looks at whether title, repo URL, premise, problem, and differentiating features are filled in. It | |
| runs bidirectionally: fill in the last field and you auto-transition to complete; clear one and you drop back to draft. | |
| 2. Events (curated demo sessions) | |
| Events are what organizers create to run a demo night. They follow a strict lifecycle state machine (src/lib/event-state.ts): | |
| draft → open_for_submissions → reviewing → live → completed → archived | |
| The transition rules are intentionally restrictive — you can reopen submissions from reviewing, but you can never go backwards from completed. Events with approved submissions can't be | |
| deleted (data protection). | |
| 3. Voting (two separate systems) | |
| This is an interesting design choice — there are two independent voting mechanisms: | |
| - Public upvotes: persistent social proof, like GitHub stars. Anyone can upvote a demo anytime. | |
| - Audience votes: event-scoped ranking during a live demo session. Points-by-position for crowd wisdom. | |
| Raw votes are stored individually (not pre-aggregated), so the ranking algorithm can be changed later without a data migration. | |
| Architecture | |
| Route Groups (Next.js App Router) | |
| The app uses three route groups visible in the page structure: | |
| ┌──────────────┬────────────────────────────────────────────────────────────────────────┐ | |
| │ Group │ Purpose │ | |
| ├──────────────┼────────────────────────────────────────────────────────────────────────┤ | |
| │ (auth)/ │ Login and signup pages │ | |
| ├──────────────┼────────────────────────────────────────────────────────────────────────┤ | |
| │ (dashboard)/ │ Authenticated pages — demo management, event management, guest landing │ | |
| ├──────────────┼────────────────────────────────────────────────────────────────────────┤ | |
| │ (public)/ │ Public-facing — homepage, demo browsing, individual demo pages │ | |
| └──────────────┴────────────────────────────────────────────────────────────────────────┘ | |
| API Layer (10 routes) | |
| API routes handle mutations: creating/updating demos, validating GitHub repos, managing events and event submissions. Every route checks auth via Supabase and role via getUserRole(). | |
| Authorization Model | |
| Authorization is enforced at the database layer via Supabase Row Level Security (RLS), not just in middleware. The middleware (src/lib/supabase/middleware.ts) handles session refresh | |
| and route protection, but the real access control lives in Postgres policies. This means even if someone bypasses the API, the database won't let them read/write unauthorized data. | |
| Role System | |
| Users have roles (at minimum guest and builder). Guests land at /guest, builders get the full /dashboard. The getUserRole() helper in src/lib/auth.ts fetches the role from the users | |
| table. | |
| Theme System | |
| The design system uses a 3-layer token architecture: raw color scales → semantic tokens → theme overrides. Components only reference semantic tokens like --text-heading or | |
| --surface-page, and the theme switch (light/dark/system) just swaps the semantic values. A small inline script in layout.tsx reads the theme from localStorage before React hydrates to | |
| prevent a flash of wrong theme. | |
| ★ Insight ───────────────────────────────────── | |
| - The two-track state model (status vs visibility) is a smart pattern — it separates "is this ready?" from "who can see it?" as independent axes, avoiding a combinatorial explosion of | |
| states. | |
| - Storing raw votes instead of aggregated counts is a forward-looking decision: you can retroactively apply different ranking algorithms (Bayesian average, Wilson score, etc.) without | |
| migrating data. | |
| - The pure-function completeness check is decoupled from the database — it can run client-side for instant UI feedback and server-side for validation, with zero duplication of logic. | |
| ───────────────────────────────────────────────── |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment