popeye-cli 1.0.1 → 1.2.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 (216) hide show
  1. package/.env.example +24 -1
  2. package/CONTRIBUTING.md +275 -0
  3. package/OPEN_SOURCE_MANIFESTO.md +172 -0
  4. package/README.md +832 -123
  5. package/dist/adapters/claude.d.ts +19 -4
  6. package/dist/adapters/claude.d.ts.map +1 -1
  7. package/dist/adapters/claude.js +908 -42
  8. package/dist/adapters/claude.js.map +1 -1
  9. package/dist/adapters/gemini.d.ts +55 -0
  10. package/dist/adapters/gemini.d.ts.map +1 -0
  11. package/dist/adapters/gemini.js +318 -0
  12. package/dist/adapters/gemini.js.map +1 -0
  13. package/dist/adapters/grok.d.ts +73 -0
  14. package/dist/adapters/grok.d.ts.map +1 -0
  15. package/dist/adapters/grok.js +430 -0
  16. package/dist/adapters/grok.js.map +1 -0
  17. package/dist/adapters/openai.d.ts +1 -1
  18. package/dist/adapters/openai.d.ts.map +1 -1
  19. package/dist/adapters/openai.js +47 -8
  20. package/dist/adapters/openai.js.map +1 -1
  21. package/dist/auth/claude.d.ts +11 -9
  22. package/dist/auth/claude.d.ts.map +1 -1
  23. package/dist/auth/claude.js +107 -71
  24. package/dist/auth/claude.js.map +1 -1
  25. package/dist/auth/gemini.d.ts +58 -0
  26. package/dist/auth/gemini.d.ts.map +1 -0
  27. package/dist/auth/gemini.js +172 -0
  28. package/dist/auth/gemini.js.map +1 -0
  29. package/dist/auth/grok.d.ts +73 -0
  30. package/dist/auth/grok.d.ts.map +1 -0
  31. package/dist/auth/grok.js +211 -0
  32. package/dist/auth/grok.js.map +1 -0
  33. package/dist/auth/index.d.ts +14 -7
  34. package/dist/auth/index.d.ts.map +1 -1
  35. package/dist/auth/index.js +41 -6
  36. package/dist/auth/index.js.map +1 -1
  37. package/dist/auth/keychain.d.ts +20 -7
  38. package/dist/auth/keychain.d.ts.map +1 -1
  39. package/dist/auth/keychain.js +85 -29
  40. package/dist/auth/keychain.js.map +1 -1
  41. package/dist/auth/openai.d.ts +2 -2
  42. package/dist/auth/openai.d.ts.map +1 -1
  43. package/dist/auth/openai.js +30 -32
  44. package/dist/auth/openai.js.map +1 -1
  45. package/dist/cli/commands/auth.d.ts +1 -1
  46. package/dist/cli/commands/auth.d.ts.map +1 -1
  47. package/dist/cli/commands/auth.js +79 -8
  48. package/dist/cli/commands/auth.js.map +1 -1
  49. package/dist/cli/commands/create.d.ts.map +1 -1
  50. package/dist/cli/commands/create.js +15 -4
  51. package/dist/cli/commands/create.js.map +1 -1
  52. package/dist/cli/interactive.d.ts.map +1 -1
  53. package/dist/cli/interactive.js +1494 -114
  54. package/dist/cli/interactive.js.map +1 -1
  55. package/dist/config/defaults.d.ts +9 -1
  56. package/dist/config/defaults.d.ts.map +1 -1
  57. package/dist/config/defaults.js +19 -2
  58. package/dist/config/defaults.js.map +1 -1
  59. package/dist/config/index.d.ts +19 -0
  60. package/dist/config/index.d.ts.map +1 -1
  61. package/dist/config/index.js +33 -1
  62. package/dist/config/index.js.map +1 -1
  63. package/dist/config/schema.d.ts +47 -0
  64. package/dist/config/schema.d.ts.map +1 -1
  65. package/dist/config/schema.js +29 -1
  66. package/dist/config/schema.js.map +1 -1
  67. package/dist/generators/fullstack.d.ts +32 -0
  68. package/dist/generators/fullstack.d.ts.map +1 -0
  69. package/dist/generators/fullstack.js +497 -0
  70. package/dist/generators/fullstack.js.map +1 -0
  71. package/dist/generators/index.d.ts +4 -3
  72. package/dist/generators/index.d.ts.map +1 -1
  73. package/dist/generators/index.js +15 -1
  74. package/dist/generators/index.js.map +1 -1
  75. package/dist/generators/python.d.ts +17 -1
  76. package/dist/generators/python.d.ts.map +1 -1
  77. package/dist/generators/python.js +34 -20
  78. package/dist/generators/python.js.map +1 -1
  79. package/dist/generators/templates/fullstack.d.ts +113 -0
  80. package/dist/generators/templates/fullstack.d.ts.map +1 -0
  81. package/dist/generators/templates/fullstack.js +1004 -0
  82. package/dist/generators/templates/fullstack.js.map +1 -0
  83. package/dist/generators/typescript.d.ts +19 -1
  84. package/dist/generators/typescript.d.ts.map +1 -1
  85. package/dist/generators/typescript.js +37 -20
  86. package/dist/generators/typescript.js.map +1 -1
  87. package/dist/state/index.d.ts +108 -0
  88. package/dist/state/index.d.ts.map +1 -1
  89. package/dist/state/index.js +551 -4
  90. package/dist/state/index.js.map +1 -1
  91. package/dist/state/registry.d.ts +52 -0
  92. package/dist/state/registry.d.ts.map +1 -0
  93. package/dist/state/registry.js +215 -0
  94. package/dist/state/registry.js.map +1 -0
  95. package/dist/types/cli.d.ts +8 -0
  96. package/dist/types/cli.d.ts.map +1 -1
  97. package/dist/types/cli.js.map +1 -1
  98. package/dist/types/consensus.d.ts +186 -4
  99. package/dist/types/consensus.d.ts.map +1 -1
  100. package/dist/types/consensus.js +35 -3
  101. package/dist/types/consensus.js.map +1 -1
  102. package/dist/types/project.d.ts +76 -0
  103. package/dist/types/project.d.ts.map +1 -1
  104. package/dist/types/project.js +1 -1
  105. package/dist/types/project.js.map +1 -1
  106. package/dist/types/workflow.d.ts +217 -16
  107. package/dist/types/workflow.d.ts.map +1 -1
  108. package/dist/types/workflow.js +40 -1
  109. package/dist/types/workflow.js.map +1 -1
  110. package/dist/workflow/auto-fix.d.ts +45 -0
  111. package/dist/workflow/auto-fix.d.ts.map +1 -0
  112. package/dist/workflow/auto-fix.js +274 -0
  113. package/dist/workflow/auto-fix.js.map +1 -0
  114. package/dist/workflow/consensus.d.ts +70 -2
  115. package/dist/workflow/consensus.d.ts.map +1 -1
  116. package/dist/workflow/consensus.js +872 -17
  117. package/dist/workflow/consensus.js.map +1 -1
  118. package/dist/workflow/execution-mode.d.ts +10 -4
  119. package/dist/workflow/execution-mode.d.ts.map +1 -1
  120. package/dist/workflow/execution-mode.js +547 -58
  121. package/dist/workflow/execution-mode.js.map +1 -1
  122. package/dist/workflow/index.d.ts +14 -2
  123. package/dist/workflow/index.d.ts.map +1 -1
  124. package/dist/workflow/index.js +69 -6
  125. package/dist/workflow/index.js.map +1 -1
  126. package/dist/workflow/milestone-workflow.d.ts +34 -0
  127. package/dist/workflow/milestone-workflow.d.ts.map +1 -0
  128. package/dist/workflow/milestone-workflow.js +414 -0
  129. package/dist/workflow/milestone-workflow.js.map +1 -0
  130. package/dist/workflow/plan-mode.d.ts +80 -3
  131. package/dist/workflow/plan-mode.d.ts.map +1 -1
  132. package/dist/workflow/plan-mode.js +767 -49
  133. package/dist/workflow/plan-mode.js.map +1 -1
  134. package/dist/workflow/plan-storage.d.ts +386 -0
  135. package/dist/workflow/plan-storage.d.ts.map +1 -0
  136. package/dist/workflow/plan-storage.js +878 -0
  137. package/dist/workflow/plan-storage.js.map +1 -0
  138. package/dist/workflow/project-verification.d.ts +37 -0
  139. package/dist/workflow/project-verification.d.ts.map +1 -0
  140. package/dist/workflow/project-verification.js +381 -0
  141. package/dist/workflow/project-verification.js.map +1 -0
  142. package/dist/workflow/task-workflow.d.ts +37 -0
  143. package/dist/workflow/task-workflow.d.ts.map +1 -0
  144. package/dist/workflow/task-workflow.js +386 -0
  145. package/dist/workflow/task-workflow.js.map +1 -0
  146. package/dist/workflow/test-runner.d.ts +9 -0
  147. package/dist/workflow/test-runner.d.ts.map +1 -1
  148. package/dist/workflow/test-runner.js +101 -5
  149. package/dist/workflow/test-runner.js.map +1 -1
  150. package/dist/workflow/ui-designer.d.ts +82 -0
  151. package/dist/workflow/ui-designer.d.ts.map +1 -0
  152. package/dist/workflow/ui-designer.js +234 -0
  153. package/dist/workflow/ui-designer.js.map +1 -0
  154. package/dist/workflow/ui-setup.d.ts +58 -0
  155. package/dist/workflow/ui-setup.d.ts.map +1 -0
  156. package/dist/workflow/ui-setup.js +685 -0
  157. package/dist/workflow/ui-setup.js.map +1 -0
  158. package/dist/workflow/ui-verification.d.ts +114 -0
  159. package/dist/workflow/ui-verification.d.ts.map +1 -0
  160. package/dist/workflow/ui-verification.js +258 -0
  161. package/dist/workflow/ui-verification.js.map +1 -0
  162. package/dist/workflow/workflow-logger.d.ts +110 -0
  163. package/dist/workflow/workflow-logger.d.ts.map +1 -0
  164. package/dist/workflow/workflow-logger.js +267 -0
  165. package/dist/workflow/workflow-logger.js.map +1 -0
  166. package/dist/workflow/workspace-manager.d.ts +342 -0
  167. package/dist/workflow/workspace-manager.d.ts.map +1 -0
  168. package/dist/workflow/workspace-manager.js +733 -0
  169. package/dist/workflow/workspace-manager.js.map +1 -0
  170. package/package.json +2 -2
  171. package/src/adapters/claude.ts +1067 -47
  172. package/src/adapters/gemini.ts +373 -0
  173. package/src/adapters/grok.ts +492 -0
  174. package/src/adapters/openai.ts +48 -9
  175. package/src/auth/claude.ts +120 -78
  176. package/src/auth/gemini.ts +207 -0
  177. package/src/auth/grok.ts +255 -0
  178. package/src/auth/index.ts +47 -9
  179. package/src/auth/keychain.ts +95 -28
  180. package/src/auth/openai.ts +29 -36
  181. package/src/cli/commands/auth.ts +89 -10
  182. package/src/cli/commands/create.ts +13 -4
  183. package/src/cli/interactive.ts +1774 -142
  184. package/src/config/defaults.ts +19 -2
  185. package/src/config/index.ts +36 -1
  186. package/src/config/schema.ts +30 -1
  187. package/src/generators/fullstack.ts +551 -0
  188. package/src/generators/index.ts +25 -1
  189. package/src/generators/python.ts +65 -20
  190. package/src/generators/templates/fullstack.ts +1047 -0
  191. package/src/generators/typescript.ts +69 -20
  192. package/src/state/index.ts +713 -4
  193. package/src/state/registry.ts +278 -0
  194. package/src/types/cli.ts +8 -0
  195. package/src/types/consensus.ts +197 -6
  196. package/src/types/project.ts +82 -1
  197. package/src/types/workflow.ts +90 -1
  198. package/src/workflow/auto-fix.ts +340 -0
  199. package/src/workflow/consensus.ts +1180 -16
  200. package/src/workflow/execution-mode.ts +673 -74
  201. package/src/workflow/index.ts +95 -6
  202. package/src/workflow/milestone-workflow.ts +576 -0
  203. package/src/workflow/plan-mode.ts +924 -50
  204. package/src/workflow/plan-storage.ts +1282 -0
  205. package/src/workflow/project-verification.ts +471 -0
  206. package/src/workflow/task-workflow.ts +528 -0
  207. package/src/workflow/test-runner.ts +120 -5
  208. package/src/workflow/ui-designer.ts +337 -0
  209. package/src/workflow/ui-setup.ts +797 -0
  210. package/src/workflow/ui-verification.ts +357 -0
  211. package/src/workflow/workflow-logger.ts +353 -0
  212. package/src/workflow/workspace-manager.ts +912 -0
  213. package/tests/config/config.test.ts +1 -1
  214. package/tests/types/consensus.test.ts +3 -3
  215. package/tests/workflow/plan-mode.test.ts +213 -0
  216. package/tests/workflow/test-runner.test.ts +5 -3
@@ -0,0 +1,1047 @@
1
+ /**
2
+ * Fullstack project templates
3
+ * Provides template files for fullstack monorepo project generation
4
+ */
5
+
6
+ import type { WorkspaceConfig } from '../../types/project.js';
7
+
8
+ /**
9
+ * Generate workspace.json content
10
+ *
11
+ * @param projectName - The project name
12
+ * @returns Workspace configuration object
13
+ */
14
+ export function generateWorkspaceConfig(projectName: string): WorkspaceConfig {
15
+ return {
16
+ version: '1.0',
17
+ apps: {
18
+ frontend: {
19
+ name: 'frontend',
20
+ path: 'apps/frontend',
21
+ language: 'typescript',
22
+ commands: {
23
+ test: 'npm test',
24
+ lint: 'npm run lint',
25
+ build: 'npm run build',
26
+ dev: 'npm run dev',
27
+ typecheck: 'npm run typecheck',
28
+ },
29
+ docker: {
30
+ dockerfile: 'apps/frontend/Dockerfile',
31
+ imageName: `${projectName}-frontend`,
32
+ context: 'apps/frontend',
33
+ },
34
+ uiSpec: '.popeye/ui-spec.json',
35
+ },
36
+ backend: {
37
+ name: 'backend',
38
+ path: 'apps/backend',
39
+ language: 'python',
40
+ commands: {
41
+ test: 'python -m pytest tests/ -v',
42
+ lint: 'ruff check src/ tests/',
43
+ build: 'pip install -e .',
44
+ dev: 'uvicorn src.backend.main:app --reload --port 8000',
45
+ },
46
+ docker: {
47
+ dockerfile: 'apps/backend/Dockerfile',
48
+ imageName: `${projectName}-backend`,
49
+ context: 'apps/backend',
50
+ },
51
+ contextRoots: ['src/backend', 'tests'],
52
+ },
53
+ },
54
+ commands: {
55
+ testAll: 'cd apps/backend && pytest && cd ../frontend && npm test',
56
+ lintAll: 'cd apps/backend && ruff check . && cd ../frontend && npm run lint',
57
+ buildAll: 'cd apps/backend && pip install -e . && cd ../frontend && npm run build',
58
+ devAll: 'docker-compose up',
59
+ },
60
+ docker: {
61
+ composePath: 'infra/docker/docker-compose.yml',
62
+ rootComposeSymlink: true,
63
+ },
64
+ };
65
+ }
66
+
67
+ /**
68
+ * Generate workspace.json file content as string
69
+ */
70
+ export function generateWorkspaceJson(projectName: string): string {
71
+ const config = generateWorkspaceConfig(projectName);
72
+ return JSON.stringify(config, null, 2);
73
+ }
74
+
75
+ /**
76
+ * Generate root docker-compose.yml for fullstack project
77
+ */
78
+ export function generateRootDockerCompose(projectName: string): string {
79
+ return `version: "3.8"
80
+
81
+ services:
82
+ frontend:
83
+ build:
84
+ context: ./apps/frontend
85
+ target: production
86
+ container_name: ${projectName}-frontend
87
+ restart: unless-stopped
88
+ ports:
89
+ - "3000:80"
90
+ depends_on:
91
+ - backend
92
+ environment:
93
+ - VITE_API_URL=http://backend:8000
94
+
95
+ backend:
96
+ build:
97
+ context: ./apps/backend
98
+ container_name: ${projectName}-backend
99
+ restart: unless-stopped
100
+ ports:
101
+ - "8000:8000"
102
+ env_file:
103
+ - ./apps/backend/.env
104
+ volumes:
105
+ - backend-data:/app/data
106
+
107
+ frontend-dev:
108
+ build:
109
+ context: ./apps/frontend
110
+ target: development
111
+ container_name: ${projectName}-frontend-dev
112
+ ports:
113
+ - "5173:5173"
114
+ volumes:
115
+ - ./apps/frontend/src:/app/src
116
+ environment:
117
+ - VITE_API_URL=http://backend:8000
118
+ depends_on:
119
+ - backend
120
+
121
+ backend-dev:
122
+ build:
123
+ context: ./apps/backend
124
+ container_name: ${projectName}-backend-dev
125
+ ports:
126
+ - "8000:8000"
127
+ volumes:
128
+ - ./apps/backend/src:/app/src
129
+ - ./apps/backend/tests:/app/tests
130
+ command: ["uvicorn", "src.backend.main:app", "--reload", "--host", "0.0.0.0", "--port", "8000"]
131
+
132
+ volumes:
133
+ backend-data:
134
+ `;
135
+ }
136
+
137
+ /**
138
+ * Generate root README.md for fullstack project
139
+ */
140
+ export function generateRootReadme(projectName: string, description?: string): string {
141
+ return `# ${projectName}
142
+
143
+ ${description || 'A fullstack application with React frontend and FastAPI backend.'}
144
+
145
+ ## Project Structure
146
+
147
+ \`\`\`
148
+ ${projectName}/
149
+ apps/
150
+ frontend/ # React + Vite + Tailwind CSS
151
+ backend/ # FastAPI (Python)
152
+ packages/
153
+ contracts/ # OpenAPI spec (future)
154
+ infra/
155
+ docker/ # Docker configuration
156
+ docs/ # Documentation
157
+ .popeye/ # Popeye CLI configuration
158
+ \`\`\`
159
+
160
+ ## Quick Start
161
+
162
+ ### Development Mode
163
+
164
+ Run both frontend and backend in development mode:
165
+
166
+ \`\`\`bash
167
+ # Option 1: Using Docker Compose (recommended)
168
+ docker-compose up frontend-dev backend-dev
169
+
170
+ # Option 2: Run separately
171
+ # Terminal 1 - Backend
172
+ cd apps/backend
173
+ pip install -e .
174
+ uvicorn src.backend.main:app --reload --port 8000
175
+
176
+ # Terminal 2 - Frontend
177
+ cd apps/frontend
178
+ npm install
179
+ npm run dev
180
+ \`\`\`
181
+
182
+ ### Production Build
183
+
184
+ \`\`\`bash
185
+ # Build and run with Docker Compose
186
+ docker-compose up --build frontend backend
187
+ \`\`\`
188
+
189
+ ## Running Tests
190
+
191
+ \`\`\`bash
192
+ # Run all tests
193
+ cd apps/backend && pytest && cd ../frontend && npm test
194
+
195
+ # Frontend tests only
196
+ cd apps/frontend && npm test
197
+
198
+ # Backend tests only
199
+ cd apps/backend && pytest
200
+ \`\`\`
201
+
202
+ ## Linting
203
+
204
+ \`\`\`bash
205
+ # Lint all
206
+ cd apps/backend && ruff check . && cd ../frontend && npm run lint
207
+
208
+ # Frontend only
209
+ cd apps/frontend && npm run lint
210
+
211
+ # Backend only
212
+ cd apps/backend && ruff check .
213
+ \`\`\`
214
+
215
+ ## Apps
216
+
217
+ ### Frontend (apps/frontend)
218
+
219
+ React application built with:
220
+ - **Vite** - Fast build tool
221
+ - **Tailwind CSS** - Utility-first CSS
222
+ - **TypeScript** - Type safety
223
+ - **Vitest** - Unit testing
224
+
225
+ See [apps/frontend/README.md](apps/frontend/README.md) for frontend-specific documentation.
226
+
227
+ ### Backend (apps/backend)
228
+
229
+ Python API built with:
230
+ - **FastAPI** - Modern async API framework
231
+ - **Pydantic** - Data validation
232
+ - **pytest** - Testing framework
233
+
234
+ See [apps/backend/README.md](apps/backend/README.md) for backend-specific documentation.
235
+
236
+ ## API Communication
237
+
238
+ Frontend connects to backend at:
239
+ - Development: \`http://localhost:8000\`
240
+ - Docker: \`http://backend:8000\`
241
+
242
+ The API URL is configured via \`VITE_API_URL\` environment variable.
243
+
244
+ ## Docker
245
+
246
+ ### Services
247
+
248
+ | Service | Port | Description |
249
+ |---------|------|-------------|
250
+ | frontend | 3000 | Production frontend (nginx) |
251
+ | backend | 8000 | Production API |
252
+ | frontend-dev | 5173 | Development frontend (HMR) |
253
+ | backend-dev | 8000 | Development API (auto-reload) |
254
+
255
+ ### Commands
256
+
257
+ \`\`\`bash
258
+ # Build all
259
+ docker-compose build
260
+
261
+ # Run production
262
+ docker-compose up frontend backend
263
+
264
+ # Run development
265
+ docker-compose up frontend-dev backend-dev
266
+
267
+ # Stop all
268
+ docker-compose down
269
+ \`\`\`
270
+
271
+ ## Configuration
272
+
273
+ - Backend environment: \`apps/backend/.env\`
274
+ - Frontend environment: \`apps/frontend/.env\`
275
+ - Workspace config: \`.popeye/workspace.json\`
276
+
277
+ ## License
278
+
279
+ MIT
280
+ `;
281
+ }
282
+
283
+ /**
284
+ * Generate root .gitignore for fullstack project
285
+ */
286
+ export function generateRootGitignore(): string {
287
+ return `# Dependencies
288
+ node_modules/
289
+ __pycache__/
290
+ *.py[cod]
291
+ *$py.class
292
+ .Python
293
+ venv/
294
+ .venv/
295
+ env/
296
+
297
+ # Build outputs
298
+ dist/
299
+ build/
300
+ *.egg-info/
301
+ .eggs/
302
+
303
+ # IDE
304
+ .idea/
305
+ .vscode/
306
+ *.swp
307
+ *.swo
308
+
309
+ # Environment files
310
+ .env
311
+ .env.local
312
+ .env.*.local
313
+ !.env.example
314
+
315
+ # Logs
316
+ *.log
317
+ npm-debug.log*
318
+ pip-log.txt
319
+
320
+ # Testing
321
+ coverage/
322
+ .coverage
323
+ htmlcov/
324
+ .pytest_cache/
325
+ .nyc_output/
326
+
327
+ # OS files
328
+ .DS_Store
329
+ Thumbs.db
330
+
331
+ # Project specific
332
+ .popeye/state.json
333
+ data/
334
+
335
+ # Docker
336
+ *.pid
337
+ `;
338
+ }
339
+
340
+ /**
341
+ * Generate frontend-specific README for fullstack project
342
+ */
343
+ export function generateFrontendReadme(projectName: string): string {
344
+ return `# ${projectName} - Frontend
345
+
346
+ React frontend application built with Vite, Tailwind CSS, and TypeScript.
347
+
348
+ ## Development
349
+
350
+ \`\`\`bash
351
+ npm install
352
+ npm run dev
353
+ \`\`\`
354
+
355
+ ## Scripts
356
+
357
+ | Script | Description |
358
+ |--------|-------------|
359
+ | \`npm run dev\` | Start development server |
360
+ | \`npm run build\` | Build for production |
361
+ | \`npm run preview\` | Preview production build |
362
+ | \`npm test\` | Run tests |
363
+ | \`npm run lint\` | Lint code |
364
+ | \`npm run typecheck\` | Type check |
365
+
366
+ ## Structure
367
+
368
+ \`\`\`
369
+ src/
370
+ components/ # Reusable components
371
+ pages/ # Page components
372
+ hooks/ # Custom hooks
373
+ utils/ # Utility functions
374
+ api/ # API client
375
+ App.tsx # Root component
376
+ main.tsx # Entry point
377
+ \`\`\`
378
+
379
+ ## API Integration
380
+
381
+ The API URL is configured via environment variable:
382
+
383
+ \`\`\`env
384
+ VITE_API_URL=http://localhost:8000
385
+ \`\`\`
386
+
387
+ ## Testing
388
+
389
+ \`\`\`bash
390
+ npm test # Run tests
391
+ npm run test:watch # Watch mode
392
+ npm run test:coverage # With coverage
393
+ \`\`\`
394
+ `;
395
+ }
396
+
397
+ /**
398
+ * Generate backend-specific README for fullstack project
399
+ */
400
+ export function generateBackendReadme(projectName: string): string {
401
+ return `# ${projectName} - Backend
402
+
403
+ FastAPI backend application.
404
+
405
+ ## Development
406
+
407
+ \`\`\`bash
408
+ # Install dependencies
409
+ pip install -e .
410
+
411
+ # Run development server
412
+ uvicorn src.backend.main:app --reload --port 8000
413
+ \`\`\`
414
+
415
+ ## Scripts (Makefile)
416
+
417
+ | Command | Description |
418
+ |---------|-------------|
419
+ | \`make dev\` | Run development server |
420
+ | \`make test\` | Run tests |
421
+ | \`make lint\` | Lint code |
422
+ | \`make format\` | Format code |
423
+
424
+ ## Structure
425
+
426
+ \`\`\`
427
+ src/backend/
428
+ main.py # FastAPI app entry point
429
+ routes/ # API routes
430
+ models/ # Pydantic models
431
+ services/ # Business logic
432
+ utils/ # Utility functions
433
+ tests/
434
+ test_main.py # Main tests
435
+ conftest.py # Test fixtures
436
+ \`\`\`
437
+
438
+ ## API Documentation
439
+
440
+ Once running, API docs are available at:
441
+ - Swagger UI: http://localhost:8000/docs
442
+ - ReDoc: http://localhost:8000/redoc
443
+
444
+ ## Testing
445
+
446
+ \`\`\`bash
447
+ pytest # Run all tests
448
+ pytest -v # Verbose
449
+ pytest --cov=src/backend # With coverage
450
+ \`\`\`
451
+
452
+ ## Environment Variables
453
+
454
+ Copy \`.env.example\` to \`.env\` and configure:
455
+
456
+ \`\`\`env
457
+ DEBUG=true
458
+ DATABASE_URL=sqlite:///./data/app.db
459
+ \`\`\`
460
+ `;
461
+ }
462
+
463
+ /**
464
+ * Generate UI spec placeholder for fullstack project
465
+ */
466
+ export function generateUiSpec(projectName: string): string {
467
+ return JSON.stringify(
468
+ {
469
+ name: projectName,
470
+ version: '1.0',
471
+ theme: {
472
+ colors: {
473
+ primary: '#3B82F6',
474
+ secondary: '#6B7280',
475
+ accent: '#10B981',
476
+ },
477
+ fonts: {
478
+ heading: 'Inter',
479
+ body: 'Inter',
480
+ },
481
+ },
482
+ components: [],
483
+ pages: [
484
+ {
485
+ name: 'Home',
486
+ path: '/',
487
+ layout: 'default',
488
+ },
489
+ ],
490
+ },
491
+ null,
492
+ 2
493
+ );
494
+ }
495
+
496
+ /**
497
+ * Generate Vite config for React frontend
498
+ */
499
+ export function generateViteConfigReact(): string {
500
+ return `import { defineConfig } from 'vite';
501
+ import react from '@vitejs/plugin-react';
502
+ import path from 'path';
503
+
504
+ export default defineConfig({
505
+ plugins: [react()],
506
+ resolve: {
507
+ alias: {
508
+ '@': path.resolve(__dirname, './src'),
509
+ },
510
+ },
511
+ server: {
512
+ port: 5173,
513
+ host: true,
514
+ proxy: {
515
+ '/api': {
516
+ target: process.env.VITE_API_URL || 'http://localhost:8000',
517
+ changeOrigin: true,
518
+ },
519
+ },
520
+ },
521
+ build: {
522
+ outDir: 'dist',
523
+ sourcemap: true,
524
+ },
525
+ });
526
+ `;
527
+ }
528
+
529
+ /**
530
+ * Generate Tailwind config for frontend
531
+ */
532
+ export function generateTailwindConfig(): string {
533
+ return `/** @type {import('tailwindcss').Config} */
534
+ export default {
535
+ content: [
536
+ './index.html',
537
+ './src/**/*.{js,ts,jsx,tsx}',
538
+ ],
539
+ theme: {
540
+ extend: {
541
+ colors: {
542
+ primary: {
543
+ 50: '#eff6ff',
544
+ 100: '#dbeafe',
545
+ 200: '#bfdbfe',
546
+ 300: '#93c5fd',
547
+ 400: '#60a5fa',
548
+ 500: '#3b82f6',
549
+ 600: '#2563eb',
550
+ 700: '#1d4ed8',
551
+ 800: '#1e40af',
552
+ 900: '#1e3a8a',
553
+ },
554
+ },
555
+ },
556
+ },
557
+ plugins: [],
558
+ };
559
+ `;
560
+ }
561
+
562
+ /**
563
+ * Generate PostCSS config for frontend
564
+ */
565
+ export function generatePostcssConfig(): string {
566
+ return `export default {
567
+ plugins: {
568
+ tailwindcss: {},
569
+ autoprefixer: {},
570
+ },
571
+ };
572
+ `;
573
+ }
574
+
575
+ /**
576
+ * Generate main CSS with Tailwind directives
577
+ */
578
+ export function generateMainCss(): string {
579
+ return `@tailwind base;
580
+ @tailwind components;
581
+ @tailwind utilities;
582
+
583
+ /* Custom styles */
584
+ body {
585
+ @apply bg-gray-50 text-gray-900;
586
+ }
587
+ `;
588
+ }
589
+
590
+ /**
591
+ * Generate React App.tsx
592
+ */
593
+ export function generateAppTsx(projectName: string): string {
594
+ return `import { useState, useEffect } from 'react';
595
+
596
+ interface HealthStatus {
597
+ status: string;
598
+ message: string;
599
+ }
600
+
601
+ function App() {
602
+ const [health, setHealth] = useState<HealthStatus | null>(null);
603
+ const [loading, setLoading] = useState(true);
604
+ const [error, setError] = useState<string | null>(null);
605
+
606
+ useEffect(() => {
607
+ const checkHealth = async () => {
608
+ try {
609
+ const apiUrl = import.meta.env.VITE_API_URL || 'http://localhost:8000';
610
+ const response = await fetch(\`\${apiUrl}/health\`);
611
+ if (response.ok) {
612
+ const data = await response.json();
613
+ setHealth(data);
614
+ } else {
615
+ setError('Backend not responding');
616
+ }
617
+ } catch (err) {
618
+ setError('Failed to connect to backend');
619
+ } finally {
620
+ setLoading(false);
621
+ }
622
+ };
623
+
624
+ checkHealth();
625
+ }, []);
626
+
627
+ return (
628
+ <div className="min-h-screen flex items-center justify-center">
629
+ <div className="text-center p-8">
630
+ <h1 className="text-4xl font-bold text-primary-600 mb-4">
631
+ ${projectName}
632
+ </h1>
633
+ <p className="text-gray-600 mb-8">
634
+ Fullstack application with React + FastAPI
635
+ </p>
636
+
637
+ <div className="bg-white rounded-lg shadow-md p-6">
638
+ <h2 className="text-lg font-semibold mb-2">Backend Status</h2>
639
+ {loading && (
640
+ <p className="text-gray-500">Checking...</p>
641
+ )}
642
+ {error && (
643
+ <p className="text-red-500">{error}</p>
644
+ )}
645
+ {health && (
646
+ <div className="text-green-500">
647
+ <p>Status: {health.status}</p>
648
+ <p className="text-sm text-gray-500">{health.message}</p>
649
+ </div>
650
+ )}
651
+ </div>
652
+ </div>
653
+ </div>
654
+ );
655
+ }
656
+
657
+ export default App;
658
+ `;
659
+ }
660
+
661
+ /**
662
+ * Generate React main.tsx entry point
663
+ */
664
+ export function generateMainTsx(): string {
665
+ return `import { StrictMode } from 'react';
666
+ import { createRoot } from 'react-dom/client';
667
+ import App from './App';
668
+ import './index.css';
669
+
670
+ createRoot(document.getElementById('root')!).render(
671
+ <StrictMode>
672
+ <App />
673
+ </StrictMode>
674
+ );
675
+ `;
676
+ }
677
+
678
+ /**
679
+ * Generate index.html for React app
680
+ */
681
+ export function generateIndexHtml(projectName: string): string {
682
+ return `<!DOCTYPE html>
683
+ <html lang="en">
684
+ <head>
685
+ <meta charset="UTF-8" />
686
+ <link rel="icon" type="image/svg+xml" href="/vite.svg" />
687
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
688
+ <title>${projectName}</title>
689
+ </head>
690
+ <body>
691
+ <div id="root"></div>
692
+ <script type="module" src="/src/main.tsx"></script>
693
+ </body>
694
+ </html>
695
+ `;
696
+ }
697
+
698
+ /**
699
+ * Generate frontend package.json for React + Vite
700
+ */
701
+ export function generateFrontendPackageJson(projectName: string): string {
702
+ return JSON.stringify(
703
+ {
704
+ name: `${projectName}-frontend`,
705
+ private: true,
706
+ version: '1.0.0',
707
+ type: 'module',
708
+ scripts: {
709
+ dev: 'vite',
710
+ build: 'tsc && vite build',
711
+ preview: 'vite preview',
712
+ test: 'vitest run',
713
+ 'test:watch': 'vitest',
714
+ 'test:coverage': 'vitest run --coverage',
715
+ lint: 'eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0',
716
+ typecheck: 'tsc --noEmit',
717
+ },
718
+ dependencies: {
719
+ react: '^18.2.0',
720
+ 'react-dom': '^18.2.0',
721
+ },
722
+ devDependencies: {
723
+ '@types/react': '^18.2.0',
724
+ '@types/react-dom': '^18.2.0',
725
+ '@typescript-eslint/eslint-plugin': '^8.0.0',
726
+ '@typescript-eslint/parser': '^8.0.0',
727
+ '@vitejs/plugin-react': '^4.2.0',
728
+ '@vitest/coverage-v8': '^2.0.0',
729
+ autoprefixer: '^10.4.0',
730
+ eslint: '^9.0.0',
731
+ 'eslint-plugin-react-hooks': '^4.6.0',
732
+ 'eslint-plugin-react-refresh': '^0.4.0',
733
+ postcss: '^8.4.0',
734
+ tailwindcss: '^3.4.0',
735
+ typescript: '^5.4.0',
736
+ vite: '^5.2.0',
737
+ vitest: '^2.0.0',
738
+ },
739
+ },
740
+ null,
741
+ 2
742
+ );
743
+ }
744
+
745
+ /**
746
+ * Generate frontend tsconfig.json for React
747
+ */
748
+ export function generateFrontendTsconfig(): string {
749
+ return JSON.stringify(
750
+ {
751
+ compilerOptions: {
752
+ target: 'ES2020',
753
+ useDefineForClassFields: true,
754
+ lib: ['ES2020', 'DOM', 'DOM.Iterable'],
755
+ module: 'ESNext',
756
+ skipLibCheck: true,
757
+ moduleResolution: 'bundler',
758
+ allowImportingTsExtensions: true,
759
+ resolveJsonModule: true,
760
+ isolatedModules: true,
761
+ noEmit: true,
762
+ jsx: 'react-jsx',
763
+ strict: true,
764
+ noUnusedLocals: true,
765
+ noUnusedParameters: true,
766
+ noFallthroughCasesInSwitch: true,
767
+ paths: {
768
+ '@/*': ['./src/*'],
769
+ },
770
+ },
771
+ include: ['src'],
772
+ references: [{ path: './tsconfig.node.json' }],
773
+ },
774
+ null,
775
+ 2
776
+ );
777
+ }
778
+
779
+ /**
780
+ * Generate frontend tsconfig.node.json
781
+ */
782
+ export function generateFrontendTsconfigNode(): string {
783
+ return JSON.stringify(
784
+ {
785
+ compilerOptions: {
786
+ composite: true,
787
+ skipLibCheck: true,
788
+ module: 'ESNext',
789
+ moduleResolution: 'bundler',
790
+ allowSyntheticDefaultImports: true,
791
+ strict: true,
792
+ },
793
+ include: ['vite.config.ts'],
794
+ },
795
+ null,
796
+ 2
797
+ );
798
+ }
799
+
800
+ /**
801
+ * Generate frontend Dockerfile for React + nginx
802
+ */
803
+ export function generateFrontendDockerfile(): string {
804
+ return `# Build stage
805
+ FROM node:20-slim as build
806
+
807
+ WORKDIR /app
808
+
809
+ COPY package*.json ./
810
+ RUN npm ci
811
+
812
+ COPY . .
813
+ RUN npm run build
814
+
815
+ # Production stage
816
+ FROM nginx:alpine as production
817
+
818
+ COPY --from=build /app/dist /usr/share/nginx/html
819
+ COPY nginx.conf /etc/nginx/conf.d/default.conf
820
+
821
+ EXPOSE 80
822
+ CMD ["nginx", "-g", "daemon off;"]
823
+
824
+ # Development stage
825
+ FROM node:20-slim as development
826
+
827
+ WORKDIR /app
828
+
829
+ COPY package*.json ./
830
+ RUN npm ci
831
+
832
+ COPY . .
833
+
834
+ EXPOSE 5173
835
+ CMD ["npm", "run", "dev", "--", "--host"]
836
+ `;
837
+ }
838
+
839
+ /**
840
+ * Generate nginx config for frontend
841
+ */
842
+ export function generateNginxConfig(): string {
843
+ return `server {
844
+ listen 80;
845
+ server_name localhost;
846
+ root /usr/share/nginx/html;
847
+ index index.html;
848
+
849
+ # Handle SPA routing
850
+ location / {
851
+ try_files $uri $uri/ /index.html;
852
+ }
853
+
854
+ # Proxy API requests to backend
855
+ location /api {
856
+ proxy_pass http://backend:8000;
857
+ proxy_http_version 1.1;
858
+ proxy_set_header Upgrade $http_upgrade;
859
+ proxy_set_header Connection 'upgrade';
860
+ proxy_set_header Host $host;
861
+ proxy_cache_bypass $http_upgrade;
862
+ }
863
+
864
+ # Cache static assets
865
+ location ~* \\.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
866
+ expires 1y;
867
+ add_header Cache-Control "public, immutable";
868
+ }
869
+ }
870
+ `;
871
+ }
872
+
873
+ /**
874
+ * Generate frontend test file
875
+ */
876
+ export function generateFrontendTest(projectName: string): string {
877
+ return `import { describe, it, expect } from 'vitest';
878
+ import { render, screen } from '@testing-library/react';
879
+ import App from '../src/App';
880
+
881
+ describe('App', () => {
882
+ it('renders the project name', () => {
883
+ render(<App />);
884
+ expect(screen.getByText('${projectName}')).toBeDefined();
885
+ });
886
+
887
+ it('shows loading state initially', () => {
888
+ render(<App />);
889
+ expect(screen.getByText('Checking...')).toBeDefined();
890
+ });
891
+ });
892
+ `;
893
+ }
894
+
895
+ /**
896
+ * Generate vitest setup for React
897
+ */
898
+ export function generateVitestSetup(): string {
899
+ return `import '@testing-library/jest-dom';
900
+ `;
901
+ }
902
+
903
+ /**
904
+ * Generate vitest config for React
905
+ */
906
+ export function generateFrontendVitestConfig(): string {
907
+ return `import { defineConfig } from 'vitest/config';
908
+ import react from '@vitejs/plugin-react';
909
+
910
+ export default defineConfig({
911
+ plugins: [react()],
912
+ test: {
913
+ globals: true,
914
+ environment: 'jsdom',
915
+ setupFiles: './tests/setup.ts',
916
+ coverage: {
917
+ provider: 'v8',
918
+ reporter: ['text', 'json', 'html'],
919
+ exclude: ['node_modules/', 'tests/'],
920
+ },
921
+ },
922
+ });
923
+ `;
924
+ }
925
+
926
+ /**
927
+ * Generate backend FastAPI main.py
928
+ */
929
+ export function generateFastAPIMain(projectName: string): string {
930
+ return `"""
931
+ ${projectName} Backend API
932
+
933
+ FastAPI application entry point.
934
+ """
935
+
936
+ import logging
937
+ from fastapi import FastAPI
938
+ from fastapi.middleware.cors import CORSMiddleware
939
+
940
+ # Configure logging
941
+ logging.basicConfig(level=logging.INFO)
942
+ logger = logging.getLogger(__name__)
943
+
944
+ # Create FastAPI app
945
+ app = FastAPI(
946
+ title="${projectName} API",
947
+ description="Backend API for ${projectName}",
948
+ version="1.0.0",
949
+ )
950
+
951
+ # Configure CORS
952
+ app.add_middleware(
953
+ CORSMiddleware,
954
+ allow_origins=["http://localhost:5173", "http://localhost:3000"],
955
+ allow_credentials=True,
956
+ allow_methods=["*"],
957
+ allow_headers=["*"],
958
+ )
959
+
960
+
961
+ @app.get("/health")
962
+ async def health_check():
963
+ """
964
+ Health check endpoint.
965
+
966
+ Returns:
967
+ dict: Health status.
968
+ """
969
+ return {
970
+ "status": "healthy",
971
+ "message": "Backend is running",
972
+ }
973
+
974
+
975
+ @app.get("/")
976
+ async def root():
977
+ """
978
+ Root endpoint.
979
+
980
+ Returns:
981
+ dict: Welcome message.
982
+ """
983
+ return {
984
+ "message": "Welcome to ${projectName} API",
985
+ "docs": "/docs",
986
+ }
987
+
988
+
989
+ if __name__ == "__main__":
990
+ import uvicorn
991
+ uvicorn.run(app, host="0.0.0.0", port=8000)
992
+ `;
993
+ }
994
+
995
+ /**
996
+ * Generate backend Dockerfile for FastAPI
997
+ */
998
+ export function generateBackendDockerfile(_projectName: string): string {
999
+ return `# Python base image
1000
+ FROM python:3.11-slim
1001
+
1002
+ WORKDIR /app
1003
+
1004
+ # Install system dependencies
1005
+ RUN apt-get update && apt-get install -y --no-install-recommends \\
1006
+ build-essential \\
1007
+ && rm -rf /var/lib/apt/lists/*
1008
+
1009
+ # Copy requirements first for caching
1010
+ COPY requirements.txt pyproject.toml ./
1011
+ RUN pip install --no-cache-dir -r requirements.txt
1012
+
1013
+ # Copy application code
1014
+ COPY src/ ./src/
1015
+ COPY tests/ ./tests/
1016
+
1017
+ # Install the package
1018
+ RUN pip install -e .
1019
+
1020
+ # Create non-root user
1021
+ RUN adduser --disabled-password --gecos '' appuser
1022
+ RUN mkdir -p /app/data && chown -R appuser:appuser /app
1023
+ USER appuser
1024
+
1025
+ EXPOSE 8000
1026
+
1027
+ CMD ["uvicorn", "src.backend.main:app", "--host", "0.0.0.0", "--port", "8000"]
1028
+ `;
1029
+ }
1030
+
1031
+ /**
1032
+ * Generate backend requirements.txt for FastAPI
1033
+ */
1034
+ export function generateFastAPIRequirements(): string {
1035
+ return `# FastAPI and dependencies
1036
+ fastapi>=0.109.0
1037
+ uvicorn[standard]>=0.27.0
1038
+ pydantic>=2.5.0
1039
+ pydantic-settings>=2.1.0
1040
+
1041
+ # Development
1042
+ ruff>=0.1.0
1043
+ pytest>=7.4.0
1044
+ pytest-asyncio>=0.23.0
1045
+ httpx>=0.26.0
1046
+ `;
1047
+ }