@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,207 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spartan:deploy
|
|
3
|
+
description: Deployment guide and checklist for Railway (primary), AWS, or GCP. Validates readiness, generates config, and walks through the deployment steps.
|
|
4
|
+
argument-hint: "[service name] [railway | aws | gcp]"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Deploy: {{ args[0] }}
|
|
8
|
+
Target: {{ args[1] | default: "railway" }}
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Pre-flight Checklist (run first, always)
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
# Tests must all pass
|
|
16
|
+
./gradlew test # Kotlin BE
|
|
17
|
+
npm test -- --run 2>/dev/null # Next.js FE (if applicable)
|
|
18
|
+
|
|
19
|
+
# Build must succeed
|
|
20
|
+
./gradlew build -x test # Kotlin
|
|
21
|
+
npm run build 2>/dev/null # Next.js
|
|
22
|
+
|
|
23
|
+
# No uncommitted changes
|
|
24
|
+
git status
|
|
25
|
+
git diff --stat
|
|
26
|
+
|
|
27
|
+
# Current branch
|
|
28
|
+
git branch --show-current
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**Blocker:** Any failing test or build error = do NOT deploy.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
{% if args[1] == "railway" or args[1] == nil %}
|
|
36
|
+
## Railway Deployment
|
|
37
|
+
|
|
38
|
+
### First-time setup (new service)
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
# Install Railway CLI if needed
|
|
42
|
+
npm install -g @railway/cli
|
|
43
|
+
|
|
44
|
+
# Login
|
|
45
|
+
railway login
|
|
46
|
+
|
|
47
|
+
# Link to project (if not already)
|
|
48
|
+
railway link
|
|
49
|
+
|
|
50
|
+
# Check current project
|
|
51
|
+
railway status
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Validate railway.toml
|
|
55
|
+
|
|
56
|
+
Ensure `railway.toml` exists at project root:
|
|
57
|
+
|
|
58
|
+
```toml
|
|
59
|
+
[build]
|
|
60
|
+
builder = "nixpacks"
|
|
61
|
+
|
|
62
|
+
[deploy]
|
|
63
|
+
# Kotlin/Micronaut:
|
|
64
|
+
startCommand = "java -jar build/libs/*-all.jar"
|
|
65
|
+
# OR: startCommand = "./gradlew bootRun"
|
|
66
|
+
|
|
67
|
+
# Next.js:
|
|
68
|
+
# startCommand = "npm start"
|
|
69
|
+
|
|
70
|
+
healthcheckPath = "/health" # Kotlin
|
|
71
|
+
# healthcheckPath = "/api/health" # Next.js custom
|
|
72
|
+
healthcheckTimeout = 60
|
|
73
|
+
restartPolicyType = "on-failure"
|
|
74
|
+
restartPolicyMaxRetries = 3
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Environment variables check
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# List current vars
|
|
81
|
+
railway variables
|
|
82
|
+
|
|
83
|
+
# Set missing vars (one by one)
|
|
84
|
+
railway variables set KEY=value
|
|
85
|
+
|
|
86
|
+
# Critical vars to verify for Kotlin BE:
|
|
87
|
+
# DATASOURCES_DEFAULT_URL
|
|
88
|
+
# DATASOURCES_DEFAULT_USERNAME
|
|
89
|
+
# DATASOURCES_DEFAULT_PASSWORD
|
|
90
|
+
# MICRONAUT_ENVIRONMENTS=prod
|
|
91
|
+
|
|
92
|
+
# Critical vars for Next.js:
|
|
93
|
+
# NEXT_PUBLIC_API_URL (pointing to BE service)
|
|
94
|
+
# Any auth secrets
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Deploy
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
# Deploy current branch
|
|
101
|
+
railway up
|
|
102
|
+
|
|
103
|
+
# Or deploy a specific service
|
|
104
|
+
railway up --service [service-name]
|
|
105
|
+
|
|
106
|
+
# Watch logs during deploy
|
|
107
|
+
railway logs --follow
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Post-deploy verification
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
# Check service is healthy
|
|
114
|
+
railway status
|
|
115
|
+
|
|
116
|
+
# Check health endpoint
|
|
117
|
+
curl https://[service-url]/health
|
|
118
|
+
|
|
119
|
+
# Check recent logs for errors
|
|
120
|
+
railway logs | tail -50
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Rollback if needed
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
# View deployment history in Railway dashboard
|
|
127
|
+
# Or redeploy previous commit:
|
|
128
|
+
git log --oneline -5
|
|
129
|
+
railway up --detach # after checking out previous commit
|
|
130
|
+
```
|
|
131
|
+
{% endif %}
|
|
132
|
+
|
|
133
|
+
{% if args[1] == "aws" %}
|
|
134
|
+
## AWS Deployment
|
|
135
|
+
|
|
136
|
+
### Service type check
|
|
137
|
+
|
|
138
|
+
Ask: What AWS service is this deploying to?
|
|
139
|
+
- **ECS (Fargate)** — containerized service
|
|
140
|
+
- **Lambda** — serverless function
|
|
141
|
+
- **Elastic Beanstalk** — managed app platform
|
|
142
|
+
- **S3 + CloudFront** — static Next.js export
|
|
143
|
+
|
|
144
|
+
### ECS Fargate (Kotlin BE)
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
# Build and push Docker image
|
|
148
|
+
aws ecr get-login-password --region ap-southeast-1 | \
|
|
149
|
+
docker login --username AWS --password-stdin [account].dkr.ecr.ap-southeast-1.amazonaws.com
|
|
150
|
+
|
|
151
|
+
docker build -t [service-name] .
|
|
152
|
+
docker tag [service-name]:latest [account].dkr.ecr.ap-southeast-1.amazonaws.com/[service-name]:latest
|
|
153
|
+
docker push [account].dkr.ecr.ap-southeast-1.amazonaws.com/[service-name]:latest
|
|
154
|
+
|
|
155
|
+
# Update ECS service
|
|
156
|
+
aws ecs update-service \
|
|
157
|
+
--cluster [cluster-name] \
|
|
158
|
+
--service [service-name] \
|
|
159
|
+
--force-new-deployment
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Post-deploy
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
# Watch deployment status
|
|
166
|
+
aws ecs describe-services \
|
|
167
|
+
--cluster [cluster-name] \
|
|
168
|
+
--services [service-name] \
|
|
169
|
+
--query 'services[0].deployments'
|
|
170
|
+
|
|
171
|
+
# Check task health
|
|
172
|
+
aws ecs list-tasks --cluster [cluster-name] --service-name [service-name]
|
|
173
|
+
```
|
|
174
|
+
{% endif %}
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Common Issues & Fixes
|
|
179
|
+
|
|
180
|
+
| Issue | Fix |
|
|
181
|
+
|---|---|
|
|
182
|
+
| Health check failing | Check `/health` returns 200, increase `healthcheckTimeout` |
|
|
183
|
+
| Out of memory | Increase Railway service RAM, or tune JVM: `-Xmx512m` |
|
|
184
|
+
| DB connection failed | Verify `DATABASE_URL` env var, check Railway DB is in same project |
|
|
185
|
+
| Build timeout | Gradle daemon issue — add `org.gradle.daemon=false` to `gradle.properties` |
|
|
186
|
+
| CORS errors | Check `ALLOWED_ORIGINS` env var includes FE URL |
|
|
187
|
+
| Cold start too slow | For Railway: disable `sleep` on free tier, or upgrade plan |
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## Deployment Summary
|
|
192
|
+
|
|
193
|
+
After successful deploy, output:
|
|
194
|
+
|
|
195
|
+
```markdown
|
|
196
|
+
## Deploy Summary: [service] → [target]
|
|
197
|
+
|
|
198
|
+
- URL: [service URL]
|
|
199
|
+
- Git commit: [hash]
|
|
200
|
+
- Deploy time: [timestamp]
|
|
201
|
+
- Health: ✅ / ❌
|
|
202
|
+
|
|
203
|
+
## Smoke Tests Run
|
|
204
|
+
- [ ] Health endpoint: [result]
|
|
205
|
+
- [ ] Key user-facing endpoint: [result]
|
|
206
|
+
- [ ] Logs clean (no errors): [result]
|
|
207
|
+
```
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spartan:e2e
|
|
3
|
+
description: Set up Playwright end-to-end testing for a Next.js app. Scaffold config, page objects, and critical path tests. Use when the app has enough features to warrant E2E coverage.
|
|
4
|
+
argument-hint: "[optional: feature or critical path to test first]"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# E2E Testing Setup: {{ args[0] | default: "full setup" }}
|
|
8
|
+
|
|
9
|
+
You are setting up **Playwright** for end-to-end testing in a Next.js project.
|
|
10
|
+
E2E tests complement unit tests (Vitest) — they test real user flows across the full stack.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Step 1: Install Playwright
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install -D @playwright/test
|
|
18
|
+
npx playwright install chromium # Only chromium for speed; add more later if needed
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Step 2: Configure
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
// playwright.config.ts
|
|
27
|
+
import { defineConfig, devices } from '@playwright/test'
|
|
28
|
+
|
|
29
|
+
export default defineConfig({
|
|
30
|
+
testDir: './e2e',
|
|
31
|
+
fullyParallel: true,
|
|
32
|
+
forbidOnly: !!process.env.CI,
|
|
33
|
+
retries: process.env.CI ? 2 : 0,
|
|
34
|
+
workers: process.env.CI ? 1 : undefined,
|
|
35
|
+
reporter: process.env.CI ? 'github' : 'html',
|
|
36
|
+
|
|
37
|
+
use: {
|
|
38
|
+
baseURL: process.env.E2E_BASE_URL ?? 'http://localhost:3000',
|
|
39
|
+
trace: 'on-first-retry',
|
|
40
|
+
screenshot: 'only-on-failure',
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
projects: [
|
|
44
|
+
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
|
|
45
|
+
// Add when ready:
|
|
46
|
+
// { name: 'mobile', use: { ...devices['iPhone 14'] } },
|
|
47
|
+
],
|
|
48
|
+
|
|
49
|
+
// Start Next.js dev server for local runs
|
|
50
|
+
webServer: {
|
|
51
|
+
command: 'npm run dev',
|
|
52
|
+
url: 'http://localhost:3000',
|
|
53
|
+
reuseExistingServer: !process.env.CI,
|
|
54
|
+
timeout: 30_000,
|
|
55
|
+
},
|
|
56
|
+
})
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Step 3: Directory Structure
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
e2e/
|
|
65
|
+
├── fixtures/ ← Shared test fixtures and setup
|
|
66
|
+
│ ├── base.fixture.ts ← Extended test with common helpers
|
|
67
|
+
│ └── test-data.ts ← Test data factories
|
|
68
|
+
├── pages/ ← Page Object Models
|
|
69
|
+
│ ├── BasePage.ts
|
|
70
|
+
│ └── [Feature]Page.ts
|
|
71
|
+
├── [feature].spec.ts ← Test files
|
|
72
|
+
└── global-setup.ts ← One-time setup (auth, seed data)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Step 4: Base Page Object
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
// e2e/pages/BasePage.ts
|
|
81
|
+
import { type Page, type Locator, expect } from '@playwright/test'
|
|
82
|
+
|
|
83
|
+
export abstract class BasePage {
|
|
84
|
+
constructor(protected readonly page: Page) {}
|
|
85
|
+
|
|
86
|
+
// Common helpers
|
|
87
|
+
async waitForPageReady() {
|
|
88
|
+
await this.page.waitForLoadState('networkidle')
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async expectToastMessage(text: string) {
|
|
92
|
+
await expect(this.page.getByRole('alert')).toContainText(text)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async expectUrl(pattern: string | RegExp) {
|
|
96
|
+
await expect(this.page).toHaveURL(pattern)
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
// e2e/pages/HomePage.ts — example
|
|
103
|
+
import { type Page, type Locator, expect } from '@playwright/test'
|
|
104
|
+
import { BasePage } from './BasePage'
|
|
105
|
+
|
|
106
|
+
export class HomePage extends BasePage {
|
|
107
|
+
readonly heading: Locator
|
|
108
|
+
readonly ctaButton: Locator
|
|
109
|
+
|
|
110
|
+
constructor(page: Page) {
|
|
111
|
+
super(page)
|
|
112
|
+
this.heading = page.getByRole('heading', { level: 1 })
|
|
113
|
+
this.ctaButton = page.getByRole('link', { name: /get started/i })
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async goto() {
|
|
117
|
+
await this.page.goto('/')
|
|
118
|
+
await this.waitForPageReady()
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async clickCta() {
|
|
122
|
+
await this.ctaButton.click()
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## Step 5: Test Fixture
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
// e2e/fixtures/base.fixture.ts
|
|
133
|
+
import { test as base } from '@playwright/test'
|
|
134
|
+
import { HomePage } from '../pages/HomePage'
|
|
135
|
+
|
|
136
|
+
type Fixtures = {
|
|
137
|
+
homePage: HomePage
|
|
138
|
+
// Add more page objects as features grow
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export const test = base.extend<Fixtures>({
|
|
142
|
+
homePage: async ({ page }, use) => {
|
|
143
|
+
const homePage = new HomePage(page)
|
|
144
|
+
await use(homePage)
|
|
145
|
+
},
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
export { expect } from '@playwright/test'
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Step 6: First E2E Test
|
|
154
|
+
|
|
155
|
+
{% if args[0] and args[0] != "full setup" %}
|
|
156
|
+
Write tests for: **{{ args[0] }}**
|
|
157
|
+
{% else %}
|
|
158
|
+
Write a smoke test for the critical happy path:
|
|
159
|
+
{% endif %}
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
// e2e/smoke.spec.ts
|
|
163
|
+
import { test, expect } from './fixtures/base.fixture'
|
|
164
|
+
|
|
165
|
+
test.describe('Smoke Tests', () => {
|
|
166
|
+
test('home page loads and renders correctly', async ({ homePage }) => {
|
|
167
|
+
await homePage.goto()
|
|
168
|
+
await expect(homePage.heading).toBeVisible()
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
test('health endpoint returns ok', async ({ request }) => {
|
|
172
|
+
const response = await request.get('/api/health')
|
|
173
|
+
expect(response.ok()).toBeTruthy()
|
|
174
|
+
const body = await response.json()
|
|
175
|
+
expect(body.status).toBe('ok')
|
|
176
|
+
})
|
|
177
|
+
})
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## Step 7: Package.json Scripts
|
|
183
|
+
|
|
184
|
+
```json
|
|
185
|
+
{
|
|
186
|
+
"scripts": {
|
|
187
|
+
"test:e2e": "playwright test",
|
|
188
|
+
"test:e2e:ui": "playwright test --ui",
|
|
189
|
+
"test:e2e:headed": "playwright test --headed",
|
|
190
|
+
"test:e2e:report": "playwright show-report"
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Step 8: CI Integration
|
|
198
|
+
|
|
199
|
+
Add to `.github/workflows/ci.yml`:
|
|
200
|
+
|
|
201
|
+
```yaml
|
|
202
|
+
e2e:
|
|
203
|
+
runs-on: ubuntu-latest
|
|
204
|
+
needs: test # Run after unit tests pass
|
|
205
|
+
steps:
|
|
206
|
+
- uses: actions/checkout@v4
|
|
207
|
+
- uses: actions/setup-node@v4
|
|
208
|
+
with:
|
|
209
|
+
node-version: '20'
|
|
210
|
+
cache: 'npm'
|
|
211
|
+
- run: npm ci
|
|
212
|
+
- run: npx playwright install chromium --with-deps
|
|
213
|
+
- run: npm run test:e2e
|
|
214
|
+
env:
|
|
215
|
+
CI: true
|
|
216
|
+
- uses: actions/upload-artifact@v4
|
|
217
|
+
if: failure()
|
|
218
|
+
with:
|
|
219
|
+
name: playwright-report
|
|
220
|
+
path: playwright-report/
|
|
221
|
+
retention-days: 7
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## Step 9: .gitignore additions
|
|
227
|
+
|
|
228
|
+
```
|
|
229
|
+
# Playwright
|
|
230
|
+
/test-results/
|
|
231
|
+
/playwright-report/
|
|
232
|
+
/blob-report/
|
|
233
|
+
/playwright/.cache/
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Step 10: Verify
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
# Run E2E tests
|
|
242
|
+
npm run test:e2e
|
|
243
|
+
|
|
244
|
+
# Debug with UI mode
|
|
245
|
+
npm run test:e2e:ui
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
After setup, say:
|
|
249
|
+
"✅ Playwright E2E configured. Smoke test passing.
|
|
250
|
+
Use Page Object pattern in `e2e/pages/` for each new feature.
|
|
251
|
+
Run `npm run test:e2e:ui` for interactive debugging."
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## E2E Test Writing Conventions
|
|
256
|
+
|
|
257
|
+
When writing new E2E tests, follow these rules:
|
|
258
|
+
|
|
259
|
+
1. **Use Page Objects** — never raw selectors in test files
|
|
260
|
+
2. **Prefer accessible locators**: `getByRole`, `getByLabel`, `getByText` over CSS selectors
|
|
261
|
+
3. **One assertion per test** (prefer) or closely related assertions
|
|
262
|
+
4. **Test user flows**, not implementation — "user can complete checkout" not "checkout button has class X"
|
|
263
|
+
5. **Isolate test data** — each test creates its own data, never depends on other tests
|
|
264
|
+
6. **Name tests as user stories**: `test('user can add item to cart and checkout')`
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spartan:env-setup
|
|
3
|
+
description: Set up and audit environment variables for a service across local, Railway, and AWS environments. Generates .env.example, validates required vars, and flags missing ones.
|
|
4
|
+
argument-hint: "[service name] [local | railway | aws | audit]"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Environment Setup: {{ args[0] }}
|
|
8
|
+
Mode: {{ args[1] | default: "audit" }}
|
|
9
|
+
|
|
10
|
+
Environment variables are the #1 cause of "works locally but breaks in prod."
|
|
11
|
+
This command audits, generates, and validates env vars across environments.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Step 1: Discover required variables
|
|
16
|
+
|
|
17
|
+
Scan the codebase to find all env var references:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# Kotlin Micronaut — application.yml and @Property annotations
|
|
21
|
+
grep -r "\${" src/main/resources/ --include="*.yml" | grep -v "^Binary"
|
|
22
|
+
grep -r "@Property\|@ConfigurationProperties\|Environment\|System.getenv" \
|
|
23
|
+
src/main/kotlin/ --include="*.kt" | grep -v "test\|Test"
|
|
24
|
+
|
|
25
|
+
# Next.js — process.env references
|
|
26
|
+
grep -r "process\.env\." --include="*.ts" --include="*.tsx" src/ app/ lib/ 2>/dev/null | \
|
|
27
|
+
grep -v "test\|spec\|node_modules"
|
|
28
|
+
|
|
29
|
+
# Docker Compose
|
|
30
|
+
cat docker-compose.yml 2>/dev/null | grep "environment\|env_file" -A5
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Step 2: Generate .env.example
|
|
36
|
+
|
|
37
|
+
Based on findings, create/update `.env.example` (safe to commit — no real values):
|
|
38
|
+
|
|
39
|
+
### Kotlin Micronaut template:
|
|
40
|
+
```bash
|
|
41
|
+
# .env.example for [service-name]
|
|
42
|
+
# Copy to .env.local and fill in values
|
|
43
|
+
|
|
44
|
+
# === Database ===
|
|
45
|
+
DATASOURCES_DEFAULT_URL=jdbc:postgresql://localhost:5432/[dbname]
|
|
46
|
+
DATASOURCES_DEFAULT_USERNAME=postgres
|
|
47
|
+
DATASOURCES_DEFAULT_PASSWORD=changeme
|
|
48
|
+
|
|
49
|
+
# === Application ===
|
|
50
|
+
MICRONAUT_ENVIRONMENTS=local
|
|
51
|
+
MICRONAUT_SERVER_PORT=8080
|
|
52
|
+
|
|
53
|
+
# === External Services ===
|
|
54
|
+
# [SERVICE]_API_KEY=your-key-here
|
|
55
|
+
# [SERVICE]_BASE_URL=https://api.example.com
|
|
56
|
+
|
|
57
|
+
# === Auth (if applicable) ===
|
|
58
|
+
# JWT_SECRET=generate-with: openssl rand -base64 32
|
|
59
|
+
# JWT_EXPIRY_MS=86400000
|
|
60
|
+
|
|
61
|
+
# === Observability ===
|
|
62
|
+
# SENTRY_DSN=
|
|
63
|
+
# DATADOG_API_KEY=
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Next.js template:
|
|
67
|
+
```bash
|
|
68
|
+
# .env.example for [fe-service]
|
|
69
|
+
|
|
70
|
+
# === API Connection ===
|
|
71
|
+
NEXT_PUBLIC_API_URL=http://localhost:8080
|
|
72
|
+
|
|
73
|
+
# === Auth ===
|
|
74
|
+
# NEXTAUTH_URL=http://localhost:3000
|
|
75
|
+
# NEXTAUTH_SECRET=generate-with: openssl rand -base64 32
|
|
76
|
+
|
|
77
|
+
# === External Services ===
|
|
78
|
+
# NEXT_PUBLIC_ANALYTICS_ID=
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Step 3: Audit current environments
|
|
84
|
+
|
|
85
|
+
### Local
|
|
86
|
+
```bash
|
|
87
|
+
# Check .env.local exists and has all required vars
|
|
88
|
+
cat .env.local 2>/dev/null || echo "⚠️ .env.local missing"
|
|
89
|
+
|
|
90
|
+
# Find vars in .env.example but missing from .env.local
|
|
91
|
+
comm -23 <(grep "^[A-Z]" .env.example | cut -d= -f1 | sort) \
|
|
92
|
+
<(grep "^[A-Z]" .env.local 2>/dev/null | cut -d= -f1 | sort)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Railway
|
|
96
|
+
```bash
|
|
97
|
+
railway variables 2>/dev/null || echo "Not linked to Railway project"
|
|
98
|
+
|
|
99
|
+
# Check for missing vars (compare with .env.example)
|
|
100
|
+
railway variables --json 2>/dev/null | \
|
|
101
|
+
python3 -c "import json,sys; vars=json.load(sys.stdin); [print(k) for k in vars]"
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### AWS (if applicable)
|
|
105
|
+
```bash
|
|
106
|
+
# List SSM Parameter Store entries for this service
|
|
107
|
+
aws ssm get-parameters-by-path \
|
|
108
|
+
--path "/spartan/[service-name]/" \
|
|
109
|
+
--query "Parameters[*].Name"
|
|
110
|
+
|
|
111
|
+
# Or check Secrets Manager
|
|
112
|
+
aws secretsmanager list-secrets \
|
|
113
|
+
--query "SecretList[?contains(Name, '[service-name]')].Name"
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Step 4: Output audit report
|
|
119
|
+
|
|
120
|
+
```markdown
|
|
121
|
+
## Env Audit: [service-name]
|
|
122
|
+
|
|
123
|
+
### Variables found in code: [N]
|
|
124
|
+
|
|
125
|
+
### Status by environment:
|
|
126
|
+
|
|
127
|
+
| Variable | Local | Railway | AWS | Notes |
|
|
128
|
+
|---|---|---|---|---|
|
|
129
|
+
| DATASOURCES_DEFAULT_URL | ✅ | ✅ | ✅ | |
|
|
130
|
+
| JWT_SECRET | ✅ | ✅ | ❌ | Missing in AWS |
|
|
131
|
+
| SENTRY_DSN | ❌ | ✅ | ✅ | Missing locally (ok) |
|
|
132
|
+
|
|
133
|
+
### Issues Found:
|
|
134
|
+
- [MISSING_VAR]: Required in prod but not set in Railway
|
|
135
|
+
- [SECRET_IN_CODE]: Found hardcoded value in [file:line] — move to env var
|
|
136
|
+
|
|
137
|
+
### All clear:
|
|
138
|
+
- .env.example is up to date
|
|
139
|
+
- No secrets committed to git
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## Step 5: Security check
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
# Check nothing sensitive was committed
|
|
148
|
+
git log --all --full-history -- "*.env" "**/.env" "**/.env.local"
|
|
149
|
+
git grep -I "password\|secret\|api_key\|apikey\|token" -- '*.yml' '*.yaml' '*.properties' | \
|
|
150
|
+
grep -v "placeholder\|example\|changeme\|your-"
|
|
151
|
+
|
|
152
|
+
# Verify .gitignore covers env files
|
|
153
|
+
grep "\.env" .gitignore || echo "⚠️ .env files not in .gitignore!"
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
If any secrets found in git history:
|
|
157
|
+
```bash
|
|
158
|
+
# Remove from history (nuclear option — coordinate with team first)
|
|
159
|
+
git filter-branch --force --index-filter \
|
|
160
|
+
'git rm --cached --ignore-unmatch .env.local' HEAD
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
After audit, summarize what's missing and offer to set the Railway vars interactively:
|
|
166
|
+
"Found [N] missing variables. Want me to help set them in Railway now? I'll ask for each value one at a time."
|