# CLAUDE.md — DanceChamp ## What is this project? DanceChamp is a mobile platform for **pole dance championships**. Three apps, one database: - **Member App** (React Native / Expo) — Dancers discover championships, register, track their 10-step progress - **Org App** (React Native / Expo) — Championship organizers create events, manage members, review videos, confirm payments - **Admin Panel** (React + Vite, web) — Platform admin approves orgs, reviews championships from unverified orgs, manages users ## Project Structure ``` / ├── CLAUDE.md ← You are here ├── apps/ │ ├── mobile/ ← Expo app (Member + Org views, switched by role) │ │ ├── src/ │ │ │ ├── screens/ │ │ │ │ ├── member/ ← Home, MyChamps, Search, Profile, ChampDetail, Progress │ │ │ │ ├── org/ ← Dashboard, ChampDetail (tabbed), MemberDetail, Settings │ │ │ │ └── auth/ ← SignIn, SignUp, Onboarding │ │ │ ├── components/ ← Shared UI components │ │ │ ├── navigation/ ← Tab + Stack navigators │ │ │ ├── store/ ← Zustand stores │ │ │ ├── lib/ ← Supabase client, helpers │ │ │ └── theme/ ← Colors, fonts, spacing │ │ └── app.json │ └── admin/ ← Vite React app │ └── src/ │ ├── pages/ ← Dashboard, Orgs, Champs, Users │ ├── components/ │ └── lib/ ├── packages/ │ └── shared/ ← Shared types, constants, validation │ ├── types.ts ← TypeScript interfaces (User, Championship, etc.) │ └── constants.ts ← Status enums, role enums ├── supabase/ │ ├── migrations/ ← SQL migration files │ └── seed.sql ← Demo data └── docs/ ├── SPEC.md ← Full technical specification ├── PLAN.md ← Phase-by-phase dev plan with checkboxes ├── DATABASE.md ← Complete database schema + RLS policies ├── DESIGN-SYSTEM.md ← Colors, fonts, components, patterns └── SCREENS.md ← Screen-by-screen reference for all 3 apps ``` ## Tech Stack | Layer | Choice | Notes | |---|---|---| | Mobile | React Native (Expo) | `npx create-expo-app` with TypeScript | | Admin | React + Vite | Separate web app | | Language | TypeScript | Everywhere | | Navigation | React Navigation | Bottom tabs + stack | | State | Zustand | Lightweight stores | | Backend | Supabase | Auth, Postgres DB, Storage, Realtime, Edge Functions | | Push | Expo Notifications | Via Supabase Edge Function triggers | ## Key Architecture Decisions ### 1. One mobile app, two views Member and Org use the **same Expo app**. After login, the app checks `user.role` and shows the appropriate navigation: - `role === "member"` → Member tabs (Home, My Champs, Search, Profile) - `role === "organization"` → Org tabs (Dashboard, Settings) ### 2. Everything is scoped per-championship Members, results, categories, rules, fees, judges — all belong to a specific championship. There is no "global members list" for an org. Each championship is self-contained. ### 3. Configurable tabs (Org) Orgs don't fill a giant wizard. They quick-create a championship (name + date + location), then configure each section (Categories, Fees, Rules, Judges) at their own pace. Each section has a "✓ Mark as Done" button. Championship can only go live when all sections are done. ### 4. Approval flow - **Verified orgs** → "Go Live" sets status to `live` immediately (auto-approved) - **Unverified orgs** → "Go Live" sets status to `pending_approval` → admin must approve ### 5. Registration dates (not deadline) Championships have: `event_date`, `reg_start`, `reg_end`. Registration close date must be before event date. No single "deadline" field. ### 6. Judges = People, Scoring = Rules The "Judges" tab shows judge profiles (name, instagram, bio). Scoring criteria and penalties live in the "Rules" tab. ## Conventions ### Code Style - Functional components only, no class components - Use hooks: `useState`, `useEffect`, custom hooks for data fetching - Zustand for global state (auth, current user, championships cache) - Local state for UI-only state (modals, form inputs, filters) - TypeScript strict mode ### Naming - Files: `kebab-case.ts` / `kebab-case.tsx` - Components: `PascalCase` - Hooks: `useCamelCase` - Zustand stores: `use[Name]Store` - DB tables: `snake_case` - DB columns: `snake_case` ### Supabase Patterns ```typescript // Client init import { createClient } from '@supabase/supabase-js' const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY) // Fetching const { data, error } = await supabase .from('championships') .select('*, disciplines(*), fees(*)') .eq('status', 'live') // Realtime subscription supabase.channel('registrations') .on('postgres_changes', { event: '*', schema: 'public', table: 'registrations' }, handler) .subscribe() ``` ### Navigation Pattern ```typescript // Member const MemberTabs = () => ( ) // Org const OrgTabs = () => ( ) ``` ## Important Docs Before coding any feature, read the relevant doc: | Doc | When to read | |---|---| | `docs/SPEC.md` | Full feature spec — read first for any new feature | | `docs/PLAN.md` | Dev plan with phases — check what's next | | `docs/DATABASE.md` | Schema — read before any DB work | | `docs/DESIGN-SYSTEM.md` | UI — read before any screen work | | `docs/SCREENS.md` | Screen details — read before building specific screens | ## Quick Commands ```bash # Start mobile app cd apps/mobile && npx expo start # Start admin panel cd apps/admin && npm run dev # Supabase local dev npx supabase start npx supabase db reset # Reset + re-seed # Generate types from Supabase npx supabase gen types typescript --local > packages/shared/database.types.ts ``` ## Current Status Prototypes completed (JSX files in `/prototypes`): - `dance-champ-mvp.jsx` — Member app prototype - `dance-champ-org.jsx` — Org app prototype - `dance-champ-admin.jsx` — Admin panel prototype These are reference implementations showing the exact UI, data structure, and flows. Use them as visual guides — don't copy the code directly (they're single-file React prototypes, not production React Native).