|
| 1 | +# Consumer SaaS Design - AI Development Cockpit |
| 2 | + |
| 3 | +**Date**: 2025-11-29 |
| 4 | +**Status**: Approved |
| 5 | +**Target Users**: Non-coders (family, beginners) who want to build apps |
| 6 | + |
| 7 | +--- |
| 8 | + |
| 9 | +## Design Summary |
| 10 | + |
| 11 | +Transform AI Development Cockpit into a consumer-friendly SaaS with: |
| 12 | +- Sidebar layout (like Claude Code) |
| 13 | +- GitHub integration during project creation |
| 14 | +- Theme switcher (arcade/enterprise) |
| 15 | +- Cloud storage via Supabase free tier |
| 16 | + |
| 17 | +--- |
| 18 | + |
| 19 | +## Layout Architecture |
| 20 | + |
| 21 | +### Sidebar + Main Layout |
| 22 | + |
| 23 | +``` |
| 24 | +┌─────────────────────────────────────────────────────────────────────┐ |
| 25 | +│ AI Dev Cockpit [Select repo ▼] [Theme ▼] │ |
| 26 | +├──────────────────────┬──────────────────────────────────────────────┤ |
| 27 | +│ │ │ |
| 28 | +│ Projects Active▼ │ Quick Actions │ |
| 29 | +│ │ │ |
| 30 | +│ ┌────────────────┐ │ ┌─────────────┐ ┌─────────────┐ │ |
| 31 | +│ │ Todo App │ │ │ New Project │ │ Continue │ │ |
| 32 | +│ │ user/todo-app │ │ │ │ │ Last │ │ |
| 33 | +│ └────────────────┘ │ └─────────────┘ └─────────────┘ │ |
| 34 | +│ │ │ |
| 35 | +│ ┌────────────────┐ │ ┌─────────────┐ ┌─────────────┐ │ |
| 36 | +│ │ Weather API │ │ │ Import from │ │ Browse │ │ |
| 37 | +│ │ Draft │ │ │ GitHub │ │ Templates │ │ |
| 38 | +│ └────────────────┘ │ └─────────────┘ └─────────────┘ │ |
| 39 | +│ │ │ |
| 40 | +│ [+ New Project] │ │ |
| 41 | +│ │ │ |
| 42 | +├──────────────────────┴──────────────────────────────────────────────┤ |
| 43 | +│ 👤 Username ⚙ Settings │ |
| 44 | +└─────────────────────────────────────────────────────────────────────┘ |
| 45 | +``` |
| 46 | + |
| 47 | +### Route Structure |
| 48 | + |
| 49 | +``` |
| 50 | +src/app/ |
| 51 | +├── (app)/ # Main app with sidebar layout |
| 52 | +│ ├── layout.tsx # SidebarLayout component |
| 53 | +│ ├── page.tsx # Dashboard with quick actions |
| 54 | +│ ├── projects/[id]/ # Project detail/chat view |
| 55 | +│ └── settings/ # User settings |
| 56 | +├── (auth)/ # Auth pages (no sidebar) |
| 57 | +│ ├── layout.tsx |
| 58 | +│ ├── login/ |
| 59 | +│ └── callback/ |
| 60 | +└── layout.tsx # Root (providers only) |
| 61 | +``` |
| 62 | + |
| 63 | +--- |
| 64 | + |
| 65 | +## Theme System |
| 66 | + |
| 67 | +### Tailwind Theme Classes |
| 68 | + |
| 69 | +Add to `globals.css`: |
| 70 | + |
| 71 | +```css |
| 72 | +/* Arcade Theme - Terminal green */ |
| 73 | +.theme-arcade { |
| 74 | + --background: 10 10 10; |
| 75 | + --foreground: 0 255 0; |
| 76 | + --card: 26 26 26; |
| 77 | + --card-foreground: 0 255 0; |
| 78 | + --primary: 0 255 0; |
| 79 | + --primary-foreground: 0 0 0; |
| 80 | + --muted: 38 38 38; |
| 81 | + --muted-foreground: 0 200 0; |
| 82 | + --border: 0 100 0; |
| 83 | +} |
| 84 | + |
| 85 | +/* Enterprise Theme - Professional blue */ |
| 86 | +.theme-enterprise { |
| 87 | + --background: 255 255 255; |
| 88 | + --foreground: 31 41 55; |
| 89 | + --card: 249 250 251; |
| 90 | + --card-foreground: 31 41 55; |
| 91 | + --primary: 59 130 246; |
| 92 | + --primary-foreground: 255 255 255; |
| 93 | + --muted: 243 244 246; |
| 94 | + --muted-foreground: 107 114 128; |
| 95 | + --border: 229 231 235; |
| 96 | +} |
| 97 | + |
| 98 | +/* Dark variant for enterprise */ |
| 99 | +.dark.theme-enterprise { |
| 100 | + --background: 17 24 39; |
| 101 | + --foreground: 243 244 246; |
| 102 | + --card: 31 41 55; |
| 103 | + --primary: 96 165 250; |
| 104 | +} |
| 105 | +``` |
| 106 | + |
| 107 | +### Theme Switcher Component |
| 108 | + |
| 109 | +Store preference in: |
| 110 | +1. localStorage (immediate) |
| 111 | +2. Supabase profiles.theme_preference (persist across devices) |
| 112 | + |
| 113 | +--- |
| 114 | + |
| 115 | +## Database Schema |
| 116 | + |
| 117 | +### Projects Table |
| 118 | + |
| 119 | +```sql |
| 120 | +CREATE TABLE projects ( |
| 121 | + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), |
| 122 | + user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE NOT NULL, |
| 123 | + name TEXT NOT NULL, |
| 124 | + description TEXT, |
| 125 | + status TEXT DEFAULT 'draft' |
| 126 | + CHECK (status IN ('draft', 'building', 'ready', 'deployed', 'failed')), |
| 127 | + user_request TEXT, |
| 128 | + github_repo_url TEXT, |
| 129 | + github_repo_full_name TEXT, |
| 130 | + total_cost_usd DECIMAL(10,6) DEFAULT 0, |
| 131 | + created_at TIMESTAMPTZ DEFAULT NOW(), |
| 132 | + updated_at TIMESTAMPTZ DEFAULT NOW() |
| 133 | +); |
| 134 | + |
| 135 | +-- RLS: Users see only their projects |
| 136 | +ALTER TABLE projects ENABLE ROW LEVEL SECURITY; |
| 137 | + |
| 138 | +CREATE POLICY "Users manage own projects" ON projects |
| 139 | + FOR ALL USING (auth.uid() = user_id); |
| 140 | + |
| 141 | +-- Index for fast lookups |
| 142 | +CREATE INDEX idx_projects_user_id ON projects(user_id); |
| 143 | +``` |
| 144 | + |
| 145 | +### Project Builds Table |
| 146 | + |
| 147 | +```sql |
| 148 | +CREATE TABLE project_builds ( |
| 149 | + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), |
| 150 | + project_id UUID REFERENCES projects(id) ON DELETE CASCADE NOT NULL, |
| 151 | + build_number INTEGER NOT NULL, |
| 152 | + status TEXT DEFAULT 'pending' |
| 153 | + CHECK (status IN ('pending', 'running', 'success', 'failed')), |
| 154 | + cost_usd DECIMAL(10,6) DEFAULT 0, |
| 155 | + duration_ms INTEGER, |
| 156 | + agent_outputs JSONB, |
| 157 | + error_message TEXT, |
| 158 | + started_at TIMESTAMPTZ DEFAULT NOW(), |
| 159 | + completed_at TIMESTAMPTZ |
| 160 | +); |
| 161 | + |
| 162 | +-- RLS: Access through project ownership |
| 163 | +ALTER TABLE project_builds ENABLE ROW LEVEL SECURITY; |
| 164 | + |
| 165 | +CREATE POLICY "Users view own project builds" ON project_builds |
| 166 | + FOR SELECT USING ( |
| 167 | + project_id IN (SELECT id FROM projects WHERE user_id = auth.uid()) |
| 168 | + ); |
| 169 | + |
| 170 | +CREATE POLICY "System creates builds" ON project_builds |
| 171 | + FOR INSERT WITH CHECK (true); |
| 172 | +``` |
| 173 | + |
| 174 | +### Profile Updates |
| 175 | + |
| 176 | +```sql |
| 177 | +ALTER TABLE profiles |
| 178 | + ADD COLUMN IF NOT EXISTS theme_preference TEXT DEFAULT 'arcade', |
| 179 | + ADD COLUMN IF NOT EXISTS github_connected BOOLEAN DEFAULT FALSE, |
| 180 | + ADD COLUMN IF NOT EXISTS onboarding_completed BOOLEAN DEFAULT FALSE; |
| 181 | +``` |
| 182 | + |
| 183 | +--- |
| 184 | + |
| 185 | +## GitHub Integration |
| 186 | + |
| 187 | +### OAuth Scope |
| 188 | + |
| 189 | +Request `repo` scope for full repository access (public and private). |
| 190 | + |
| 191 | +### Flow |
| 192 | + |
| 193 | +1. User clicks "Select repository" dropdown |
| 194 | +2. If not connected → "Connect GitHub" button |
| 195 | +3. OAuth flow → store token securely |
| 196 | +4. Dropdown populates with user's repos |
| 197 | +5. User selects existing repo OR creates new one |
| 198 | +6. On build complete → auto-push code to repo |
| 199 | + |
| 200 | +### GitHubService Methods |
| 201 | + |
| 202 | +```typescript |
| 203 | +interface GitHubService { |
| 204 | + isConnected(): boolean |
| 205 | + connect(): Promise<void> // OAuth redirect |
| 206 | + listRepos(): Promise<Repo[]> // GET /user/repos |
| 207 | + createRepo(name: string, isPrivate: boolean): Promise<Repo> |
| 208 | + pushFiles(repo: string, files: File[], message: string): Promise<void> |
| 209 | +} |
| 210 | +``` |
| 211 | + |
| 212 | +--- |
| 213 | + |
| 214 | +## Components to Build |
| 215 | + |
| 216 | +### Layout Components |
| 217 | + |
| 218 | +| Component | Purpose | |
| 219 | +|-----------|---------| |
| 220 | +| `SidebarLayout.tsx` | Main app layout with sidebar | |
| 221 | +| `Sidebar.tsx` | Project list, new project button | |
| 222 | +| `TopBar.tsx` | Logo, repo selector, theme toggle | |
| 223 | +| `UserMenu.tsx` | Avatar, settings link, sign out | |
| 224 | + |
| 225 | +### Project Components |
| 226 | + |
| 227 | +| Component | Purpose | |
| 228 | +|-----------|---------| |
| 229 | +| `ProjectList.tsx` | Sidebar project list | |
| 230 | +| `ProjectCard.tsx` | Single project in sidebar | |
| 231 | +| `QuickActions.tsx` | Dashboard action cards | |
| 232 | +| `CreateProjectModal.tsx` | New project form | |
| 233 | +| `RepoSelector.tsx` | GitHub repo dropdown | |
| 234 | + |
| 235 | +### Theme Components |
| 236 | + |
| 237 | +| Component | Purpose | |
| 238 | +|-----------|---------| |
| 239 | +| `ThemeSwitcher.tsx` | Arcade/Enterprise toggle | |
| 240 | +| `ThemePreview.tsx` | Visual preview of theme | |
| 241 | + |
| 242 | +--- |
| 243 | + |
| 244 | +## User Flows |
| 245 | + |
| 246 | +### New User Flow |
| 247 | + |
| 248 | +1. User visits site → sees login page |
| 249 | +2. Clicks "Sign in with GitHub" → OAuth with `repo` scope |
| 250 | +3. Redirects to dashboard → sees quick actions |
| 251 | +4. GitHub already connected (from OAuth) |
| 252 | +5. Clicks "New Project" → create project modal |
| 253 | +6. Selects/creates repo, describes app → starts building |
| 254 | + |
| 255 | +### Returning User Flow |
| 256 | + |
| 257 | +1. User visits site → auto-logged in (session) |
| 258 | +2. Sees dashboard with project list in sidebar |
| 259 | +3. Clicks project → opens project detail/chat |
| 260 | +4. Or clicks "New Project" to start fresh |
| 261 | + |
| 262 | +### Theme Switch Flow |
| 263 | + |
| 264 | +1. User clicks theme toggle in top bar |
| 265 | +2. Theme switches immediately (localStorage) |
| 266 | +3. Preference saves to Supabase (background) |
| 267 | +4. On next visit, theme loads from Supabase |
| 268 | + |
| 269 | +--- |
| 270 | + |
| 271 | +## File Structure |
| 272 | + |
| 273 | +``` |
| 274 | +src/ |
| 275 | +├── app/ |
| 276 | +│ ├── (app)/ |
| 277 | +│ │ ├── layout.tsx # SidebarLayout |
| 278 | +│ │ ├── page.tsx # Dashboard |
| 279 | +│ │ ├── projects/ |
| 280 | +│ │ │ └── [id]/page.tsx # Project detail |
| 281 | +│ │ └── settings/page.tsx # Settings |
| 282 | +│ ├── (auth)/ |
| 283 | +│ │ ├── layout.tsx |
| 284 | +│ │ ├── login/page.tsx |
| 285 | +│ │ └── callback/page.tsx |
| 286 | +│ ├── globals.css # Theme CSS variables |
| 287 | +│ └── layout.tsx # Root providers |
| 288 | +├── components/ |
| 289 | +│ ├── layout/ |
| 290 | +│ │ ├── SidebarLayout.tsx |
| 291 | +│ │ ├── Sidebar.tsx |
| 292 | +│ │ ├── TopBar.tsx |
| 293 | +│ │ └── UserMenu.tsx |
| 294 | +│ ├── projects/ |
| 295 | +│ │ ├── ProjectList.tsx |
| 296 | +│ │ ├── ProjectCard.tsx |
| 297 | +│ │ ├── CreateProjectModal.tsx |
| 298 | +│ │ └── RepoSelector.tsx |
| 299 | +│ ├── dashboard/ |
| 300 | +│ │ └── QuickActions.tsx |
| 301 | +│ └── theme/ |
| 302 | +│ └── ThemeSwitcher.tsx |
| 303 | +├── services/ |
| 304 | +│ ├── projects/ |
| 305 | +│ │ └── ProjectsService.ts |
| 306 | +│ └── github/ |
| 307 | +│ └── GitHubService.ts |
| 308 | +└── types/ |
| 309 | + └── projects.ts |
| 310 | +``` |
| 311 | + |
| 312 | +--- |
| 313 | + |
| 314 | +## Success Criteria |
| 315 | + |
| 316 | +- [ ] Sidebar shows user's projects |
| 317 | +- [ ] Quick action cards on dashboard |
| 318 | +- [ ] Theme switches between arcade/enterprise |
| 319 | +- [ ] GitHub repos populate in dropdown |
| 320 | +- [ ] New project creates repo and saves to Supabase |
| 321 | +- [ ] Projects persist across sessions |
| 322 | +- [ ] Mobile responsive (sidebar collapses) |
| 323 | + |
| 324 | +--- |
| 325 | + |
| 326 | +## Implementation Order |
| 327 | + |
| 328 | +1. **SidebarLayout + TopBar** - Foundation |
| 329 | +2. **Theme system** - CSS variables + switcher |
| 330 | +3. **Database migration** - Projects + builds tables |
| 331 | +4. **ProjectsService** - CRUD operations |
| 332 | +5. **Sidebar + ProjectList** - Display projects |
| 333 | +6. **CreateProjectModal + RepoSelector** - GitHub integration |
| 334 | +7. **Dashboard QuickActions** - Entry points |
| 335 | +8. **Polish** - Loading states, empty states, errors |
0 commit comments