@hienlh/ppm 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. package/.claude/agent-memory/tester/MEMORY.md +3 -0
  2. package/.claude/agent-memory/tester/project-ppm-test-conventions.md +32 -0
  3. package/.env.example +1 -0
  4. package/.github/workflows/release.yml +46 -0
  5. package/README.md +349 -0
  6. package/bun.lock +1217 -0
  7. package/components.json +21 -0
  8. package/docs/code-standards.md +574 -0
  9. package/docs/codebase-summary.md +294 -0
  10. package/docs/deployment-guide.md +631 -0
  11. package/docs/design-guidelines.md +661 -0
  12. package/docs/project-overview-pdr.md +142 -0
  13. package/docs/project-roadmap.md +400 -0
  14. package/docs/system-architecture.md +459 -0
  15. package/package.json +68 -0
  16. package/plans/260314-2009-ppm-implementation/phase-01-project-skeleton.md +81 -0
  17. package/plans/260314-2009-ppm-implementation/phase-02-backend-core.md +148 -0
  18. package/plans/260314-2009-ppm-implementation/phase-03-frontend-shell.md +256 -0
  19. package/plans/260314-2009-ppm-implementation/phase-04-file-explorer-editor.md +120 -0
  20. package/plans/260314-2009-ppm-implementation/phase-05-web-terminal.md +174 -0
  21. package/plans/260314-2009-ppm-implementation/phase-06-git-integration.md +244 -0
  22. package/plans/260314-2009-ppm-implementation/phase-07-ai-chat.md +242 -0
  23. package/plans/260314-2009-ppm-implementation/phase-08-cli-commands.md +143 -0
  24. package/plans/260314-2009-ppm-implementation/phase-09-pwa-build-deploy.md +209 -0
  25. package/plans/260314-2009-ppm-implementation/phase-10-testing.md +311 -0
  26. package/plans/260314-2009-ppm-implementation/plan.md +202 -0
  27. package/plans/260315-0356-project-scoped-api-refactor/phase-01-backend-project-router.md +145 -0
  28. package/plans/260315-0356-project-scoped-api-refactor/phase-02-frontend-api-migration.md +107 -0
  29. package/plans/260315-0356-project-scoped-api-refactor/phase-03-per-project-tabs.md +100 -0
  30. package/plans/260315-0356-project-scoped-api-refactor/phase-04-websocket-migration.md +66 -0
  31. package/plans/260315-0356-project-scoped-api-refactor/plan.md +87 -0
  32. package/plans/reports/brainstorm-260314-1938-final-techstack.md +342 -0
  33. package/plans/reports/docs-manager-260315-1314-documentation-creation.md +386 -0
  34. package/plans/reports/fullstack-developer-260314-2252-phase-02-backend-core.md +57 -0
  35. package/plans/reports/fullstack-developer-260314-2253-phase-03-frontend-shell.md +70 -0
  36. package/plans/reports/fullstack-developer-260314-2300-phase-04-05-file-api-terminal-ws.md +49 -0
  37. package/plans/reports/fullstack-developer-260314-2300-phase-04-05-file-explorer-editor-terminal.md +52 -0
  38. package/plans/reports/fullstack-developer-260314-2307-ai-chat-phase7.md +58 -0
  39. package/plans/reports/fullstack-developer-260314-2307-phase-06-git-integration.md +33 -0
  40. package/plans/reports/research-260314-1911-ppm-tech-stack.md +318 -0
  41. package/plans/reports/research-260314-1930-claude-code-integration.md +293 -0
  42. package/plans/reports/researcher-260314-2232-node-pty-bun-crash-analysis.md +305 -0
  43. package/plans/reports/researcher-260314-2232-ui-style.md +942 -0
  44. package/plans/reports/researcher-260315-0300-opcode-claude-interaction.md +745 -0
  45. package/plans/reports/researcher-260315-0303-opcode-deep-analysis.md +742 -0
  46. package/plans/reports/researcher-260315-0305-claude-agent-sdk-github-research.md +423 -0
  47. package/plans/reports/tester-260314-2053-initial-test-suite.md +81 -0
  48. package/ppm.example.yaml +14 -0
  49. package/repomix-output.xml +23745 -0
  50. package/scripts/build.ts +13 -0
  51. package/src/cli/commands/chat-cmd.ts +259 -0
  52. package/src/cli/commands/config-cmd.ts +121 -0
  53. package/src/cli/commands/git-cmd.ts +315 -0
  54. package/src/cli/commands/init.ts +57 -0
  55. package/src/cli/commands/open.ts +19 -0
  56. package/src/cli/commands/projects.ts +100 -0
  57. package/src/cli/commands/start.ts +3 -0
  58. package/src/cli/commands/stop.ts +33 -0
  59. package/src/cli/utils/project-resolver.ts +27 -0
  60. package/src/index.ts +59 -0
  61. package/src/providers/claude-agent-sdk.ts +499 -0
  62. package/src/providers/claude-binary-finder.ts +256 -0
  63. package/src/providers/claude-code-cli.ts +413 -0
  64. package/src/providers/claude-process-registry.ts +106 -0
  65. package/src/providers/mock-provider.ts +171 -0
  66. package/src/providers/provider.interface.ts +10 -0
  67. package/src/providers/registry.ts +45 -0
  68. package/src/server/helpers/resolve-project.ts +22 -0
  69. package/src/server/index.ts +181 -0
  70. package/src/server/middleware/auth.ts +30 -0
  71. package/src/server/routes/chat.ts +153 -0
  72. package/src/server/routes/files.ts +168 -0
  73. package/src/server/routes/git.ts +261 -0
  74. package/src/server/routes/project-scoped.ts +27 -0
  75. package/src/server/routes/projects.ts +57 -0
  76. package/src/server/routes/static.ts +26 -0
  77. package/src/server/ws/chat.ts +130 -0
  78. package/src/server/ws/terminal.ts +89 -0
  79. package/src/services/chat.service.ts +110 -0
  80. package/src/services/claude-usage.service.ts +113 -0
  81. package/src/services/config.service.ts +90 -0
  82. package/src/services/file.service.ts +261 -0
  83. package/src/services/git-dirs.service.ts +112 -0
  84. package/src/services/git.service.ts +372 -0
  85. package/src/services/project.service.ts +107 -0
  86. package/src/services/slash-items.service.ts +184 -0
  87. package/src/services/terminal.service.ts +212 -0
  88. package/src/types/api.ts +37 -0
  89. package/src/types/chat.ts +92 -0
  90. package/src/types/config.ts +41 -0
  91. package/src/types/git.ts +50 -0
  92. package/src/types/project.ts +18 -0
  93. package/src/types/terminal.ts +20 -0
  94. package/src/web/app.tsx +168 -0
  95. package/src/web/components/auth/login-screen.tsx +88 -0
  96. package/src/web/components/chat/attachment-chips.tsx +55 -0
  97. package/src/web/components/chat/chat-placeholder.tsx +10 -0
  98. package/src/web/components/chat/chat-tab.tsx +301 -0
  99. package/src/web/components/chat/file-picker.tsx +126 -0
  100. package/src/web/components/chat/message-input.tsx +420 -0
  101. package/src/web/components/chat/message-list.tsx +838 -0
  102. package/src/web/components/chat/session-picker.tsx +139 -0
  103. package/src/web/components/chat/slash-command-picker.tsx +135 -0
  104. package/src/web/components/chat/usage-badge.tsx +186 -0
  105. package/src/web/components/editor/code-editor.tsx +329 -0
  106. package/src/web/components/editor/diff-viewer.tsx +276 -0
  107. package/src/web/components/editor/editor-placeholder.tsx +10 -0
  108. package/src/web/components/explorer/file-actions.tsx +191 -0
  109. package/src/web/components/explorer/file-tree.tsx +298 -0
  110. package/src/web/components/git/git-graph.tsx +727 -0
  111. package/src/web/components/git/git-placeholder.tsx +55 -0
  112. package/src/web/components/git/git-status-panel.tsx +850 -0
  113. package/src/web/components/layout/mobile-drawer.tsx +137 -0
  114. package/src/web/components/layout/mobile-nav.tsx +103 -0
  115. package/src/web/components/layout/sidebar.tsx +90 -0
  116. package/src/web/components/layout/tab-bar.tsx +152 -0
  117. package/src/web/components/layout/tab-content.tsx +85 -0
  118. package/src/web/components/projects/dir-suggest.tsx +152 -0
  119. package/src/web/components/projects/project-list.tsx +187 -0
  120. package/src/web/components/settings/settings-tab.tsx +57 -0
  121. package/src/web/components/terminal/terminal-placeholder.tsx +10 -0
  122. package/src/web/components/terminal/terminal-tab.tsx +133 -0
  123. package/src/web/components/ui/button.tsx +64 -0
  124. package/src/web/components/ui/context-menu.tsx +250 -0
  125. package/src/web/components/ui/dialog.tsx +156 -0
  126. package/src/web/components/ui/dropdown-menu.tsx +257 -0
  127. package/src/web/components/ui/input.tsx +21 -0
  128. package/src/web/components/ui/scroll-area.tsx +56 -0
  129. package/src/web/components/ui/separator.tsx +26 -0
  130. package/src/web/components/ui/sonner.tsx +40 -0
  131. package/src/web/components/ui/tabs.tsx +91 -0
  132. package/src/web/components/ui/tooltip.tsx +57 -0
  133. package/src/web/hooks/use-chat.ts +420 -0
  134. package/src/web/hooks/use-terminal.ts +182 -0
  135. package/src/web/hooks/use-url-sync.ts +66 -0
  136. package/src/web/hooks/use-websocket.ts +48 -0
  137. package/src/web/index.html +16 -0
  138. package/src/web/lib/api-client.ts +90 -0
  139. package/src/web/lib/file-support.ts +68 -0
  140. package/src/web/lib/utils.ts +6 -0
  141. package/src/web/lib/ws-client.ts +100 -0
  142. package/src/web/main.tsx +10 -0
  143. package/src/web/public/icon-192.svg +5 -0
  144. package/src/web/public/icon-512.svg +5 -0
  145. package/src/web/stores/file-store.ts +81 -0
  146. package/src/web/stores/project-store.ts +50 -0
  147. package/src/web/stores/settings-store.ts +65 -0
  148. package/src/web/stores/tab-store.ts +187 -0
  149. package/src/web/styles/globals.css +227 -0
  150. package/src/web/vite-env.d.ts +1 -0
  151. package/tests/integration/api/chat-routes.test.ts +95 -0
  152. package/tests/integration/claude-agent-sdk-integration.test.ts +228 -0
  153. package/tests/integration/ws/chat-websocket.test.ts +312 -0
  154. package/tests/test-setup.ts +5 -0
  155. package/tests/unit/providers/claude-agent-sdk.test.ts +339 -0
  156. package/tests/unit/providers/mock-provider.test.ts +143 -0
  157. package/tests/unit/services/chat-service.test.ts +100 -0
  158. package/tsconfig.json +32 -0
  159. package/vite.config.ts +62 -0
@@ -0,0 +1,661 @@
1
+ # PPM Design Guidelines
2
+
3
+ ## Design Philosophy
4
+
5
+ **PPM** prioritizes **clarity, efficiency, and accessibility** over decoration. The UI should feel lightweight, responsive, and get out of the way of actual development work.
6
+
7
+ **Core Principles:**
8
+ 1. **Mobile-first** — Design for small screens, scale up
9
+ 2. **Dark-mode default** — Reduce eye strain during long coding sessions
10
+ 3. **Minimal chrome** — Maximize editor/terminal space
11
+ 4. **Keyboard-friendly** — Power users prefer shortcuts
12
+ 5. **Accessible** — WCAG 2.1 AA compliance
13
+ 6. **Consistent** — Reuse patterns across features
14
+
15
+ ---
16
+
17
+ ## UI Framework Stack
18
+
19
+ ### Tailwind CSS 4.2
20
+ - Utility-first CSS framework
21
+ - Dark mode support (class-based: `dark:` prefix)
22
+ - Responsive breakpoints (`sm:`, `md:`, `lg:`, `xl:`, `2xl:`)
23
+ - Custom configuration in `tailwind.config.ts`
24
+
25
+ ### Radix UI 1.4.3
26
+ - Unstyled, accessible components
27
+ - Provides accessibility (ARIA, keyboard navigation)
28
+ - Examples: Dialog, Dropdown, Tooltip, Tabs
29
+ - No CSS imports; styled with Tailwind
30
+
31
+ ### shadcn/ui (New York Style)
32
+ - Pre-built Radix components with Tailwind styling
33
+ - Copy-paste component library (not npm-installed)
34
+ - Located in `src/web/components/ui/`
35
+ - Customizable and maintainable
36
+
37
+ ### Lucide Icons
38
+ - Clean, consistent icon set
39
+ - 600+ icons available
40
+ - Usage: `import { FileIcon, FolderIcon } from "lucide-react"`
41
+
42
+ ---
43
+
44
+ ## Color Scheme
45
+
46
+ ### Light Mode
47
+
48
+ | Purpose | Color | Tailwind | Usage |
49
+ |---------|-------|----------|-------|
50
+ | Background | #FFFFFF | `bg-white` | Page background |
51
+ | Foreground | #000000 | `text-black` | Primary text |
52
+ | Sidebar | #F3F4F6 | `bg-gray-100` | Navigation panel |
53
+ | Border | #E5E7EB | `border-gray-200` | Dividers, edges |
54
+ | Accent | #3B82F6 | `bg-blue-500` | Links, active states |
55
+ | Hover | #DBEAFE | `hover:bg-blue-100` | Interactive states |
56
+ | Danger | #EF4444 | `bg-red-500` | Destructive actions |
57
+ | Success | #10B981 | `bg-green-500` | Positive feedback |
58
+
59
+ ### Dark Mode
60
+
61
+ | Purpose | Color | Tailwind | Usage |
62
+ |---------|-------|----------|-------|
63
+ | Background | #0F172A | `dark:bg-slate-950` | Page background |
64
+ | Foreground | #F1F5F9 | `dark:text-slate-100` | Primary text |
65
+ | Sidebar | #1E293B | `dark:bg-slate-800` | Navigation panel |
66
+ | Border | #334155 | `dark:border-slate-700` | Dividers, edges |
67
+ | Accent | #3B82F6 | `dark:bg-blue-500` | Links, active states |
68
+ | Hover | #1E3A8A | `dark:hover:bg-blue-900` | Interactive states |
69
+ | Danger | #EF4444 | `dark:bg-red-600` | Destructive actions |
70
+ | Success | #10B981 | `dark:bg-green-600` | Positive feedback |
71
+
72
+ ### Implementation
73
+
74
+ ```tsx
75
+ // Auto-detected based on system preference
76
+ // Or manually controlled via SettingsStore
77
+
78
+ // Dark mode uses: <html class="dark">
79
+ // Tailwind applies dark: prefix styles
80
+
81
+ // Example component
82
+ <button className="bg-white dark:bg-slate-800 text-black dark:text-white">
83
+ Click me
84
+ </button>
85
+ ```
86
+
87
+ ---
88
+
89
+ ## Typography
90
+
91
+ ### Font Stack
92
+
93
+ ```css
94
+ /* tailwind.config.ts */
95
+ theme: {
96
+ fontFamily: {
97
+ sans: ['Inter', 'system-ui', 'sans-serif'],
98
+ mono: ['JetBrains Mono', 'Monaco', 'Courier New', 'monospace'],
99
+ }
100
+ }
101
+ ```
102
+
103
+ ### Type Scale
104
+
105
+ | Usage | Size | Line Height | Weight |
106
+ |-------|------|-------------|--------|
107
+ | H1 (Title) | 32px | 1.2 | 700 (bold) |
108
+ | H2 (Heading) | 24px | 1.3 | 600 (semibold) |
109
+ | H3 (Subheading) | 20px | 1.4 | 600 (semibold) |
110
+ | Body | 14px | 1.5 | 400 (regular) |
111
+ | Small | 12px | 1.4 | 400 (regular) |
112
+ | Code | 13px | 1.6 | 400 (monospace) |
113
+
114
+ ### Example
115
+
116
+ ```tsx
117
+ // Heading
118
+ <h1 className="text-2xl font-bold">PPM</h1>
119
+
120
+ // Body text
121
+ <p className="text-sm text-gray-600 dark:text-gray-400">
122
+ Descriptive text
123
+ </p>
124
+
125
+ // Code/terminal text
126
+ <code className="font-mono text-xs bg-gray-100 dark:bg-gray-800 px-2 py-1 rounded">
127
+ npm install
128
+ </code>
129
+ ```
130
+
131
+ ---
132
+
133
+ ## Component Patterns
134
+
135
+ ### Button Component
136
+
137
+ ```tsx
138
+ // Base button from shadcn/ui
139
+ import { Button } from "@/components/ui/button";
140
+
141
+ // Variants
142
+ <Button>Primary</Button>
143
+ <Button variant="outline">Outline</Button>
144
+ <Button variant="ghost">Ghost</Button>
145
+ <Button variant="destructive">Delete</Button>
146
+ <Button disabled>Disabled</Button>
147
+
148
+ // Sizes
149
+ <Button size="sm">Small</Button>
150
+ <Button size="default">Default</Button>
151
+ <Button size="lg">Large</Button>
152
+ ```
153
+
154
+ ### Input Component
155
+
156
+ ```tsx
157
+ import { Input } from "@/components/ui/input";
158
+
159
+ <Input
160
+ type="text"
161
+ placeholder="Enter search..."
162
+ className="h-9 rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
163
+ />
164
+ ```
165
+
166
+ ### Dialog Component
167
+
168
+ ```tsx
169
+ import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog";
170
+
171
+ <Dialog open={isOpen} onOpenChange={setIsOpen}>
172
+ <DialogContent>
173
+ <DialogHeader>
174
+ <DialogTitle>Confirm Action</DialogTitle>
175
+ </DialogHeader>
176
+ <p>Are you sure?</p>
177
+ </DialogContent>
178
+ </Dialog>
179
+ ```
180
+
181
+ ### Dropdown Menu
182
+
183
+ ```tsx
184
+ import {
185
+ DropdownMenu,
186
+ DropdownMenuContent,
187
+ DropdownMenuItem,
188
+ DropdownMenuTrigger,
189
+ } from "@/components/ui/dropdown-menu";
190
+
191
+ <DropdownMenu>
192
+ <DropdownMenuTrigger asChild>
193
+ <Button variant="ghost" size="sm">•••</Button>
194
+ </DropdownMenuTrigger>
195
+ <DropdownMenuContent>
196
+ <DropdownMenuItem>Edit</DropdownMenuItem>
197
+ <DropdownMenuItem>Delete</DropdownMenuItem>
198
+ </DropdownMenuContent>
199
+ </DropdownMenu>
200
+ ```
201
+
202
+ ---
203
+
204
+ ## Layout Structure
205
+
206
+ ### Desktop Layout
207
+
208
+ ```
209
+ ┌─────────────────────────────────────────────────────────┐
210
+ │ Sidebar (300px) │ MainArea │
211
+ ├──────────────────┼─────────────────────────────────────┤
212
+ │ Project Selector │ ┌───────────────────────────────────┐│
213
+ ├──────────────────┤ │ TabBar (Chat | Editor | Git | … )││
214
+ │ File Explorer │ ├───────────────────────────────────┤│
215
+ │ │ │ Tab Content (varies) ││
216
+ │ • src/ │ │ CodeEditor, ChatTab, etc. ││
217
+ │ - main.ts │ │ ││
218
+ │ - utils.ts │ │ ││
219
+ │ │ │ ││
220
+ │ • dist/ │ │ (Fills remaining space) ││
221
+ │ │ │ ││
222
+ │ │ │ ││
223
+ │ │ └───────────────────────────────────┘│
224
+ └──────────────────┴─────────────────────────────────────┘
225
+ ```
226
+
227
+ **Sidebar:** 300px fixed, scrollable, dark background
228
+ **MainArea:** Flex 1, contains TabBar + content
229
+ **TabBar:** Horizontal tabs (chat, editor, git, terminal, settings)
230
+ **Content:** Flex, fills remaining space, scrollable if needed
231
+
232
+ ### Mobile Layout
233
+
234
+ ```
235
+ ┌─────────────────────────────────────┐
236
+ │ ☰ | Project Selector | ⚙️ │
237
+ ├─────────────────────────────────────┤
238
+ │ MainArea (full width) │
239
+ │ │
240
+ │ ChatTab / EditorTab / etc. │
241
+ │ │
242
+ │ (Sidebar hidden, accessible via ☰) │
243
+ ├─────────────────────────────────────┤
244
+ │ TabBar (bottom, horizontal scroll) │
245
+ │ [Chat] [Editor] [Git] [Terminal] │
246
+ └─────────────────────────────────────┘
247
+ ```
248
+
249
+ **Header:** Project selector + hamburger menu
250
+ **Content:** Full-width tab content
251
+ **TabBar:** Bottom navigation (mobile-friendly)
252
+ **Sidebar:** Slide-in drawer (MobileDrawer component)
253
+
254
+ ### Responsive Breakpoints
255
+
256
+ ```typescript
257
+ // tailwind.config.ts
258
+ screens: {
259
+ sm: '640px', // Mobile
260
+ md: '768px', // Tablet
261
+ lg: '1024px', // Desktop
262
+ xl: '1280px', // Wide desktop
263
+ '2xl': '1536px' // Ultra-wide
264
+ }
265
+ ```
266
+
267
+ **Rules:**
268
+ - `sm:` and below — Mobile optimizations
269
+ - `md:` and above — Show sidebar
270
+ - `lg:` and above — Full-width optimizations
271
+
272
+ ---
273
+
274
+ ## Component Library Usage
275
+
276
+ ### File Tree Component
277
+
278
+ ```tsx
279
+ // src/web/components/explorer/file-tree.tsx
280
+ // Shows directory structure with expand/collapse
281
+
282
+ <FileTree
283
+ root={project.root}
284
+ onSelect={(file) => openFile(file)}
285
+ onContextMenu={(file) => showMenu(file)}
286
+ />
287
+
288
+ // Features:
289
+ // - Lazy load directories (expand on click)
290
+ // - File icons based on extension
291
+ // - Highlight current file
292
+ // - Right-click context menu (create, delete, etc.)
293
+ ```
294
+
295
+ ### Code Editor
296
+
297
+ ```tsx
298
+ // src/web/components/editor/code-editor.tsx
299
+ // CodeMirror 6 integration with syntax highlighting
300
+
301
+ <CodeEditor
302
+ language="javascript"
303
+ value={fileContent}
304
+ onChange={setFileContent}
305
+ theme="dark"
306
+ readOnly={false}
307
+ />
308
+
309
+ // Features:
310
+ // - 50+ language support
311
+ // - Real-time syntax highlighting
312
+ // - Line numbers, code folding
313
+ // - Find/replace (Ctrl+H)
314
+ ```
315
+
316
+ ### Terminal Component
317
+
318
+ ```tsx
319
+ // src/web/components/terminal/terminal-tab.tsx
320
+ // xterm.js integration
321
+
322
+ <TerminalTab projectName={project.name} />
323
+
324
+ // Features:
325
+ // - Full terminal emulation (bash/zsh)
326
+ // - 256 color support
327
+ // - Mouse support (click, scroll)
328
+ // - Resize handling
329
+ // - Copy/paste from clipboard
330
+ ```
331
+
332
+ ### Chat Component
333
+
334
+ ```tsx
335
+ // src/web/components/chat/chat-tab.tsx
336
+ // Message list + input with file attachments
337
+
338
+ <ChatTab sessionId={sessionId} />
339
+
340
+ // Features:
341
+ // - Streaming message display
342
+ // - Tool use cards (file_read, git commands)
343
+ // - File attachment previews
344
+ // - Slash command autocomplete
345
+ // - Session switcher
346
+ ```
347
+
348
+ ### Git Status Panel
349
+
350
+ ```tsx
351
+ // src/web/components/git/git-status-panel.tsx
352
+ // Git status with staging UI
353
+
354
+ <GitStatusPanel projectName={project.name} />
355
+
356
+ // Features:
357
+ // - Staged/unstaged/untracked file lists
358
+ // - Stage/unstage buttons
359
+ // - Commit message input
360
+ // - Commit graph (Mermaid)
361
+ ```
362
+
363
+ ---
364
+
365
+ ## Dark Mode Implementation
366
+
367
+ ### Automatic Detection
368
+
369
+ ```tsx
370
+ // src/web/app.tsx
371
+ // Detect system preference
372
+
373
+ useEffect(() => {
374
+ const preference = window.matchMedia('(prefers-color-scheme: dark)');
375
+ const isDark = preference.matches;
376
+ setTheme(isDark ? 'dark' : 'light');
377
+ }, []);
378
+ ```
379
+
380
+ ### Manual Override
381
+
382
+ ```tsx
383
+ // Settings tab allows user to choose:
384
+ // - System (follow OS preference)
385
+ // - Dark (always dark)
386
+ // - Light (always light)
387
+
388
+ // Implementation via next-themes
389
+ <ThemeProvider attribute="class" defaultTheme="system">
390
+ <App />
391
+ </ThemeProvider>
392
+ ```
393
+
394
+ ### CSS in Dark Mode
395
+
396
+ ```tsx
397
+ // Tailwind dark: prefix
398
+ <div className="bg-white dark:bg-slate-950 text-black dark:text-white">
399
+ Content adapts to theme
400
+ </div>
401
+ ```
402
+
403
+ ---
404
+
405
+ ## Responsive Design
406
+
407
+ ### Mobile-First CSS
408
+
409
+ Start with mobile styles, add complexity for larger screens:
410
+
411
+ ```css
412
+ /* Mobile-first */
413
+ .sidebar {
414
+ display: none; /* Hidden on mobile */
415
+ }
416
+
417
+ /* Tablet and up */
418
+ @media (min-width: 768px) {
419
+ .sidebar {
420
+ display: block;
421
+ width: 300px;
422
+ }
423
+ }
424
+ ```
425
+
426
+ **Or in Tailwind:**
427
+ ```tsx
428
+ <div className="hidden md:block w-64">
429
+ Sidebar (hidden on mobile, shown on md+)
430
+ </div>
431
+ ```
432
+
433
+ ### Touch-Friendly Sizes
434
+
435
+ - **Button height:** 44px minimum (iOS guideline)
436
+ - **Touch target:** 44×44px or larger
437
+ - **Spacing:** 16px minimum between interactive elements
438
+
439
+ ```tsx
440
+ // Good: Touch-friendly
441
+ <button className="px-4 py-3 rounded-lg">Click</button>
442
+
443
+ // Avoid: Too small
444
+ <button className="px-2 py-1">Click</button>
445
+ ```
446
+
447
+ ### Viewport Configuration
448
+
449
+ ```html
450
+ <!-- public/index.html -->
451
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
452
+ ```
453
+
454
+ ---
455
+
456
+ ## PWA Considerations
457
+
458
+ ### Web App Manifest
459
+
460
+ ```json
461
+ {
462
+ "name": "Personal Project Manager",
463
+ "short_name": "PPM",
464
+ "description": "Mobile-first web IDE for managing code projects",
465
+ "start_url": "/",
466
+ "scope": "/",
467
+ "display": "standalone",
468
+ "theme_color": "#0F172A",
469
+ "background_color": "#FFFFFF",
470
+ "icons": [
471
+ {
472
+ "src": "/icons/icon-192.png",
473
+ "sizes": "192x192",
474
+ "type": "image/png",
475
+ "purpose": "any"
476
+ }
477
+ ]
478
+ }
479
+ ```
480
+
481
+ ### Service Worker
482
+
483
+ - Cache static assets (CSS, JS, images)
484
+ - Offline fallback (HTML, basic UI)
485
+ - Background sync (planned for v3)
486
+
487
+ ### Installation Prompt
488
+
489
+ - Browser shows "Add to Home Screen" on first visit
490
+ - Users can install as standalone app
491
+ - App opens fullscreen without browser chrome
492
+
493
+ ---
494
+
495
+ ## Animation & Micro-interactions
496
+
497
+ ### Smooth Transitions
498
+
499
+ ```css
500
+ /* Fade in content */
501
+ .fade-in {
502
+ animation: fadeIn 0.3s ease-in;
503
+ }
504
+
505
+ @keyframes fadeIn {
506
+ from { opacity: 0; }
507
+ to { opacity: 1; }
508
+ }
509
+ ```
510
+
511
+ ### Button Hover States
512
+
513
+ ```tsx
514
+ <button className="bg-blue-500 hover:bg-blue-600 active:bg-blue-700 transition-colors">
515
+ Click me
516
+ </button>
517
+ ```
518
+
519
+ ### Loading Spinner
520
+
521
+ ```tsx
522
+ <Spinner className="animate-spin w-5 h-5" />
523
+ ```
524
+
525
+ ### Toast Notifications
526
+
527
+ ```tsx
528
+ // sonner library for notifications
529
+ import { toast } from "sonner";
530
+
531
+ toast.success("File saved!");
532
+ toast.error("Failed to commit");
533
+ toast.loading("Pushing...");
534
+ ```
535
+
536
+ ---
537
+
538
+ ## Accessibility
539
+
540
+ ### Keyboard Navigation
541
+
542
+ - **Tab order:** Logical flow (left-to-right, top-to-bottom)
543
+ - **Focus visible:** Clear focus indicator on interactive elements
544
+ - **Keyboard shortcuts:** Alt+S (save), Ctrl+K (command palette), etc.
545
+
546
+ ```tsx
547
+ // Good: Focus visible
548
+ <button className="focus-visible:ring-2 focus-visible:ring-blue-500">
549
+ Click me
550
+ </button>
551
+ ```
552
+
553
+ ### Color Contrast
554
+
555
+ - **WCAG AA:** 4.5:1 for normal text, 3:1 for large text
556
+ - **Avoid:** Color-only indicators (use icons + text)
557
+
558
+ ```tsx
559
+ // Good: Icon + text + color
560
+ <span className="text-red-600">
561
+ <ErrorIcon className="inline" /> Error occurred
562
+ </span>
563
+
564
+ // Avoid: Color only
565
+ <span className="text-red-600">Error</span>
566
+ ```
567
+
568
+ ### ARIA Labels
569
+
570
+ ```tsx
571
+ // Good: Descriptive labels
572
+ <button aria-label="Delete file">
573
+ <TrashIcon />
574
+ </button>
575
+
576
+ <input
577
+ type="text"
578
+ aria-label="Search projects"
579
+ placeholder="Search..."
580
+ />
581
+ ```
582
+
583
+ ### Semantic HTML
584
+
585
+ ```tsx
586
+ // Good: Semantic structure
587
+ <nav>Navigation here</nav>
588
+ <main>Main content</main>
589
+ <aside>Sidebar</aside>
590
+ <footer>Footer</footer>
591
+
592
+ // Avoid: Generic divs
593
+ <div>Navigation here</div>
594
+ <div>Main content</div>
595
+ ```
596
+
597
+ ---
598
+
599
+ ## Visual Hierarchy
600
+
601
+ ### Size & Weight
602
+
603
+ Larger, bolder elements draw attention first:
604
+
605
+ ```tsx
606
+ // Page title (largest, boldest)
607
+ <h1 className="text-3xl font-bold">Project Name</h1>
608
+
609
+ // Section heading (medium)
610
+ <h2 className="text-xl font-semibold">Files</h2>
611
+
612
+ // Regular text (small, normal weight)
613
+ <p className="text-sm font-normal">3 files</p>
614
+ ```
615
+
616
+ ### Spacing & Whitespace
617
+
618
+ - **Compact:** 8px gutters between elements
619
+ - **Normal:** 16px padding inside containers
620
+ - **Generous:** 24px+ between major sections
621
+
622
+ ```tsx
623
+ // Compact list
624
+ <ul className="space-y-1">
625
+ <li>Item 1</li>
626
+ <li>Item 2</li>
627
+ </ul>
628
+
629
+ // Generous spacing
630
+ <section className="mb-8">
631
+ <h2 className="mb-4">Title</h2>
632
+ <p className="mb-4">Paragraph 1</p>
633
+ <p>Paragraph 2</p>
634
+ </section>
635
+ ```
636
+
637
+ ---
638
+
639
+ ## Icon Guidelines
640
+
641
+ **Lucide Icons** — Consistent 24px icons for UI
642
+
643
+ ### Usage Patterns
644
+
645
+ - **Navigation:** Folder, File, Terminal, Settings icons
646
+ - **Actions:** Plus (add), Trash (delete), Check (confirm)
647
+ - **Status:** CheckCircle (success), XCircle (error), AlertCircle (warning)
648
+ - **Modifiers:** ChevronRight (expand), X (close)
649
+
650
+ ```tsx
651
+ import { FileIcon, FolderIcon, TrashIcon } from "lucide-react";
652
+
653
+ <FileIcon className="w-5 h-5 text-gray-600" />
654
+ ```
655
+
656
+ ### Size Guidelines
657
+
658
+ - **UI elements:** 16px–20px (inline, labels)
659
+ - **Buttons:** 20px–24px (primary actions)
660
+ - **Headers:** 32px+ (large, prominent)
661
+