@c0x12c/ai-toolkit 1.15.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 (255) hide show
  1. package/.claude-plugin/marketplace.json +16 -0
  2. package/.claude-plugin/plugin.json +12 -0
  3. package/README.md +439 -0
  4. package/VERSION +1 -0
  5. package/agents/design-critic.md +127 -0
  6. package/agents/idea-killer.md +72 -0
  7. package/agents/infrastructure-expert.md +49 -0
  8. package/agents/micronaut-backend-expert.md +45 -0
  9. package/agents/phase-reviewer.md +150 -0
  10. package/agents/research-planner.md +70 -0
  11. package/agents/solution-architect-cto.md +49 -0
  12. package/agents/sre-architect.md +49 -0
  13. package/agents/team-coordinator.md +111 -0
  14. package/bin/cli.js +780 -0
  15. package/claude-md/00-header.md +39 -0
  16. package/claude-md/01-core.md +105 -0
  17. package/claude-md/05-database.md +20 -0
  18. package/claude-md/11-backend-micronaut.md +19 -0
  19. package/claude-md/20-frontend-react.md +44 -0
  20. package/claude-md/25-ux-design.md +56 -0
  21. package/claude-md/30-infrastructure.md +24 -0
  22. package/claude-md/30-project-mgmt.md +119 -0
  23. package/claude-md/40-product.md +39 -0
  24. package/claude-md/50-ops.md +34 -0
  25. package/claude-md/60-research.md +27 -0
  26. package/claude-md/90-footer.md +21 -0
  27. package/commands/spartan/brainstorm.md +134 -0
  28. package/commands/spartan/brownfield.md +157 -0
  29. package/commands/spartan/build.md +435 -0
  30. package/commands/spartan/careful.md +94 -0
  31. package/commands/spartan/commit-message.md +112 -0
  32. package/commands/spartan/content.md +17 -0
  33. package/commands/spartan/context-save.md +161 -0
  34. package/commands/spartan/contribute.md +140 -0
  35. package/commands/spartan/daily.md +42 -0
  36. package/commands/spartan/debug.md +308 -0
  37. package/commands/spartan/deep-dive.md +55 -0
  38. package/commands/spartan/deploy.md +207 -0
  39. package/commands/spartan/e2e.md +264 -0
  40. package/commands/spartan/env-setup.md +166 -0
  41. package/commands/spartan/epic.md +199 -0
  42. package/commands/spartan/fe-review.md +181 -0
  43. package/commands/spartan/figma-to-code.md +260 -0
  44. package/commands/spartan/forensics.md +46 -0
  45. package/commands/spartan/freeze.md +84 -0
  46. package/commands/spartan/fundraise.md +53 -0
  47. package/commands/spartan/gate-review.md +229 -0
  48. package/commands/spartan/gsd-upgrade.md +376 -0
  49. package/commands/spartan/guard.md +42 -0
  50. package/commands/spartan/init-project.md +178 -0
  51. package/commands/spartan/init-rules.md +298 -0
  52. package/commands/spartan/interview.md +154 -0
  53. package/commands/spartan/kickoff.md +73 -0
  54. package/commands/spartan/kotlin-service.md +109 -0
  55. package/commands/spartan/lean-canvas.md +222 -0
  56. package/commands/spartan/lint-rules.md +122 -0
  57. package/commands/spartan/map-codebase.md +124 -0
  58. package/commands/spartan/migration.md +82 -0
  59. package/commands/spartan/next-app.md +317 -0
  60. package/commands/spartan/next-feature.md +212 -0
  61. package/commands/spartan/onboard.md +326 -0
  62. package/commands/spartan/outreach.md +16 -0
  63. package/commands/spartan/phase.md +142 -0
  64. package/commands/spartan/pitch.md +18 -0
  65. package/commands/spartan/plan.md +210 -0
  66. package/commands/spartan/pr-ready.md +202 -0
  67. package/commands/spartan/project.md +106 -0
  68. package/commands/spartan/qa.md +222 -0
  69. package/commands/spartan/research.md +254 -0
  70. package/commands/spartan/review.md +132 -0
  71. package/commands/spartan/scan-rules.md +173 -0
  72. package/commands/spartan/sessions.md +143 -0
  73. package/commands/spartan/spec.md +131 -0
  74. package/commands/spartan/startup.md +257 -0
  75. package/commands/spartan/team.md +570 -0
  76. package/commands/spartan/teardown.md +161 -0
  77. package/commands/spartan/testcontainer.md +97 -0
  78. package/commands/spartan/tf-cost.md +123 -0
  79. package/commands/spartan/tf-deploy.md +116 -0
  80. package/commands/spartan/tf-drift.md +100 -0
  81. package/commands/spartan/tf-import.md +107 -0
  82. package/commands/spartan/tf-module.md +121 -0
  83. package/commands/spartan/tf-plan.md +100 -0
  84. package/commands/spartan/tf-review.md +106 -0
  85. package/commands/spartan/tf-scaffold.md +109 -0
  86. package/commands/spartan/tf-security.md +147 -0
  87. package/commands/spartan/think.md +221 -0
  88. package/commands/spartan/unfreeze.md +13 -0
  89. package/commands/spartan/update.md +134 -0
  90. package/commands/spartan/ux.md +1233 -0
  91. package/commands/spartan/validate.md +193 -0
  92. package/commands/spartan/web-to-prd.md +706 -0
  93. package/commands/spartan/workstreams.md +109 -0
  94. package/commands/spartan/write.md +16 -0
  95. package/commands/spartan.md +386 -0
  96. package/frameworks/00-framework-comparison-guide.md +317 -0
  97. package/frameworks/01-lean-canvas.md +196 -0
  98. package/frameworks/02-design-sprint.md +304 -0
  99. package/frameworks/03-foundation-sprint.md +337 -0
  100. package/frameworks/04-business-model-canvas.md +391 -0
  101. package/frameworks/05-customer-development.md +426 -0
  102. package/frameworks/06-jobs-to-be-done.md +358 -0
  103. package/frameworks/07-mom-test.md +392 -0
  104. package/frameworks/08-value-proposition-canvas.md +488 -0
  105. package/frameworks/09-javelin-board.md +428 -0
  106. package/frameworks/10-build-measure-learn.md +467 -0
  107. package/frameworks/11-mvp-approaches.md +533 -0
  108. package/frameworks/think-before-build.md +593 -0
  109. package/lib/assembler.js +197 -0
  110. package/lib/assembler.test.js +159 -0
  111. package/lib/detector.js +166 -0
  112. package/lib/detector.test.js +221 -0
  113. package/lib/packs.js +16 -0
  114. package/lib/resolver.js +272 -0
  115. package/lib/resolver.test.js +298 -0
  116. package/lib/worktree.sh +104 -0
  117. package/package.json +50 -0
  118. package/packs/backend-micronaut.yaml +35 -0
  119. package/packs/backend-nodejs.yaml +15 -0
  120. package/packs/backend-python.yaml +15 -0
  121. package/packs/core.yaml +37 -0
  122. package/packs/database.yaml +21 -0
  123. package/packs/frontend-react.yaml +24 -0
  124. package/packs/infrastructure.yaml +40 -0
  125. package/packs/ops.yaml +16 -0
  126. package/packs/packs.compiled.json +371 -0
  127. package/packs/product.yaml +22 -0
  128. package/packs/project-mgmt.yaml +24 -0
  129. package/packs/research.yaml +39 -0
  130. package/packs/shared-backend.yaml +14 -0
  131. package/packs/ux-design.yaml +21 -0
  132. package/rules/backend-micronaut/API_DESIGN.md +313 -0
  133. package/rules/backend-micronaut/BATCH_PROCESSING.md +92 -0
  134. package/rules/backend-micronaut/CONTROLLERS.md +388 -0
  135. package/rules/backend-micronaut/KOTLIN.md +414 -0
  136. package/rules/backend-micronaut/RETROFIT_PLACEMENT.md +290 -0
  137. package/rules/backend-micronaut/SERVICES_AND_BEANS.md +325 -0
  138. package/rules/core/NAMING_CONVENTIONS.md +208 -0
  139. package/rules/core/SKILL_AUTHORING.md +174 -0
  140. package/rules/core/TIMEZONE.md +316 -0
  141. package/rules/database/ORM_AND_REPO.md +289 -0
  142. package/rules/database/SCHEMA.md +146 -0
  143. package/rules/database/TRANSACTIONS.md +311 -0
  144. package/rules/frontend-react/FRONTEND.md +344 -0
  145. package/rules/infrastructure/MODULES.md +260 -0
  146. package/rules/infrastructure/NAMING.md +196 -0
  147. package/rules/infrastructure/PROVIDERS.md +309 -0
  148. package/rules/infrastructure/SECURITY.md +310 -0
  149. package/rules/infrastructure/STATE_AND_BACKEND.md +237 -0
  150. package/rules/infrastructure/STRUCTURE.md +234 -0
  151. package/rules/infrastructure/VARIABLES.md +285 -0
  152. package/rules/shared-backend/ARCHITECTURE.md +46 -0
  153. package/rules/ux-design/DESIGN_PROCESS.md +176 -0
  154. package/skills/api-endpoint-creator/SKILL.md +455 -0
  155. package/skills/api-endpoint-creator/error-handling-guide.md +244 -0
  156. package/skills/api-endpoint-creator/examples.md +522 -0
  157. package/skills/api-endpoint-creator/testing-patterns.md +302 -0
  158. package/skills/article-writing/SKILL.md +109 -0
  159. package/skills/article-writing/examples.md +59 -0
  160. package/skills/backend-api-design/SKILL.md +84 -0
  161. package/skills/backend-api-design/code-patterns.md +138 -0
  162. package/skills/brainstorm/SKILL.md +95 -0
  163. package/skills/browser-qa/SKILL.md +87 -0
  164. package/skills/browser-qa/playwright-snippets.md +110 -0
  165. package/skills/ci-cd-patterns/SKILL.md +108 -0
  166. package/skills/ci-cd-patterns/workflows.md +149 -0
  167. package/skills/competitive-teardown/SKILL.md +93 -0
  168. package/skills/competitive-teardown/example-analysis.md +50 -0
  169. package/skills/content-engine/SKILL.md +131 -0
  170. package/skills/content-engine/examples.md +72 -0
  171. package/skills/database-patterns/SKILL.md +72 -0
  172. package/skills/database-patterns/code-templates.md +114 -0
  173. package/skills/database-table-creator/SKILL.md +141 -0
  174. package/skills/database-table-creator/examples.md +552 -0
  175. package/skills/database-table-creator/kotlin-templates.md +400 -0
  176. package/skills/database-table-creator/migration-template.sql +68 -0
  177. package/skills/database-table-creator/validation-checklist.md +337 -0
  178. package/skills/deep-research/SKILL.md +80 -0
  179. package/skills/design-intelligence/SKILL.md +268 -0
  180. package/skills/design-workflow/SKILL.md +127 -0
  181. package/skills/design-workflow/checklists.md +45 -0
  182. package/skills/idea-validation/SKILL.md +129 -0
  183. package/skills/idea-validation/example-report.md +50 -0
  184. package/skills/investor-materials/SKILL.md +122 -0
  185. package/skills/investor-materials/example-outline.md +70 -0
  186. package/skills/investor-outreach/SKILL.md +112 -0
  187. package/skills/investor-outreach/examples.md +76 -0
  188. package/skills/kotlin-best-practices/SKILL.md +58 -0
  189. package/skills/kotlin-best-practices/code-patterns.md +132 -0
  190. package/skills/market-research/SKILL.md +99 -0
  191. package/skills/security-checklist/SKILL.md +65 -0
  192. package/skills/security-checklist/audit-reference.md +95 -0
  193. package/skills/service-debugging/SKILL.md +116 -0
  194. package/skills/service-debugging/common-issues.md +65 -0
  195. package/skills/startup-pipeline/SKILL.md +152 -0
  196. package/skills/terraform-best-practices/SKILL.md +244 -0
  197. package/skills/terraform-module-creator/SKILL.md +284 -0
  198. package/skills/terraform-review/SKILL.md +222 -0
  199. package/skills/terraform-security-audit/SKILL.md +280 -0
  200. package/skills/terraform-service-scaffold/SKILL.md +574 -0
  201. package/skills/testing-strategies/SKILL.md +116 -0
  202. package/skills/testing-strategies/examples.md +103 -0
  203. package/skills/testing-strategies/integration-test-setup.md +71 -0
  204. package/skills/ui-ux-pro-max/SKILL.md +238 -0
  205. package/skills/ui-ux-pro-max/data/charts.csv +26 -0
  206. package/skills/ui-ux-pro-max/data/colors.csv +97 -0
  207. package/skills/ui-ux-pro-max/data/icons.csv +101 -0
  208. package/skills/ui-ux-pro-max/data/landing.csv +31 -0
  209. package/skills/ui-ux-pro-max/data/products.csv +97 -0
  210. package/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
  211. package/skills/ui-ux-pro-max/data/stacks/astro.csv +54 -0
  212. package/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  213. package/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  214. package/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
  215. package/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  216. package/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  217. package/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  218. package/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  219. package/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
  220. package/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  221. package/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  222. package/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  223. package/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  224. package/skills/ui-ux-pro-max/data/styles.csv +68 -0
  225. package/skills/ui-ux-pro-max/data/typography.csv +58 -0
  226. package/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  227. package/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  228. package/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
  229. package/skills/ui-ux-pro-max/python-setup.md +146 -0
  230. package/skills/ui-ux-pro-max/scripts/core.py +253 -0
  231. package/skills/ui-ux-pro-max/scripts/design_system.py +1067 -0
  232. package/skills/ui-ux-pro-max/scripts/search.py +114 -0
  233. package/skills/web-to-prd/SKILL.md +478 -0
  234. package/templates/build-config.yaml +44 -0
  235. package/templates/commands-config.yaml +55 -0
  236. package/templates/competitor-analysis.md +60 -0
  237. package/templates/content/AGENT_TEMPLATE.md +47 -0
  238. package/templates/content/COMMAND_TEMPLATE.md +27 -0
  239. package/templates/content/RULE_TEMPLATE.md +40 -0
  240. package/templates/content/SKILL_TEMPLATE.md +41 -0
  241. package/templates/design-config.md +105 -0
  242. package/templates/design-doc.md +207 -0
  243. package/templates/epic.md +100 -0
  244. package/templates/feature-spec.md +181 -0
  245. package/templates/idea-canvas.md +47 -0
  246. package/templates/implementation-plan.md +159 -0
  247. package/templates/prd-template.md +86 -0
  248. package/templates/preamble.md +89 -0
  249. package/templates/project-readme.md +35 -0
  250. package/templates/quality-gates.md +230 -0
  251. package/templates/spartan-config.yaml +164 -0
  252. package/templates/user-interview.md +69 -0
  253. package/templates/validation-checklist.md +108 -0
  254. package/templates/workflow-backend-micronaut.md +409 -0
  255. package/templates/workflow-frontend-react.md +233 -0
@@ -0,0 +1,317 @@
1
+ ---
2
+ name: spartan:next-app
3
+ description: Scaffold a complete new Next.js application from scratch — App Router, TypeScript, Tailwind, testing setup, API client layer, auth scaffolding, and CI config.
4
+ argument-hint: "[app name] [brief description]"
5
+ ---
6
+
7
+ # New Next.js App: {{ args[0] }}
8
+ Description: {{ args[1] }}
9
+
10
+ Scaffolding a **production-ready** Next.js application. This is more complete than
11
+ `/spartan:next-feature` — use this for a brand-new frontend project.
12
+
13
+ ---
14
+
15
+ ## Step 1: Clarify before building
16
+
17
+ Ask:
18
+ 1. **Auth**: None / NextAuth.js / custom JWT / Clerk / Auth0?
19
+ 2. **State management**: Server-only (preferred) / Zustand / React Query for client state?
20
+ 3. **Connects to which BE service(s)?** (Kotlin service names/URLs)
21
+ 4. **Deploy target**: Railway / Vercel / AWS / Docker+K8s?
22
+ 5. **Database** (if any — for full-stack Next.js with Prisma): Yes / No, using separate BE
23
+
24
+ **Auto mode on?** → Use defaults: No auth, Server-only state, Railway deploy, no DB (separate BE). Proceed immediately.
25
+ **Auto mode off?** → Wait for answers.
26
+
27
+ ---
28
+
29
+ ## Step 2: Bootstrap with create-next-app
30
+
31
+ ```bash
32
+ npx create-next-app@latest {{ args[0] }} \
33
+ --typescript \
34
+ --tailwind \
35
+ --app \
36
+ --src-dir \
37
+ --import-alias "@/*" \
38
+ --no-eslint # we configure this ourselves
39
+
40
+ cd {{ args[0] }}
41
+ ```
42
+
43
+ ---
44
+
45
+ ## Step 3: Install core dependencies
46
+
47
+ ```bash
48
+ # Testing
49
+ npm install -D vitest @vitejs/plugin-react jsdom
50
+ npm install -D @testing-library/react @testing-library/user-event @testing-library/jest-dom
51
+
52
+ # API + validation
53
+ npm install zod
54
+
55
+ # Auth (if NextAuth chosen)
56
+ npm install next-auth@beta # v5 for App Router
57
+
58
+ # Dev tooling
59
+ npm install -D eslint-config-next @typescript-eslint/eslint-plugin prettier
60
+ ```
61
+
62
+ ---
63
+
64
+ ## Step 4: Configure project structure
65
+
66
+ ```
67
+ src/
68
+ ├── app/ # App Router
69
+ │ ├── (auth)/ # Route group — auth pages
70
+ │ │ ├── login/page.tsx
71
+ │ │ └── layout.tsx
72
+ │ ├── (dashboard)/ # Route group — protected pages
73
+ │ │ ├── layout.tsx # ← auth check here
74
+ │ │ └── [feature]/
75
+ │ ├── api/ # API routes (only when server actions aren't enough)
76
+ │ ├── globals.css
77
+ │ └── layout.tsx # Root layout
78
+ ├── components/
79
+ │ ├── ui/ # Shared primitives (Button, Input, Card...)
80
+ │ └── [feature]/ # Feature-specific components
81
+ ├── lib/
82
+ │ ├── api/ # BE API client functions
83
+ │ │ ├── client.ts # Base fetch wrapper
84
+ │ │ └── [service].api.ts # Per-service functions
85
+ │ ├── auth/ # Auth utilities
86
+ │ └── utils.ts # cn(), formatDate(), etc.
87
+ ├── hooks/ # Custom React hooks (client-side)
88
+ ├── types/ # Shared TypeScript types
89
+ │ └── api.types.ts # Mirror Kotlin DTOs here
90
+ └── middleware.ts # Auth + route protection
91
+ ```
92
+
93
+ ---
94
+
95
+ ## Step 5: Create base API client
96
+
97
+ ```typescript
98
+ // src/lib/api/client.ts
99
+ const BASE_URL = process.env.NEXT_PUBLIC_API_URL ?? 'http://localhost:8080'
100
+
101
+ type ApiError = {
102
+ message: string
103
+ code: string
104
+ status: number
105
+ }
106
+
107
+ export class ApiClient {
108
+ private static async request<T>(
109
+ path: string,
110
+ options?: RequestInit & { tags?: string[] }
111
+ ): Promise<T> {
112
+ const res = await fetch(`${BASE_URL}${path}`, {
113
+ ...options,
114
+ headers: {
115
+ 'Content-Type': 'application/json',
116
+ ...options?.headers,
117
+ },
118
+ next: options?.tags ? { tags: options.tags } : undefined,
119
+ })
120
+
121
+ if (!res.ok) {
122
+ const error: ApiError = await res.json().catch(() => ({
123
+ message: 'Unknown error',
124
+ code: 'UNKNOWN',
125
+ status: res.status,
126
+ }))
127
+ throw new Error(error.message)
128
+ }
129
+
130
+ return res.json()
131
+ }
132
+
133
+ static get<T>(path: string, tags?: string[]) {
134
+ return this.request<T>(path, { tags })
135
+ }
136
+
137
+ static post<T>(path: string, body: unknown) {
138
+ return this.request<T>(path, {
139
+ method: 'POST',
140
+ body: JSON.stringify(body),
141
+ })
142
+ }
143
+
144
+ static put<T>(path: string, body: unknown) {
145
+ return this.request<T>(path, {
146
+ method: 'PUT',
147
+ body: JSON.stringify(body),
148
+ })
149
+ }
150
+
151
+ static delete<T>(path: string) {
152
+ return this.request<T>(path, { method: 'DELETE' })
153
+ }
154
+ }
155
+ ```
156
+
157
+ ---
158
+
159
+ ## Step 6: Configure Vitest
160
+
161
+ ```typescript
162
+ // vitest.config.ts
163
+ import { defineConfig } from 'vitest/config'
164
+ import react from '@vitejs/plugin-react'
165
+ import path from 'path'
166
+
167
+ export default defineConfig({
168
+ plugins: [react()],
169
+ test: {
170
+ environment: 'jsdom',
171
+ globals: true,
172
+ setupFiles: ['./src/test/setup.ts'],
173
+ },
174
+ resolve: {
175
+ alias: {
176
+ '@': path.resolve(__dirname, './src'),
177
+ },
178
+ },
179
+ })
180
+ ```
181
+
182
+ ```typescript
183
+ // src/test/setup.ts
184
+ import '@testing-library/jest-dom'
185
+ import { vi } from 'vitest'
186
+
187
+ // Mock Next.js navigation
188
+ vi.mock('next/navigation', () => ({
189
+ useRouter: () => ({ push: vi.fn(), replace: vi.fn(), back: vi.fn() }),
190
+ usePathname: () => '/',
191
+ useSearchParams: () => new URLSearchParams(),
192
+ }))
193
+ ```
194
+
195
+ Add to `package.json`:
196
+ ```json
197
+ {
198
+ "scripts": {
199
+ "test": "vitest",
200
+ "test:run": "vitest run",
201
+ "test:coverage": "vitest run --coverage"
202
+ }
203
+ }
204
+ ```
205
+
206
+ ---
207
+
208
+ ## Step 7: Environment variables
209
+
210
+ Create `.env.local`:
211
+ ```bash
212
+ NEXT_PUBLIC_API_URL=http://localhost:8080
213
+ # NEXTAUTH_URL=http://localhost:3000
214
+ # NEXTAUTH_SECRET= # generate: openssl rand -base64 32
215
+ ```
216
+
217
+ Create `.env.example` (commit this):
218
+ ```bash
219
+ NEXT_PUBLIC_API_URL=http://localhost:8080
220
+ # NEXTAUTH_URL=https://your-domain.com
221
+ # NEXTAUTH_SECRET=your-secret-here
222
+ ```
223
+
224
+ ---
225
+
226
+ ## Step 8: Deploy configuration
227
+
228
+ **Railway** (`railway.toml`):
229
+ ```toml
230
+ [build]
231
+ builder = "nixpacks"
232
+
233
+ [deploy]
234
+ startCommand = "npm start"
235
+ healthcheckPath = "/api/health"
236
+ healthcheckTimeout = 30
237
+ ```
238
+
239
+ Create `src/app/api/health/route.ts`:
240
+ ```typescript
241
+ export function GET() {
242
+ return Response.json({ status: 'ok', timestamp: new Date().toISOString() })
243
+ }
244
+ ```
245
+
246
+ **Docker** (`Dockerfile`):
247
+ ```dockerfile
248
+ FROM node:20-alpine AS deps
249
+ WORKDIR /app
250
+ COPY package*.json ./
251
+ RUN npm ci
252
+
253
+ FROM node:20-alpine AS builder
254
+ WORKDIR /app
255
+ COPY --from=deps /app/node_modules ./node_modules
256
+ COPY . .
257
+ RUN npm run build
258
+
259
+ FROM node:20-alpine AS runner
260
+ WORKDIR /app
261
+ ENV NODE_ENV=production
262
+ COPY --from=builder /app/.next/standalone ./
263
+ COPY --from=builder /app/.next/static ./.next/static
264
+ COPY --from=builder /app/public ./public
265
+ EXPOSE 3000
266
+ CMD ["node", "server.js"]
267
+ ```
268
+
269
+ Add to `next.config.ts`: `output: 'standalone'`
270
+
271
+ ---
272
+
273
+ ## Step 9: First test — smoke test
274
+
275
+ ```typescript
276
+ // src/app/page.test.tsx
277
+ import { render, screen } from '@testing-library/react'
278
+ import { describe, it, expect } from 'vitest'
279
+ import Home from './page'
280
+
281
+ describe('Home page', () => {
282
+ it('renders without crashing', () => {
283
+ render(<Home />)
284
+ expect(document.body).toBeDefined()
285
+ })
286
+ })
287
+ ```
288
+
289
+ Run: `npm test` — must be green before moving on.
290
+
291
+ ---
292
+
293
+ ## Step 10: GitHub Actions CI
294
+
295
+ ```yaml
296
+ # .github/workflows/ci.yml
297
+ name: CI
298
+
299
+ on: [push, pull_request]
300
+
301
+ jobs:
302
+ test:
303
+ runs-on: ubuntu-latest
304
+ steps:
305
+ - uses: actions/checkout@v4
306
+ - uses: actions/setup-node@v4
307
+ with:
308
+ node-version: '20'
309
+ cache: 'npm'
310
+ - run: npm ci
311
+ - run: npm run test:run
312
+ - run: npm run build
313
+ ```
314
+
315
+ After scaffolding complete:
316
+ "✅ App scaffolded. Run `npm run dev` to start. First test is green.
317
+ Use `/spartan:next-feature [name]` to build individual features."
@@ -0,0 +1,212 @@
1
+ ---
2
+ name: spartan:next-feature
3
+ description: Scaffold a new Next.js feature following App Router conventions — pages, components, server actions, types, and tests.
4
+ argument-hint: "[feature name] [brief description]"
5
+ ---
6
+
7
+ # Next.js Feature: {{ args[0] }}
8
+ Description: {{ args[1] }}
9
+
10
+ You are scaffolding a new Next.js feature following **App Router** conventions for the Spartan frontend.
11
+
12
+ ---
13
+
14
+ ## Step 1: Clarify before building
15
+
16
+ Ask the user:
17
+ 1. Is this a **page** (new route), a **component** (reusable UI), or a **feature** (page + components + logic)?
18
+ 2. Does it need **data fetching** from the Kotlin BE? If yes, which API endpoints?
19
+ 3. Is any part **interactive** (needs `'use client'`)? What interactions?
20
+ 4. Any **auth/access control** requirements?
21
+
22
+ **Auto mode on?** → Infer answers from the feature name and codebase context. Assume "feature" type, check existing API patterns, proceed immediately.
23
+ **Auto mode off?** → Wait for answers, then proceed.
24
+
25
+ ---
26
+
27
+ ## Step 1.5: Check for design tokens (silent)
28
+
29
+ ```bash
30
+ ls .planning/design/system/tokens.md .planning/design-config.md 2>/dev/null
31
+ ```
32
+
33
+ If design tokens exist, read them. All scaffolded components MUST use project tokens:
34
+ - Use project colors in default styles, not Tailwind defaults
35
+ - Use project font in any typography
36
+ - Import from the project's design token file if it exists (e.g., `@/lib/design-tokens`)
37
+
38
+ If NO tokens exist, scaffold with clean, unstyled components. Use `bg-neutral-*` placeholder styles that are obviously temporary. Don't use `bg-blue-500` or other Tailwind color defaults.
39
+
40
+ ---
41
+
42
+ ## Step 2: Map the directory structure
43
+
44
+ Based on answers, propose this structure under `app/` or `components/`:
45
+
46
+ ```
47
+ # For a new PAGE feature:
48
+ app/[feature-name]/
49
+ page.tsx ← Server Component (data fetching here)
50
+ page.test.tsx ← Tests
51
+ layout.tsx ← Only if needs own layout
52
+ loading.tsx ← Loading UI (Suspense boundary)
53
+ error.tsx ← Error boundary
54
+ _components/ ← Feature-local components
55
+ FeatureCard.tsx
56
+ FeatureCard.test.tsx
57
+ _actions/ ← Server Actions for mutations
58
+ createFeature.ts
59
+ updateFeature.ts
60
+ _types/ ← TypeScript types
61
+ feature.types.ts
62
+
63
+ # For a reusable COMPONENT:
64
+ components/[ComponentName]/
65
+ [ComponentName].tsx
66
+ [ComponentName].test.tsx
67
+ [ComponentName].stories.tsx ← If using Storybook
68
+ index.ts ← Re-export
69
+ ```
70
+
71
+ ---
72
+
73
+ ## Step 3: Create types first
74
+
75
+ In `_types/feature.types.ts`:
76
+
77
+ ```typescript
78
+ // Mirror the Kotlin DTO structure from BE
79
+ export interface FeatureDto {
80
+ id: string
81
+ // ... fields from BE response
82
+ createdAt: string // ISO string from BE
83
+ }
84
+
85
+ // For API responses — always typed
86
+ export interface ApiResponse<T> {
87
+ data: T
88
+ message?: string
89
+ }
90
+
91
+ // For form/mutation input
92
+ export interface CreateFeatureInput {
93
+ // ...
94
+ }
95
+ ```
96
+
97
+ ---
98
+
99
+ ## Step 4: Create API client
100
+
101
+ ```typescript
102
+ // lib/api/feature.api.ts
103
+
104
+ import { FeatureDto, CreateFeatureInput } from '@/app/[feature]/_types/feature.types'
105
+
106
+ export async function getFeature(id: string): Promise<FeatureDto> {
107
+ const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/v1/features/${id}`, {
108
+ next: { revalidate: 60 }, // ISR: revalidate every 60s
109
+ })
110
+
111
+ if (!res.ok) {
112
+ throw new Error(`Failed to fetch feature: ${res.status}`)
113
+ }
114
+
115
+ return res.json()
116
+ }
117
+
118
+ export async function createFeature(input: CreateFeatureInput): Promise<FeatureDto> {
119
+ const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/v1/features`, {
120
+ method: 'POST',
121
+ headers: { 'Content-Type': 'application/json' },
122
+ body: JSON.stringify(input),
123
+ })
124
+
125
+ if (!res.ok) {
126
+ const error = await res.json()
127
+ throw new Error(error.message || 'Failed to create feature')
128
+ }
129
+
130
+ return res.json()
131
+ }
132
+ ```
133
+
134
+ ---
135
+
136
+ ## Step 5: Create Server Component page
137
+
138
+ ```typescript
139
+ // app/[feature-name]/page.tsx
140
+ import { getFeature } from '@/lib/api/feature.api'
141
+ import { FeatureCard } from './_components/FeatureCard'
142
+
143
+ // Metadata for SEO
144
+ export const metadata = {
145
+ title: '[Feature Name] | Spartan',
146
+ }
147
+
148
+ interface PageProps {
149
+ params: { id: string }
150
+ searchParams: { [key: string]: string | undefined }
151
+ }
152
+
153
+ export default async function FeaturePage({ params }: PageProps) {
154
+ // Data fetching directly in Server Component
155
+ const feature = await getFeature(params.id)
156
+
157
+ return (
158
+ <main>
159
+ <FeatureCard feature={feature} />
160
+ </main>
161
+ )
162
+ }
163
+ ```
164
+
165
+ ---
166
+
167
+ ## Step 6: Write tests FIRST (TDD)
168
+
169
+ ```typescript
170
+ // page.test.tsx — Server Component test
171
+ import { render, screen } from '@testing-library/react'
172
+ import { describe, it, expect, vi } from 'vitest'
173
+ import FeaturePage from './page'
174
+
175
+ // Mock the API call
176
+ vi.mock('@/lib/api/feature.api', () => ({
177
+ getFeature: vi.fn()
178
+ }))
179
+
180
+ describe('FeaturePage', () => {
181
+ it('renders feature data when loaded', async () => {
182
+ // given
183
+ const mockFeature = { id: '1', name: 'Test Feature' }
184
+ vi.mocked(getFeature).mockResolvedValue(mockFeature)
185
+
186
+ // when
187
+ const page = await FeaturePage({ params: { id: '1' }, searchParams: {} })
188
+ render(page)
189
+
190
+ // then
191
+ expect(screen.getByText('Test Feature')).toBeInTheDocument()
192
+ })
193
+ })
194
+ ```
195
+
196
+ ---
197
+
198
+ ## Step 7: Environment variables check
199
+
200
+ Ensure these are set in `.env.local` (and in Railway env vars):
201
+ ```
202
+ NEXT_PUBLIC_API_URL=http://localhost:8080 # local
203
+ # Railway: set to production BE service URL
204
+ ```
205
+
206
+ After scaffolding, run:
207
+ ```bash
208
+ npm run dev
209
+ npm test -- --watch [feature-name]
210
+ ```
211
+
212
+ Say: "Feature scaffolded. First failing test written. Say **'go'** to implement."