@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.
- package/.claude-plugin/marketplace.json +16 -0
- package/.claude-plugin/plugin.json +12 -0
- package/README.md +439 -0
- package/VERSION +1 -0
- package/agents/design-critic.md +127 -0
- package/agents/idea-killer.md +72 -0
- package/agents/infrastructure-expert.md +49 -0
- package/agents/micronaut-backend-expert.md +45 -0
- package/agents/phase-reviewer.md +150 -0
- package/agents/research-planner.md +70 -0
- package/agents/solution-architect-cto.md +49 -0
- package/agents/sre-architect.md +49 -0
- package/agents/team-coordinator.md +111 -0
- package/bin/cli.js +780 -0
- package/claude-md/00-header.md +39 -0
- package/claude-md/01-core.md +105 -0
- package/claude-md/05-database.md +20 -0
- package/claude-md/11-backend-micronaut.md +19 -0
- package/claude-md/20-frontend-react.md +44 -0
- package/claude-md/25-ux-design.md +56 -0
- package/claude-md/30-infrastructure.md +24 -0
- package/claude-md/30-project-mgmt.md +119 -0
- package/claude-md/40-product.md +39 -0
- package/claude-md/50-ops.md +34 -0
- package/claude-md/60-research.md +27 -0
- package/claude-md/90-footer.md +21 -0
- package/commands/spartan/brainstorm.md +134 -0
- package/commands/spartan/brownfield.md +157 -0
- package/commands/spartan/build.md +435 -0
- package/commands/spartan/careful.md +94 -0
- package/commands/spartan/commit-message.md +112 -0
- package/commands/spartan/content.md +17 -0
- package/commands/spartan/context-save.md +161 -0
- package/commands/spartan/contribute.md +140 -0
- package/commands/spartan/daily.md +42 -0
- package/commands/spartan/debug.md +308 -0
- package/commands/spartan/deep-dive.md +55 -0
- package/commands/spartan/deploy.md +207 -0
- package/commands/spartan/e2e.md +264 -0
- package/commands/spartan/env-setup.md +166 -0
- package/commands/spartan/epic.md +199 -0
- package/commands/spartan/fe-review.md +181 -0
- package/commands/spartan/figma-to-code.md +260 -0
- package/commands/spartan/forensics.md +46 -0
- package/commands/spartan/freeze.md +84 -0
- package/commands/spartan/fundraise.md +53 -0
- package/commands/spartan/gate-review.md +229 -0
- package/commands/spartan/gsd-upgrade.md +376 -0
- package/commands/spartan/guard.md +42 -0
- package/commands/spartan/init-project.md +178 -0
- package/commands/spartan/init-rules.md +298 -0
- package/commands/spartan/interview.md +154 -0
- package/commands/spartan/kickoff.md +73 -0
- package/commands/spartan/kotlin-service.md +109 -0
- package/commands/spartan/lean-canvas.md +222 -0
- package/commands/spartan/lint-rules.md +122 -0
- package/commands/spartan/map-codebase.md +124 -0
- package/commands/spartan/migration.md +82 -0
- package/commands/spartan/next-app.md +317 -0
- package/commands/spartan/next-feature.md +212 -0
- package/commands/spartan/onboard.md +326 -0
- package/commands/spartan/outreach.md +16 -0
- package/commands/spartan/phase.md +142 -0
- package/commands/spartan/pitch.md +18 -0
- package/commands/spartan/plan.md +210 -0
- package/commands/spartan/pr-ready.md +202 -0
- package/commands/spartan/project.md +106 -0
- package/commands/spartan/qa.md +222 -0
- package/commands/spartan/research.md +254 -0
- package/commands/spartan/review.md +132 -0
- package/commands/spartan/scan-rules.md +173 -0
- package/commands/spartan/sessions.md +143 -0
- package/commands/spartan/spec.md +131 -0
- package/commands/spartan/startup.md +257 -0
- package/commands/spartan/team.md +570 -0
- package/commands/spartan/teardown.md +161 -0
- package/commands/spartan/testcontainer.md +97 -0
- package/commands/spartan/tf-cost.md +123 -0
- package/commands/spartan/tf-deploy.md +116 -0
- package/commands/spartan/tf-drift.md +100 -0
- package/commands/spartan/tf-import.md +107 -0
- package/commands/spartan/tf-module.md +121 -0
- package/commands/spartan/tf-plan.md +100 -0
- package/commands/spartan/tf-review.md +106 -0
- package/commands/spartan/tf-scaffold.md +109 -0
- package/commands/spartan/tf-security.md +147 -0
- package/commands/spartan/think.md +221 -0
- package/commands/spartan/unfreeze.md +13 -0
- package/commands/spartan/update.md +134 -0
- package/commands/spartan/ux.md +1233 -0
- package/commands/spartan/validate.md +193 -0
- package/commands/spartan/web-to-prd.md +706 -0
- package/commands/spartan/workstreams.md +109 -0
- package/commands/spartan/write.md +16 -0
- package/commands/spartan.md +386 -0
- package/frameworks/00-framework-comparison-guide.md +317 -0
- package/frameworks/01-lean-canvas.md +196 -0
- package/frameworks/02-design-sprint.md +304 -0
- package/frameworks/03-foundation-sprint.md +337 -0
- package/frameworks/04-business-model-canvas.md +391 -0
- package/frameworks/05-customer-development.md +426 -0
- package/frameworks/06-jobs-to-be-done.md +358 -0
- package/frameworks/07-mom-test.md +392 -0
- package/frameworks/08-value-proposition-canvas.md +488 -0
- package/frameworks/09-javelin-board.md +428 -0
- package/frameworks/10-build-measure-learn.md +467 -0
- package/frameworks/11-mvp-approaches.md +533 -0
- package/frameworks/think-before-build.md +593 -0
- package/lib/assembler.js +197 -0
- package/lib/assembler.test.js +159 -0
- package/lib/detector.js +166 -0
- package/lib/detector.test.js +221 -0
- package/lib/packs.js +16 -0
- package/lib/resolver.js +272 -0
- package/lib/resolver.test.js +298 -0
- package/lib/worktree.sh +104 -0
- package/package.json +50 -0
- package/packs/backend-micronaut.yaml +35 -0
- package/packs/backend-nodejs.yaml +15 -0
- package/packs/backend-python.yaml +15 -0
- package/packs/core.yaml +37 -0
- package/packs/database.yaml +21 -0
- package/packs/frontend-react.yaml +24 -0
- package/packs/infrastructure.yaml +40 -0
- package/packs/ops.yaml +16 -0
- package/packs/packs.compiled.json +371 -0
- package/packs/product.yaml +22 -0
- package/packs/project-mgmt.yaml +24 -0
- package/packs/research.yaml +39 -0
- package/packs/shared-backend.yaml +14 -0
- package/packs/ux-design.yaml +21 -0
- package/rules/backend-micronaut/API_DESIGN.md +313 -0
- package/rules/backend-micronaut/BATCH_PROCESSING.md +92 -0
- package/rules/backend-micronaut/CONTROLLERS.md +388 -0
- package/rules/backend-micronaut/KOTLIN.md +414 -0
- package/rules/backend-micronaut/RETROFIT_PLACEMENT.md +290 -0
- package/rules/backend-micronaut/SERVICES_AND_BEANS.md +325 -0
- package/rules/core/NAMING_CONVENTIONS.md +208 -0
- package/rules/core/SKILL_AUTHORING.md +174 -0
- package/rules/core/TIMEZONE.md +316 -0
- package/rules/database/ORM_AND_REPO.md +289 -0
- package/rules/database/SCHEMA.md +146 -0
- package/rules/database/TRANSACTIONS.md +311 -0
- package/rules/frontend-react/FRONTEND.md +344 -0
- package/rules/infrastructure/MODULES.md +260 -0
- package/rules/infrastructure/NAMING.md +196 -0
- package/rules/infrastructure/PROVIDERS.md +309 -0
- package/rules/infrastructure/SECURITY.md +310 -0
- package/rules/infrastructure/STATE_AND_BACKEND.md +237 -0
- package/rules/infrastructure/STRUCTURE.md +234 -0
- package/rules/infrastructure/VARIABLES.md +285 -0
- package/rules/shared-backend/ARCHITECTURE.md +46 -0
- package/rules/ux-design/DESIGN_PROCESS.md +176 -0
- package/skills/api-endpoint-creator/SKILL.md +455 -0
- package/skills/api-endpoint-creator/error-handling-guide.md +244 -0
- package/skills/api-endpoint-creator/examples.md +522 -0
- package/skills/api-endpoint-creator/testing-patterns.md +302 -0
- package/skills/article-writing/SKILL.md +109 -0
- package/skills/article-writing/examples.md +59 -0
- package/skills/backend-api-design/SKILL.md +84 -0
- package/skills/backend-api-design/code-patterns.md +138 -0
- package/skills/brainstorm/SKILL.md +95 -0
- package/skills/browser-qa/SKILL.md +87 -0
- package/skills/browser-qa/playwright-snippets.md +110 -0
- package/skills/ci-cd-patterns/SKILL.md +108 -0
- package/skills/ci-cd-patterns/workflows.md +149 -0
- package/skills/competitive-teardown/SKILL.md +93 -0
- package/skills/competitive-teardown/example-analysis.md +50 -0
- package/skills/content-engine/SKILL.md +131 -0
- package/skills/content-engine/examples.md +72 -0
- package/skills/database-patterns/SKILL.md +72 -0
- package/skills/database-patterns/code-templates.md +114 -0
- package/skills/database-table-creator/SKILL.md +141 -0
- package/skills/database-table-creator/examples.md +552 -0
- package/skills/database-table-creator/kotlin-templates.md +400 -0
- package/skills/database-table-creator/migration-template.sql +68 -0
- package/skills/database-table-creator/validation-checklist.md +337 -0
- package/skills/deep-research/SKILL.md +80 -0
- package/skills/design-intelligence/SKILL.md +268 -0
- package/skills/design-workflow/SKILL.md +127 -0
- package/skills/design-workflow/checklists.md +45 -0
- package/skills/idea-validation/SKILL.md +129 -0
- package/skills/idea-validation/example-report.md +50 -0
- package/skills/investor-materials/SKILL.md +122 -0
- package/skills/investor-materials/example-outline.md +70 -0
- package/skills/investor-outreach/SKILL.md +112 -0
- package/skills/investor-outreach/examples.md +76 -0
- package/skills/kotlin-best-practices/SKILL.md +58 -0
- package/skills/kotlin-best-practices/code-patterns.md +132 -0
- package/skills/market-research/SKILL.md +99 -0
- package/skills/security-checklist/SKILL.md +65 -0
- package/skills/security-checklist/audit-reference.md +95 -0
- package/skills/service-debugging/SKILL.md +116 -0
- package/skills/service-debugging/common-issues.md +65 -0
- package/skills/startup-pipeline/SKILL.md +152 -0
- package/skills/terraform-best-practices/SKILL.md +244 -0
- package/skills/terraform-module-creator/SKILL.md +284 -0
- package/skills/terraform-review/SKILL.md +222 -0
- package/skills/terraform-security-audit/SKILL.md +280 -0
- package/skills/terraform-service-scaffold/SKILL.md +574 -0
- package/skills/testing-strategies/SKILL.md +116 -0
- package/skills/testing-strategies/examples.md +103 -0
- package/skills/testing-strategies/integration-test-setup.md +71 -0
- package/skills/ui-ux-pro-max/SKILL.md +238 -0
- package/skills/ui-ux-pro-max/data/charts.csv +26 -0
- package/skills/ui-ux-pro-max/data/colors.csv +97 -0
- package/skills/ui-ux-pro-max/data/icons.csv +101 -0
- package/skills/ui-ux-pro-max/data/landing.csv +31 -0
- package/skills/ui-ux-pro-max/data/products.csv +97 -0
- package/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
- package/skills/ui-ux-pro-max/data/stacks/astro.csv +54 -0
- package/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
- package/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
- package/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
- package/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
- package/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
- package/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
- package/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
- package/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
- package/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
- package/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
- package/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
- package/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
- package/skills/ui-ux-pro-max/data/styles.csv +68 -0
- package/skills/ui-ux-pro-max/data/typography.csv +58 -0
- package/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
- package/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
- package/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
- package/skills/ui-ux-pro-max/python-setup.md +146 -0
- package/skills/ui-ux-pro-max/scripts/core.py +253 -0
- package/skills/ui-ux-pro-max/scripts/design_system.py +1067 -0
- package/skills/ui-ux-pro-max/scripts/search.py +114 -0
- package/skills/web-to-prd/SKILL.md +478 -0
- package/templates/build-config.yaml +44 -0
- package/templates/commands-config.yaml +55 -0
- package/templates/competitor-analysis.md +60 -0
- package/templates/content/AGENT_TEMPLATE.md +47 -0
- package/templates/content/COMMAND_TEMPLATE.md +27 -0
- package/templates/content/RULE_TEMPLATE.md +40 -0
- package/templates/content/SKILL_TEMPLATE.md +41 -0
- package/templates/design-config.md +105 -0
- package/templates/design-doc.md +207 -0
- package/templates/epic.md +100 -0
- package/templates/feature-spec.md +181 -0
- package/templates/idea-canvas.md +47 -0
- package/templates/implementation-plan.md +159 -0
- package/templates/prd-template.md +86 -0
- package/templates/preamble.md +89 -0
- package/templates/project-readme.md +35 -0
- package/templates/quality-gates.md +230 -0
- package/templates/spartan-config.yaml +164 -0
- package/templates/user-interview.md +69 -0
- package/templates/validation-checklist.md +108 -0
- package/templates/workflow-backend-micronaut.md +409 -0
- package/templates/workflow-frontend-react.md +233 -0
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
# Backend Workflow: Kotlin + Micronaut
|
|
2
|
+
|
|
3
|
+
> **Prefer `/spartan:build backend "feature"`** — it automates this workflow with gates and skill routing. Use this template as a manual reference when not using the Build workflow.
|
|
4
|
+
|
|
5
|
+
**Rules enforced:** `KOTLIN.md`, `CONTROLLERS.md`, `SERVICES_AND_BEANS.md`, `API_DESIGN.md`, `RETROFIT_PLACEMENT.md`, `SCHEMA.md`, `ORM_AND_REPO.md`, `TRANSACTIONS.md`, `ARCHITECTURE.md`
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## The Workflow
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
Epic → Spec → Plan → Build → Review
|
|
13
|
+
↑ ↑ ↑ ↑
|
|
14
|
+
Gate 1 Gate 2 Gate 3 Gate 4
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Module Structure
|
|
20
|
+
|
|
21
|
+
A typical Micronaut monorepo follows this layout:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
{service}/
|
|
25
|
+
├── database-migration/sql/ # Migration SQL files
|
|
26
|
+
├── app/
|
|
27
|
+
│ ├── api-application/ # Controllers, managers, factories, tests
|
|
28
|
+
│ │ └── src/main/kotlin/.../
|
|
29
|
+
│ │ ├── controller/ # HTTP endpoints (thin)
|
|
30
|
+
│ │ ├── manager/ # Business logic
|
|
31
|
+
│ │ └── runtime/factory/ # Bean wiring
|
|
32
|
+
│ ├── module-client/ # Request/response DTOs (shared)
|
|
33
|
+
│ │ └── src/main/kotlin/.../
|
|
34
|
+
│ │ ├── request/{domain}/ # Input models
|
|
35
|
+
│ │ └── response/ # Output models
|
|
36
|
+
│ ├── module-repository/ # Database layer
|
|
37
|
+
│ │ └── src/main/kotlin/.../postgresql/
|
|
38
|
+
│ │ ├── table/ # Exposed Table objects
|
|
39
|
+
│ │ ├── entity/ # Entity classes
|
|
40
|
+
│ │ └── repository/ # Data access
|
|
41
|
+
│ ├── module-exception/ # Error types
|
|
42
|
+
│ └── module-{feature}/ # Feature modules (for larger features)
|
|
43
|
+
│ ├── module-api/ # Interface (contract)
|
|
44
|
+
│ └── module-impl/ # Implementation + factory
|
|
45
|
+
└── core/ # Shared across services
|
|
46
|
+
├── module-database/ # DatabaseContext, transactions
|
|
47
|
+
├── module-retrofit/ # HTTP client
|
|
48
|
+
└── module-config/ # Configuration
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Phase Guide
|
|
54
|
+
|
|
55
|
+
### Spec Phase — what to define
|
|
56
|
+
|
|
57
|
+
The spec for a backend feature should include:
|
|
58
|
+
|
|
59
|
+
**Data model:**
|
|
60
|
+
- Tables with standard columns: `id` (UUID), `created_at`, `updated_at`, `deleted_at`
|
|
61
|
+
- Use TEXT not VARCHAR (see `SCHEMA.md`)
|
|
62
|
+
- No foreign key constraints (see `SCHEMA.md`)
|
|
63
|
+
- Soft delete via `deleted_at` column
|
|
64
|
+
- Include `update_updated_at()` trigger
|
|
65
|
+
|
|
66
|
+
**API contract:**
|
|
67
|
+
- RPC-style endpoints (see `API_DESIGN.md`)
|
|
68
|
+
- Query parameters only — no path parameters
|
|
69
|
+
- snake_case JSON in all responses
|
|
70
|
+
- Request/response models in `module-client`
|
|
71
|
+
|
|
72
|
+
**Example spec sections:**
|
|
73
|
+
|
|
74
|
+
```sql
|
|
75
|
+
-- Data Model
|
|
76
|
+
CREATE TABLE user_profiles (
|
|
77
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
78
|
+
user_id UUID NOT NULL,
|
|
79
|
+
display_name TEXT NOT NULL,
|
|
80
|
+
bio TEXT,
|
|
81
|
+
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
82
|
+
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
83
|
+
deleted_at TIMESTAMP
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
CREATE INDEX idx_user_profiles_user_id ON user_profiles(user_id) WHERE deleted_at IS NULL;
|
|
87
|
+
|
|
88
|
+
CREATE TRIGGER update_user_profiles_updated_at
|
|
89
|
+
BEFORE UPDATE ON user_profiles
|
|
90
|
+
FOR EACH ROW EXECUTE FUNCTION update_updated_at();
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
-- API Contract
|
|
95
|
+
POST /api/v1/user-profile/create
|
|
96
|
+
GET /api/v1/user-profile/get?user_id=xxx
|
|
97
|
+
POST /api/v1/user-profile/update
|
|
98
|
+
POST /api/v1/user-profile/delete
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
### Plan Phase — how to structure tasks
|
|
104
|
+
|
|
105
|
+
Break into these phases:
|
|
106
|
+
|
|
107
|
+
#### Phase 1: Database
|
|
108
|
+
| # | Task | Files | Reference |
|
|
109
|
+
|---|------|-------|-----------|
|
|
110
|
+
| 1 | Create migration SQL | `database-migration/sql/NNN-{description}.sql` | `SCHEMA.md` |
|
|
111
|
+
| 2 | Create Table object | `module-repository/.../table/{Name}Table.kt` (extends `UUIDTable`) | `ORM_AND_REPO.md` |
|
|
112
|
+
| 3 | Create Entity class | `module-repository/.../entity/{Name}Entity.kt` (implements `Entity<Instant>`) | `ORM_AND_REPO.md` |
|
|
113
|
+
| 4 | Create Repository | `module-repository/.../repository/{Name}Repository.kt` + `Default{Name}Repository.kt` | `ORM_AND_REPO.md` |
|
|
114
|
+
|
|
115
|
+
#### Phase 2: Business Logic
|
|
116
|
+
| # | Task | Files | Reference |
|
|
117
|
+
|---|------|-------|-----------|
|
|
118
|
+
| 5 | Create Manager interface | `api-application/.../manager/{Name}Manager.kt` (or `module-{name}/module-api`) | `SERVICES_AND_BEANS.md` |
|
|
119
|
+
| 6 | Create Manager implementation | `api-application/.../manager/Default{Name}Manager.kt` (or `module-{name}/module-impl`) | `SERVICES_AND_BEANS.md` |
|
|
120
|
+
| 7 | Create request/response models | `module-client/.../request/{domain}/{Name}Request.kt` + `module-client/.../response/{Name}Response.kt` | `API_DESIGN.md` |
|
|
121
|
+
|
|
122
|
+
#### Phase 3: API Layer
|
|
123
|
+
| # | Task | Files | Reference |
|
|
124
|
+
|---|------|-------|-----------|
|
|
125
|
+
| 8 | Create Controller | `api-application/.../controller/{Name}Controller.kt` | `CONTROLLERS.md` |
|
|
126
|
+
| 9 | Create/update Factory beans | `api-application/.../runtime/factory/{Name}Factory.kt` (or update `ManagerFactory.kt`) | `SERVICES_AND_BEANS.md` |
|
|
127
|
+
|
|
128
|
+
#### Phase 4: Tests
|
|
129
|
+
| # | Task | Files | Reference |
|
|
130
|
+
|---|------|-------|-----------|
|
|
131
|
+
| 10 | Repository tests | `module-repository/src/test/.../Default{Name}RepositoryTest.kt` | `testing-strategies` skill |
|
|
132
|
+
| 11 | Manager unit tests | `api-application/src/test/.../Default{Name}ManagerTest.kt` | `testing-strategies` skill |
|
|
133
|
+
| 12 | Controller integration tests | `api-application/src/test/.../{Name}ControllerTest.kt` (Retrofit client) | `testing-strategies` skill |
|
|
134
|
+
|
|
135
|
+
**Parallel groups:**
|
|
136
|
+
- Tasks 1-3 can run in parallel (migration, table, entity are independent files)
|
|
137
|
+
- Tasks 5, 7 can run in parallel (manager interface and models don't depend on each other)
|
|
138
|
+
- Tasks 10-12 can run in parallel (tests are independent)
|
|
139
|
+
|
|
140
|
+
**Sequential:**
|
|
141
|
+
- Task 4 needs 1-3 (repository needs table + entity)
|
|
142
|
+
- Task 6 needs 4, 5 (implementation needs repository + interface)
|
|
143
|
+
- Task 8 needs 6, 7 (controller needs manager + models)
|
|
144
|
+
- Task 9 needs 6 (factory needs manager implementation)
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Code Patterns
|
|
149
|
+
|
|
150
|
+
### Controller Pattern
|
|
151
|
+
|
|
152
|
+
```kotlin
|
|
153
|
+
@ExecuteOn(TaskExecutors.IO)
|
|
154
|
+
@Validated
|
|
155
|
+
@Controller("/api/v1/user-profile")
|
|
156
|
+
@Secured(SecurityRule.IS_AUTHENTICATED)
|
|
157
|
+
class UserProfileController(
|
|
158
|
+
private val userProfileManager: UserProfileManager,
|
|
159
|
+
) {
|
|
160
|
+
@Post("/create")
|
|
161
|
+
suspend fun create(@Body request: CreateUserProfileRequest): UserProfileResponse {
|
|
162
|
+
return userProfileManager.create(request).throwOrValue()
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
@Get("/get")
|
|
166
|
+
suspend fun get(@QueryValue userId: UUID): UserProfileResponse {
|
|
167
|
+
return userProfileManager.getByUserId(userId).throwOrValue()
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Key points: `suspend` functions, `@ExecuteOn(IO)`, `@QueryValue` (not path params), `.throwOrValue()` to unwrap Either.
|
|
173
|
+
|
|
174
|
+
### Manager Pattern
|
|
175
|
+
|
|
176
|
+
```kotlin
|
|
177
|
+
interface UserProfileManager {
|
|
178
|
+
suspend fun create(request: CreateUserProfileRequest): Either<ClientException, UserProfileResponse>
|
|
179
|
+
suspend fun getByUserId(userId: UUID): Either<ClientException, UserProfileResponse>
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
@Singleton
|
|
183
|
+
class DefaultUserProfileManager(
|
|
184
|
+
private val userProfileRepository: UserProfileRepository,
|
|
185
|
+
private val db: DatabaseContext,
|
|
186
|
+
) : UserProfileManager {
|
|
187
|
+
|
|
188
|
+
override suspend fun create(request: CreateUserProfileRequest): Either<ClientException, UserProfileResponse> {
|
|
189
|
+
return either {
|
|
190
|
+
val entity = db.primary {
|
|
191
|
+
userProfileRepository.create(request)
|
|
192
|
+
}
|
|
193
|
+
UserProfileResponse.from(entity)
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Key points: returns `Either<ClientException, T>`, `db.primary {}` for writes, `db.replica {}` for reads.
|
|
200
|
+
|
|
201
|
+
### Repository Pattern
|
|
202
|
+
|
|
203
|
+
```kotlin
|
|
204
|
+
interface UserProfileRepository {
|
|
205
|
+
fun create(request: CreateUserProfileRequest): UserProfileEntity
|
|
206
|
+
fun findByUserId(userId: UUID): UserProfileEntity?
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
class DefaultUserProfileRepository : UserProfileRepository {
|
|
210
|
+
override fun findByUserId(userId: UUID): UserProfileEntity? {
|
|
211
|
+
return UserProfileEntity.find {
|
|
212
|
+
(UserProfileTable.userId eq userId) and (UserProfileTable.deletedAt.isNull())
|
|
213
|
+
}.firstOrNull()
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Key points: always filter `deletedAt.isNull()`, soft delete sets `deletedAt` (never hard delete).
|
|
219
|
+
|
|
220
|
+
### Response DTO Pattern
|
|
221
|
+
|
|
222
|
+
```kotlin
|
|
223
|
+
@Serdeable
|
|
224
|
+
data class UserProfileResponse(
|
|
225
|
+
val id: UUID,
|
|
226
|
+
val userId: UUID,
|
|
227
|
+
val displayName: String,
|
|
228
|
+
val bio: String?,
|
|
229
|
+
val createdAt: Instant,
|
|
230
|
+
) {
|
|
231
|
+
companion object {
|
|
232
|
+
fun from(entity: UserProfileEntity) = UserProfileResponse(
|
|
233
|
+
id = entity.id.value,
|
|
234
|
+
userId = entity.userId,
|
|
235
|
+
displayName = entity.displayName,
|
|
236
|
+
bio = entity.bio,
|
|
237
|
+
createdAt = entity.createdAt,
|
|
238
|
+
)
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Key points: `@Serdeable`, `companion object { fun from() }` for conversion, camelCase in code (Jackson auto-converts to snake_case).
|
|
244
|
+
|
|
245
|
+
### Factory Pattern
|
|
246
|
+
|
|
247
|
+
```kotlin
|
|
248
|
+
@Factory
|
|
249
|
+
class UserProfileFactory(
|
|
250
|
+
private val userProfileRepository: UserProfileRepository,
|
|
251
|
+
private val db: DatabaseContext,
|
|
252
|
+
) {
|
|
253
|
+
@Singleton
|
|
254
|
+
fun userProfileManager(): UserProfileManager {
|
|
255
|
+
return DefaultUserProfileManager(userProfileRepository, db)
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Key points: `@Factory` class, `@Singleton` method, returns interface type, constructs `Default*` implementation.
|
|
261
|
+
|
|
262
|
+
### Test Pattern
|
|
263
|
+
|
|
264
|
+
```kotlin
|
|
265
|
+
@MicronautTest(environments = ["test"], transactional = false)
|
|
266
|
+
class UserProfileControllerTest : AbstractControllerTest() {
|
|
267
|
+
|
|
268
|
+
@Inject
|
|
269
|
+
lateinit var client: UserProfileClient // Retrofit client
|
|
270
|
+
|
|
271
|
+
@Test
|
|
272
|
+
fun `create user profile - success`() = runTest {
|
|
273
|
+
val request = CreateUserProfileRequest(
|
|
274
|
+
userId = UUID.randomUUID(),
|
|
275
|
+
displayName = "Test User",
|
|
276
|
+
)
|
|
277
|
+
val response = client.create(request)
|
|
278
|
+
assertThat(response.displayName).isEqualTo("Test User")
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
Key points: `@MicronautTest`, Retrofit client injection, `runTest` for coroutines, assertk assertions.
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
## Quality Gates — Backend Specific
|
|
288
|
+
|
|
289
|
+
### Gate 1: Spec Review (Backend)
|
|
290
|
+
|
|
291
|
+
Everything from the generic Gate 1, plus:
|
|
292
|
+
|
|
293
|
+
**Data Model (SCHEMA.md):**
|
|
294
|
+
- [ ] Uses TEXT not VARCHAR
|
|
295
|
+
- [ ] Uses UUID for primary keys
|
|
296
|
+
- [ ] Has `id`, `created_at`, `updated_at`, `deleted_at` columns
|
|
297
|
+
- [ ] No foreign key constraints
|
|
298
|
+
- [ ] `update_updated_at()` trigger in migration
|
|
299
|
+
- [ ] Indexes include `WHERE deleted_at IS NULL`
|
|
300
|
+
|
|
301
|
+
**API Design (API_DESIGN.md):**
|
|
302
|
+
- [ ] RPC-style endpoints (verb-based: `/create`, `/get`, `/update`, `/delete`)
|
|
303
|
+
- [ ] Uses query parameters, not path parameters
|
|
304
|
+
- [ ] Response models use snake_case JSON
|
|
305
|
+
- [ ] Request/response models planned for `module-client`
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
### Gate 2: Plan Review (Backend)
|
|
310
|
+
|
|
311
|
+
Everything from the generic Gate 2, plus:
|
|
312
|
+
|
|
313
|
+
**Architecture (ARCHITECTURE.md, CONTROLLERS.md):**
|
|
314
|
+
- [ ] Follows layered design: Controller → Manager → Repository
|
|
315
|
+
- [ ] Controllers only call managers (not repositories directly)
|
|
316
|
+
- [ ] Managers wrap DB operations via `db.primary {}` / `db.replica {}`
|
|
317
|
+
- [ ] Bean management follows 3-tier hierarchy (SERVICES_AND_BEANS.md)
|
|
318
|
+
|
|
319
|
+
**File Locations:**
|
|
320
|
+
- [ ] Migrations in `database-migration/sql/`
|
|
321
|
+
- [ ] Table/Entity/Repository in `module-repository`
|
|
322
|
+
- [ ] Manager interface in feature module's `module-api` or in `api-application`
|
|
323
|
+
- [ ] Manager implementation in feature module's `module-impl` or in `api-application`
|
|
324
|
+
- [ ] Request/response models in `module-client`
|
|
325
|
+
- [ ] Controller in `api-application`
|
|
326
|
+
- [ ] Factory in `api-application/runtime/factory/` or feature module's `module-impl`
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
### Gate 3: Implementation Review (Backend)
|
|
331
|
+
|
|
332
|
+
Everything from the generic Gate 3, plus:
|
|
333
|
+
|
|
334
|
+
**Kotlin (KOTLIN.md):**
|
|
335
|
+
- [ ] No `!!` anywhere in the code
|
|
336
|
+
- [ ] Null safety via `?.`, `?:`, or explicit checks
|
|
337
|
+
- [ ] Error handling uses `Either<ClientException, T>`
|
|
338
|
+
- [ ] No `@Suppress` annotations
|
|
339
|
+
- [ ] Enums use companion object for lookup
|
|
340
|
+
- [ ] Response DTOs have `companion object { fun from() }` for conversion
|
|
341
|
+
|
|
342
|
+
**Architecture:**
|
|
343
|
+
- [ ] Controller is thin — `suspend` functions, `@ExecuteOn(TaskExecutors.IO)`, `.throwOrValue()`
|
|
344
|
+
- [ ] Manager returns `Either<ClientException, T>`, uses `db.primary {}` for writes
|
|
345
|
+
- [ ] Repository checks `deletedAt.isNull()` in all queries
|
|
346
|
+
- [ ] Soft delete sets `deletedAt`, never hard deletes
|
|
347
|
+
|
|
348
|
+
**Configuration:**
|
|
349
|
+
- [ ] No magic numbers — durations, timeouts, limits come from config
|
|
350
|
+
- [ ] Config values injected as config objects (not unpacked into individual constructor params)
|
|
351
|
+
- [ ] No inline fully-qualified imports
|
|
352
|
+
|
|
353
|
+
**Models:**
|
|
354
|
+
- [ ] Uses `@Serdeable` annotation
|
|
355
|
+
- [ ] JSON field names auto-converted to snake_case via Jackson
|
|
356
|
+
- [ ] Models in `module-client`
|
|
357
|
+
|
|
358
|
+
**Tests:**
|
|
359
|
+
- [ ] Uses Retrofit clients for API tests (not raw HttpRequest)
|
|
360
|
+
- [ ] Repository tests use Testcontainers
|
|
361
|
+
- [ ] Test class extends `AbstractControllerTest` (for integration tests)
|
|
362
|
+
- [ ] Uses `runTest` for coroutine tests
|
|
363
|
+
|
|
364
|
+
---
|
|
365
|
+
|
|
366
|
+
### Gate 4: Final Review (Backend)
|
|
367
|
+
|
|
368
|
+
Everything from the generic Gate 4, plus:
|
|
369
|
+
|
|
370
|
+
- [ ] `./gradlew test` passes
|
|
371
|
+
- [ ] `./gradlew ktlintCheck` passes
|
|
372
|
+
- [ ] `./gradlew clean build` passes
|
|
373
|
+
- [ ] No `!!` in any changed file
|
|
374
|
+
- [ ] No `@Suppress` in any changed file
|
|
375
|
+
- [ ] All controllers use `@ExecuteOn(TaskExecutors.IO)` and `suspend` functions
|
|
376
|
+
- [ ] All JSON uses snake_case (auto via Jackson)
|
|
377
|
+
- [ ] No magic numbers (grep for `ChronoUnit`, `.plus(` with hardcoded values)
|
|
378
|
+
- [ ] No inline fully-qualified imports (grep for `java.\w+.\w+.\w+(`)
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
## Quick Reference
|
|
383
|
+
|
|
384
|
+
| What | Where | Rule |
|
|
385
|
+
|------|-------|------|
|
|
386
|
+
| Migration SQL | `database-migration/sql/NNN-description.sql` | `SCHEMA.md` |
|
|
387
|
+
| Table object | `module-repository/.../postgresql/table/` | `ORM_AND_REPO.md` |
|
|
388
|
+
| Entity class | `module-repository/.../postgresql/entity/` | `ORM_AND_REPO.md` |
|
|
389
|
+
| Repository | `module-repository/.../postgresql/repository/` | `ORM_AND_REPO.md` |
|
|
390
|
+
| Manager interface | `api-application/.../manager/` or `module-{name}/module-api` | `SERVICES_AND_BEANS.md` |
|
|
391
|
+
| Manager impl | `api-application/.../manager/` or `module-{name}/module-impl` | `SERVICES_AND_BEANS.md` |
|
|
392
|
+
| Controller | `api-application/.../controller/` | `CONTROLLERS.md` |
|
|
393
|
+
| Factory | `api-application/.../runtime/factory/` | `SERVICES_AND_BEANS.md` |
|
|
394
|
+
| Request DTOs | `module-client/.../request/{domain}/` | `API_DESIGN.md` |
|
|
395
|
+
| Response DTOs | `module-client/.../response/` | `API_DESIGN.md` |
|
|
396
|
+
| Integration tests | `api-application/src/test/` | `testing-strategies` skill |
|
|
397
|
+
| Repository tests | `module-repository/src/test/` | `testing-strategies` skill |
|
|
398
|
+
|
|
399
|
+
## Related Skills & Commands
|
|
400
|
+
|
|
401
|
+
- `/spartan:kotlin-service` — scaffold a new Micronaut microservice
|
|
402
|
+
- `/spartan:review` — PR review with Kotlin/Micronaut conventions
|
|
403
|
+
- `/spartan:testcontainer` — set up Testcontainers
|
|
404
|
+
- `/spartan:migration` — create a database migration
|
|
405
|
+
- `/api-endpoint-creator` skill — generates the full Controller → Manager → Repository stack
|
|
406
|
+
- `/backend-api-design` skill — RPC-style API design patterns
|
|
407
|
+
- `/kotlin-best-practices` skill — null safety, Either, coroutines
|
|
408
|
+
- `/testing-strategies` skill — integration test patterns
|
|
409
|
+
- `/security-checklist` skill — auth, validation, OWASP
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# Frontend Workflow: React + Next.js
|
|
2
|
+
|
|
3
|
+
> **Prefer `/spartan:build frontend "feature"`** — it automates this workflow with gates and skill routing. Use this template as a manual reference when not using the Build workflow.
|
|
4
|
+
|
|
5
|
+
**Rules enforced:** `FRONTEND.md`
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## The Workflow
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
Epic → Spec → Design → Plan → Build → Review
|
|
13
|
+
↑ ↑ ↑ ↑
|
|
14
|
+
Gate 1 Gate 2 Gate 3 Gate 4
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Design is NOT optional for frontend features — always create a design doc for new screens/components.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Phase Guide
|
|
22
|
+
|
|
23
|
+
### Spec Phase — what to define
|
|
24
|
+
|
|
25
|
+
The spec for a frontend feature should include:
|
|
26
|
+
|
|
27
|
+
**UI Changes:**
|
|
28
|
+
- Which screens are new or changed
|
|
29
|
+
- User flows (step by step)
|
|
30
|
+
- States: loading, empty, error, success
|
|
31
|
+
- Mobile vs desktop differences
|
|
32
|
+
|
|
33
|
+
**API dependencies:**
|
|
34
|
+
- Which API endpoints does this feature call?
|
|
35
|
+
- Request/response shapes
|
|
36
|
+
- Are these endpoints new (needs backend work first) or existing?
|
|
37
|
+
|
|
38
|
+
**Example spec sections:**
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
-- UI Changes
|
|
42
|
+
New screen: /dashboard/analytics
|
|
43
|
+
- Shows chart with last 30 days of data
|
|
44
|
+
- Filter by date range, category
|
|
45
|
+
- Empty state when no data
|
|
46
|
+
- Mobile: stacked layout, swipeable charts
|
|
47
|
+
|
|
48
|
+
-- API Dependencies (existing)
|
|
49
|
+
GET /api/v1/analytics/summary?start_date=X&end_date=Y
|
|
50
|
+
GET /api/v1/analytics/chart-data?period=daily&category=X
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
### Design Phase — always do this for frontend
|
|
56
|
+
|
|
57
|
+
Use `design-doc.md` to define:
|
|
58
|
+
|
|
59
|
+
1. **User flows** — every interaction, step by step
|
|
60
|
+
2. **Screen inventory** — every screen with all states (loading, empty, error, success)
|
|
61
|
+
3. **Component list** — reusable components with props and states
|
|
62
|
+
4. **Wireframes** — ASCII or reference screenshots
|
|
63
|
+
5. **Responsive behavior** — what changes at mobile / tablet / desktop
|
|
64
|
+
6. **Accessibility** — contrast, keyboard, focus order, touch targets
|
|
65
|
+
|
|
66
|
+
Use the `/figma-to-code` command if you have Figma designs.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
### Plan Phase — how to structure tasks
|
|
71
|
+
|
|
72
|
+
Break into these phases:
|
|
73
|
+
|
|
74
|
+
#### Phase 1: Types & API Layer
|
|
75
|
+
| # | Task | Files |
|
|
76
|
+
|---|------|-------|
|
|
77
|
+
| 1 | Define TypeScript types/interfaces | `types/{feature}.ts` |
|
|
78
|
+
| 2 | Create API client functions | `lib/api/{feature}.ts` or server actions |
|
|
79
|
+
| 3 | Create data hooks (if client-side) | `hooks/use-{feature}.ts` |
|
|
80
|
+
|
|
81
|
+
#### Phase 2: Components
|
|
82
|
+
| # | Task | Files |
|
|
83
|
+
|---|------|-------|
|
|
84
|
+
| 4 | Create base UI components | `components/{feature}/{Component}.tsx` |
|
|
85
|
+
| 5 | Create composite components | `components/{feature}/{CompositeComponent}.tsx` |
|
|
86
|
+
| 6 | Add loading/error/empty states | Update components from tasks 4-5 |
|
|
87
|
+
|
|
88
|
+
#### Phase 3: Pages & Routes
|
|
89
|
+
| # | Task | Files |
|
|
90
|
+
|---|------|-------|
|
|
91
|
+
| 7 | Create page component | `app/{route}/page.tsx` |
|
|
92
|
+
| 8 | Create layout (if needed) | `app/{route}/layout.tsx` |
|
|
93
|
+
| 9 | Add server actions (if needed) | `app/{route}/actions.ts` |
|
|
94
|
+
| 10 | Wire up navigation | Update nav/sidebar components |
|
|
95
|
+
|
|
96
|
+
#### Phase 4: Tests
|
|
97
|
+
| # | Task | Files |
|
|
98
|
+
|---|------|-------|
|
|
99
|
+
| 11 | Component unit tests | `__tests__/{Component}.test.tsx` |
|
|
100
|
+
| 12 | Hook tests | `__tests__/use-{feature}.test.ts` |
|
|
101
|
+
| 13 | E2E tests (if critical path) | `e2e/{feature}.spec.ts` |
|
|
102
|
+
|
|
103
|
+
**Parallel groups:**
|
|
104
|
+
- Tasks 1-3 can run in parallel (types, API, hooks are independent)
|
|
105
|
+
- Tasks 4-5 can run in parallel (base and composite components are separate files)
|
|
106
|
+
- Tasks 11-13 can run in parallel (tests are independent)
|
|
107
|
+
|
|
108
|
+
**Sequential:**
|
|
109
|
+
- Task 5 may need 4 (composite uses base components)
|
|
110
|
+
- Task 6 needs 4-5 (states go into existing components)
|
|
111
|
+
- Task 7 needs 4-6 (page composes components)
|
|
112
|
+
- Task 9 needs 2 (server actions may wrap API calls)
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Quality Gates — Frontend Specific
|
|
117
|
+
|
|
118
|
+
### Gate 1: Spec Review (Frontend)
|
|
119
|
+
|
|
120
|
+
Everything from the generic Gate 1, plus:
|
|
121
|
+
|
|
122
|
+
**UI Changes:**
|
|
123
|
+
- [ ] All affected screens listed
|
|
124
|
+
- [ ] All states defined (loading, empty, error, success)
|
|
125
|
+
- [ ] Mobile vs desktop differences called out
|
|
126
|
+
- [ ] User flows are step-by-step (not vague)
|
|
127
|
+
- [ ] Design doc created (`design-doc.md`)
|
|
128
|
+
|
|
129
|
+
**API Dependencies:**
|
|
130
|
+
- [ ] All needed endpoints listed
|
|
131
|
+
- [ ] New vs existing endpoints clearly marked
|
|
132
|
+
- [ ] Response shapes documented
|
|
133
|
+
- [ ] If new endpoints needed: is backend spec written?
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
### Gate 2: Plan Review (Frontend)
|
|
138
|
+
|
|
139
|
+
Everything from the generic Gate 2, plus:
|
|
140
|
+
|
|
141
|
+
**App Router (FRONTEND.md):**
|
|
142
|
+
- [ ] Pages use App Router conventions (`page.tsx`, `layout.tsx`, `loading.tsx`)
|
|
143
|
+
- [ ] Server components vs client components clearly decided
|
|
144
|
+
- [ ] Server actions used for mutations (not API routes where possible)
|
|
145
|
+
- [ ] Data fetching strategy decided (server component fetch, SWR, React Query, etc.)
|
|
146
|
+
|
|
147
|
+
**Component Design:**
|
|
148
|
+
- [ ] Reusable components identified and planned
|
|
149
|
+
- [ ] Component props are typed with TypeScript interfaces
|
|
150
|
+
- [ ] States handled: default, loading, error, empty, disabled
|
|
151
|
+
- [ ] Accessibility considered (keyboard, screen reader, focus)
|
|
152
|
+
|
|
153
|
+
**File Structure:**
|
|
154
|
+
- [ ] Types in `types/` directory
|
|
155
|
+
- [ ] API functions in `lib/api/` or server actions in route dirs
|
|
156
|
+
- [ ] Components in `components/{feature}/`
|
|
157
|
+
- [ ] Pages in `app/{route}/`
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
### Gate 3: Implementation Review (Frontend)
|
|
162
|
+
|
|
163
|
+
Everything from the generic Gate 3, plus:
|
|
164
|
+
|
|
165
|
+
**TypeScript (FRONTEND.md):**
|
|
166
|
+
- [ ] No `any` types — use proper interfaces
|
|
167
|
+
- [ ] No `as` type assertions unless truly needed
|
|
168
|
+
- [ ] Props interfaces defined and exported
|
|
169
|
+
- [ ] API responses properly typed
|
|
170
|
+
|
|
171
|
+
**React Patterns:**
|
|
172
|
+
- [ ] No unnecessary `useEffect` — prefer server components or derived state
|
|
173
|
+
- [ ] No prop drilling — use composition or context
|
|
174
|
+
- [ ] Keys on list items are stable (not array index)
|
|
175
|
+
- [ ] Event handlers don't create new functions on every render (when it matters for perf)
|
|
176
|
+
|
|
177
|
+
**API Integration (FRONTEND.md):**
|
|
178
|
+
- [ ] snake_case → camelCase conversion at API boundary
|
|
179
|
+
- [ ] camelCase → snake_case conversion for requests
|
|
180
|
+
- [ ] Error states handled (not just happy path)
|
|
181
|
+
- [ ] Loading states shown during async operations
|
|
182
|
+
|
|
183
|
+
**Accessibility:**
|
|
184
|
+
- [ ] Semantic HTML elements (not `div` for everything)
|
|
185
|
+
- [ ] ARIA labels on interactive elements without visible text
|
|
186
|
+
- [ ] Focus management for modals/dialogs
|
|
187
|
+
- [ ] Color is not the only way to show state
|
|
188
|
+
|
|
189
|
+
**Build:**
|
|
190
|
+
- [ ] `npm run build` passes (no TypeScript errors)
|
|
191
|
+
- [ ] No console warnings in dev mode
|
|
192
|
+
- [ ] No unused imports
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
### Gate 4: Final Review (Frontend)
|
|
197
|
+
|
|
198
|
+
Everything from the generic Gate 4, plus:
|
|
199
|
+
|
|
200
|
+
- [ ] `npm run build` passes with zero errors
|
|
201
|
+
- [ ] `npm run lint` passes
|
|
202
|
+
- [ ] `npm run test` passes
|
|
203
|
+
- [ ] No `any` types in changed files
|
|
204
|
+
- [ ] All pages work at mobile (375px), tablet (768px), desktop (1440px)
|
|
205
|
+
- [ ] Lighthouse accessibility score >= 90
|
|
206
|
+
- [ ] No layout shift on page load (CLS)
|
|
207
|
+
- [ ] Images use `next/image` with proper sizing
|
|
208
|
+
- [ ] No hardcoded colors — use design tokens or Tailwind classes
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Quick Reference
|
|
213
|
+
|
|
214
|
+
| What | Where | Notes |
|
|
215
|
+
|------|-------|-------|
|
|
216
|
+
| Pages | `app/{route}/page.tsx` | Server components by default |
|
|
217
|
+
| Layouts | `app/{route}/layout.tsx` | Shared UI between routes |
|
|
218
|
+
| Components | `components/{feature}/` | One component per file |
|
|
219
|
+
| Types | `types/{feature}.ts` | Shared TypeScript interfaces |
|
|
220
|
+
| API client | `lib/api/{feature}.ts` | Fetch wrappers, case conversion |
|
|
221
|
+
| Server actions | `app/{route}/actions.ts` | Mutations, form handling |
|
|
222
|
+
| Hooks | `hooks/use-{feature}.ts` | Client-side data/state |
|
|
223
|
+
| Tests | `__tests__/` or colocated | Vitest + Testing Library |
|
|
224
|
+
| E2E tests | `e2e/` | Playwright |
|
|
225
|
+
|
|
226
|
+
## Related Skills & Commands
|
|
227
|
+
|
|
228
|
+
- `/spartan:next-app` — scaffold a new Next.js app
|
|
229
|
+
- `/spartan:next-feature` — scaffold a feature in existing app
|
|
230
|
+
- `/spartan:fe-review` — PR review with React/Next.js conventions
|
|
231
|
+
- `/spartan:figma-to-code` — convert Figma design to code
|
|
232
|
+
- `/spartan:e2e` — set up Playwright E2E testing
|
|
233
|
+
- `/ui-ux-pro-max` skill — design system intelligence
|