@zigrivers/scaffold 3.5.3 → 3.7.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/README.md +150 -8
- package/content/knowledge/backend/backend-api-design.md +103 -0
- package/content/knowledge/backend/backend-architecture.md +100 -0
- package/content/knowledge/backend/backend-async-patterns.md +101 -0
- package/content/knowledge/backend/backend-auth-patterns.md +100 -0
- package/content/knowledge/backend/backend-conventions.md +105 -0
- package/content/knowledge/backend/backend-data-modeling.md +102 -0
- package/content/knowledge/backend/backend-deployment.md +100 -0
- package/content/knowledge/backend/backend-dev-environment.md +102 -0
- package/content/knowledge/backend/backend-observability.md +102 -0
- package/content/knowledge/backend/backend-project-structure.md +100 -0
- package/content/knowledge/backend/backend-requirements.md +103 -0
- package/content/knowledge/backend/backend-security.md +104 -0
- package/content/knowledge/backend/backend-testing.md +101 -0
- package/content/knowledge/backend/backend-worker-patterns.md +100 -0
- package/content/knowledge/cli/cli-architecture.md +101 -0
- package/content/knowledge/cli/cli-conventions.md +117 -0
- package/content/knowledge/cli/cli-dev-environment.md +121 -0
- package/content/knowledge/cli/cli-distribution-patterns.md +106 -0
- package/content/knowledge/cli/cli-interactivity-patterns.md +116 -0
- package/content/knowledge/cli/cli-output-patterns.md +107 -0
- package/content/knowledge/cli/cli-project-structure.md +124 -0
- package/content/knowledge/cli/cli-requirements.md +101 -0
- package/content/knowledge/cli/cli-shell-integration.md +130 -0
- package/content/knowledge/cli/cli-testing.md +134 -0
- package/content/knowledge/web-app/web-app-api-patterns.md +224 -0
- package/content/knowledge/web-app/web-app-architecture.md +116 -0
- package/content/knowledge/web-app/web-app-auth-patterns.md +256 -0
- package/content/knowledge/web-app/web-app-conventions.md +121 -0
- package/content/knowledge/web-app/web-app-data-patterns.md +218 -0
- package/content/knowledge/web-app/web-app-deployment-workflow.md +143 -0
- package/content/knowledge/web-app/web-app-deployment.md +134 -0
- package/content/knowledge/web-app/web-app-design-system.md +158 -0
- package/content/knowledge/web-app/web-app-dev-environment.md +173 -0
- package/content/knowledge/web-app/web-app-observability.md +221 -0
- package/content/knowledge/web-app/web-app-project-structure.md +160 -0
- package/content/knowledge/web-app/web-app-rendering-strategies.md +133 -0
- package/content/knowledge/web-app/web-app-requirements.md +112 -0
- package/content/knowledge/web-app/web-app-security.md +193 -0
- package/content/knowledge/web-app/web-app-session-patterns.md +214 -0
- package/content/knowledge/web-app/web-app-testing.md +249 -0
- package/content/knowledge/web-app/web-app-ux-patterns.md +162 -0
- package/content/methodology/backend-overlay.yml +73 -0
- package/content/methodology/cli-overlay.yml +69 -0
- package/content/methodology/web-app-overlay.yml +79 -0
- package/dist/cli/commands/init.d.ts +26 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +354 -7
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/init.test.js +136 -0
- package/dist/cli/commands/init.test.js.map +1 -1
- package/dist/config/schema.d.ts +800 -32
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +48 -5
- package/dist/config/schema.js.map +1 -1
- package/dist/config/schema.test.js +156 -1
- package/dist/config/schema.test.js.map +1 -1
- package/dist/core/assembly/overlay-loader.d.ts.map +1 -1
- package/dist/core/assembly/overlay-loader.js +2 -1
- package/dist/core/assembly/overlay-loader.js.map +1 -1
- package/dist/core/assembly/overlay-loader.test.js +34 -0
- package/dist/core/assembly/overlay-loader.test.js.map +1 -1
- package/dist/e2e/game-pipeline.test.js +1 -0
- package/dist/e2e/game-pipeline.test.js.map +1 -1
- package/dist/e2e/project-type-overlays.test.d.ts +15 -0
- package/dist/e2e/project-type-overlays.test.d.ts.map +1 -0
- package/dist/e2e/project-type-overlays.test.js +534 -0
- package/dist/e2e/project-type-overlays.test.js.map +1 -0
- package/dist/types/config.d.ts +13 -2
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/index.d.ts +0 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +0 -1
- package/dist/types/index.js.map +1 -1
- package/dist/wizard/questions.d.ts +30 -1
- package/dist/wizard/questions.d.ts.map +1 -1
- package/dist/wizard/questions.js +181 -36
- package/dist/wizard/questions.js.map +1 -1
- package/dist/wizard/questions.test.js +334 -4
- package/dist/wizard/questions.test.js.map +1 -1
- package/dist/wizard/wizard.d.ts +26 -0
- package/dist/wizard/wizard.d.ts.map +1 -1
- package/dist/wizard/wizard.js +31 -2
- package/dist/wizard/wizard.js.map +1 -1
- package/package.json +1 -1
- package/dist/types/wizard.d.ts +0 -14
- package/dist/types/wizard.d.ts.map +0 -1
- package/dist/types/wizard.js +0 -2
- package/dist/types/wizard.js.map +0 -1
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: web-app-deployment-workflow
|
|
3
|
+
description: Preview deploys per PR, staging environments, deployment branches, CI/CD pipeline stages, rollback strategies, and canary deployments
|
|
4
|
+
topics: [web-app, deployment, ci-cd, staging, preview, rollback, canary]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
A mature deployment workflow transforms deployment from a risky, manual event into a routine, automated step. The goal is to make every merge to main automatically and safely deliverable to production, with fast rollback when something goes wrong. The cost of building this infrastructure up front is trivially small compared to the cost of a major incident caused by a manual deploy process.
|
|
8
|
+
|
|
9
|
+
## Summary
|
|
10
|
+
|
|
11
|
+
A mature deployment workflow makes every merge to main automatically deliverable with fast rollback. Every PR gets a preview deploy. CI/CD runs lint, typecheck, test, and build in fail-fast order. Test rollback procedures quarterly. For high-traffic apps, use canary deployments with explicit rollback criteria.
|
|
12
|
+
|
|
13
|
+
## Deep Guidance
|
|
14
|
+
|
|
15
|
+
### Preview Deploys Per PR
|
|
16
|
+
|
|
17
|
+
Every pull request should get its own preview deployment — a fully functional URL that reviewers and QA can use to verify behavior before merging. This is the single highest-ROI practice in modern web deployment:
|
|
18
|
+
|
|
19
|
+
- **Vercel, Netlify, Railway**: Automatically create preview deploys on PR open/push. Zero configuration for most frameworks.
|
|
20
|
+
- **Custom CI**: Build and deploy to a path-based preview URL (`preview/<pr-number>/`) or a subdomain. Tear down on PR close.
|
|
21
|
+
|
|
22
|
+
Preview deploys must use isolated environment variables (dev database, dev third-party API keys). Never point a preview deploy at a production database.
|
|
23
|
+
|
|
24
|
+
### Deployment Branches
|
|
25
|
+
|
|
26
|
+
Establish a clear branch-to-environment mapping and document it in the repo:
|
|
27
|
+
|
|
28
|
+
| Branch | Environment | Deploys |
|
|
29
|
+
|--------|-------------|---------|
|
|
30
|
+
| `main` | Production | Automatic on merge |
|
|
31
|
+
| `staging` | Staging | Automatic on merge |
|
|
32
|
+
| `feature/*`, `fix/*` | Preview | Automatic on PR push |
|
|
33
|
+
|
|
34
|
+
Avoid long-lived branches other than `main` and optionally `staging`. Feature branches merge to `main` via PR. `main` deploys to production. This is the simplest model that works.
|
|
35
|
+
|
|
36
|
+
If you have a separate `staging` branch: keep it in sync with `main` via regular merges. Staging branches that lag `main` by weeks create false confidence and painful integration surprises.
|
|
37
|
+
|
|
38
|
+
### CI/CD Pipeline Stages
|
|
39
|
+
|
|
40
|
+
Every push to a branch should run a pipeline in this order (fast-to-slow, fail-fast):
|
|
41
|
+
|
|
42
|
+
1. **Install dependencies** (cached; skip if lockfile unchanged)
|
|
43
|
+
2. **Lint** — ESLint, Prettier check (fail fast; ~30 seconds)
|
|
44
|
+
3. **Typecheck** — `tsc --noEmit` (fail fast; ~60 seconds)
|
|
45
|
+
4. **Unit tests** — Vitest/Jest with coverage threshold (1–3 minutes)
|
|
46
|
+
5. **Build** — Production build to verify no build errors (2–5 minutes)
|
|
47
|
+
6. **E2E tests** (optional, on main/staging only) — Playwright or Cypress against preview deploy (5–15 minutes)
|
|
48
|
+
7. **Deploy** — Only if all above pass
|
|
49
|
+
|
|
50
|
+
Do not run all tests on every PR if the test suite is slow. Use test impact analysis (run only tests related to changed files) or split E2E tests to a separate workflow that runs on merge to `main`.
|
|
51
|
+
|
|
52
|
+
### Rollback Strategies
|
|
53
|
+
|
|
54
|
+
Every deployment system must have a tested rollback procedure. "We can just revert the commit and redeploy" is not a rollback strategy — that takes 5+ minutes and requires a developer to execute it under pressure.
|
|
55
|
+
|
|
56
|
+
- **Vercel/Netlify**: One-click rollback to any previous deployment in the dashboard. Target: under 30 seconds to rollback.
|
|
57
|
+
- **Custom infrastructure**: Maintain the previous two deployment artifacts. Rollback = swap the active artifact. Use blue-green or immutable deployment patterns (see below).
|
|
58
|
+
- **Database migrations**: Rollback is the hard part. Write migrations that are forward-compatible (additive only). Keep destructive changes separate, deployed only after the new code is stable. Use a migration tool that tracks state (Prisma, Flyway, Liquibase).
|
|
59
|
+
|
|
60
|
+
Test the rollback procedure at least quarterly. A rollback you have never practiced will fail in an incident.
|
|
61
|
+
|
|
62
|
+
### Canary Deployments
|
|
63
|
+
|
|
64
|
+
For high-traffic production apps, deploy changes to a small percentage of traffic before full rollout:
|
|
65
|
+
|
|
66
|
+
- Route 5% of requests to the new version, 95% to the old
|
|
67
|
+
- Monitor error rates, latency, and business metrics for 15–30 minutes
|
|
68
|
+
- Gradually increase the percentage or roll back if metrics degrade
|
|
69
|
+
|
|
70
|
+
Canary deployments require infrastructure support: feature flag services (LaunchDarkly, Unleash), traffic splitting at the load balancer (AWS ALB weighted routing, Cloudflare Workers), or platform-level support (Vercel edge middleware). Do not implement canaries manually — use the platform's built-in mechanism.
|
|
71
|
+
|
|
72
|
+
### CI/CD Pipeline Template (GitHub Actions)
|
|
73
|
+
|
|
74
|
+
```yaml
|
|
75
|
+
# .github/workflows/ci.yml
|
|
76
|
+
name: CI
|
|
77
|
+
|
|
78
|
+
on:
|
|
79
|
+
push:
|
|
80
|
+
branches: [main, staging]
|
|
81
|
+
pull_request:
|
|
82
|
+
|
|
83
|
+
jobs:
|
|
84
|
+
quality:
|
|
85
|
+
runs-on: ubuntu-latest
|
|
86
|
+
steps:
|
|
87
|
+
- uses: actions/checkout@v4
|
|
88
|
+
- uses: actions/setup-node@v4
|
|
89
|
+
with:
|
|
90
|
+
node-version: 20
|
|
91
|
+
cache: npm
|
|
92
|
+
- run: npm ci
|
|
93
|
+
- run: npm run lint
|
|
94
|
+
- run: npm run typecheck
|
|
95
|
+
- run: npm run test -- --coverage
|
|
96
|
+
- run: npm run build
|
|
97
|
+
|
|
98
|
+
deploy-preview:
|
|
99
|
+
needs: quality
|
|
100
|
+
if: github.event_name == 'pull_request'
|
|
101
|
+
runs-on: ubuntu-latest
|
|
102
|
+
steps:
|
|
103
|
+
- uses: actions/checkout@v4
|
|
104
|
+
- uses: actions/setup-node@v4
|
|
105
|
+
with:
|
|
106
|
+
node-version: 20
|
|
107
|
+
cache: npm
|
|
108
|
+
- run: npm ci && npm run build
|
|
109
|
+
- name: Deploy preview
|
|
110
|
+
run: npx vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Deployment Environment Variables
|
|
114
|
+
|
|
115
|
+
Separate environment variables by tier and manage them securely:
|
|
116
|
+
|
|
117
|
+
- **Local**: `.env.local` (gitignored, developer-managed)
|
|
118
|
+
- **Preview**: Vercel/Netlify project environment variables, marked "Preview" tier; use dev API keys only
|
|
119
|
+
- **Staging**: Staging-specific secrets in GitHub Actions or your secrets manager
|
|
120
|
+
- **Production**: Production secrets never visible to developers; managed by infra/ops
|
|
121
|
+
|
|
122
|
+
Audit who has access to production secrets quarterly. Rotate API keys and tokens on team member offboarding without exception.
|
|
123
|
+
|
|
124
|
+
### Defining "Deployment Complete"
|
|
125
|
+
|
|
126
|
+
A deployment is not complete when the deploy command exits. It is complete when:
|
|
127
|
+
|
|
128
|
+
1. The new version is serving traffic (health check passes)
|
|
129
|
+
2. Error rate is not elevated above baseline
|
|
130
|
+
3. Response latency p95 is not elevated above baseline
|
|
131
|
+
4. At least one synthetic monitor has confirmed the critical user journey works
|
|
132
|
+
|
|
133
|
+
Automate this check in your deploy pipeline. Do not send "deploy succeeded" notifications until you have validated real traffic behavior.
|
|
134
|
+
|
|
135
|
+
### Zero-Downtime Deployments
|
|
136
|
+
|
|
137
|
+
For apps that cannot tolerate downtime:
|
|
138
|
+
|
|
139
|
+
- **Rolling deployments**: Bring up new instances, drain old instances. Requires stateless services (no in-memory session storage).
|
|
140
|
+
- **Blue-green deployments**: Run two identical environments (blue = current, green = new). Switch traffic at the load balancer level. Old environment stays up as instant rollback target.
|
|
141
|
+
- **Feature flags**: Deploy code to production without enabling it. Enable via flag without a deployment. Fastest and most controllable rollout mechanism.
|
|
142
|
+
|
|
143
|
+
For stateful workloads (databases, file storage): always plan the data migration before the code migration. Code deploys are reversible; bad data migrations often are not.
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: web-app-deployment
|
|
3
|
+
description: Static CDN hosting, serverless platforms, container deployments, edge runtimes, long-running servers, and blue-green deploy patterns for web apps
|
|
4
|
+
topics: [web-app, deployment, vercel, netlify, aws, docker, cloudflare, serverless, containers]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Deployment platform selection determines your app's operational cost, performance ceiling, and scaling characteristics. Each platform has a different cost model, latency profile, and runtime constraint. Choose based on your app's rendering strategy, traffic patterns, and team's operational expertise — not on what is fashionable.
|
|
8
|
+
|
|
9
|
+
## Summary
|
|
10
|
+
|
|
11
|
+
Web app deployment platforms range from static CDN hosting (cheapest, fastest TTFB) through serverless (pay-per-invocation, cold start concerns), containers (persistent connections, custom runtimes), edge functions (global low-latency transformations), to long-running servers (WebSockets, background jobs). Choose based on rendering strategy, traffic patterns, and operational expertise.
|
|
12
|
+
|
|
13
|
+
## Deep Guidance
|
|
14
|
+
|
|
15
|
+
### Static Hosting (CDN)
|
|
16
|
+
|
|
17
|
+
For SSG applications with no server-side rendering at request time:
|
|
18
|
+
|
|
19
|
+
- **Best platforms**: Cloudflare Pages, Netlify, Vercel (static tier), AWS S3 + CloudFront, GitHub Pages
|
|
20
|
+
- **Cost**: Near zero for low-to-medium traffic; CDN egress costs at very high traffic
|
|
21
|
+
- **Performance**: Best possible — globally distributed, no cold starts, ~50 ms TTFB from any major city
|
|
22
|
+
- **Limitations**: No request-time server logic, no secrets at request time, data freshness = deploy frequency
|
|
23
|
+
|
|
24
|
+
Configure aggressive caching headers. Static assets (hashed filenames) get `Cache-Control: immutable, max-age=31536000`. HTML pages get `Cache-Control: no-cache` (validated on every request, served from cache when fresh).
|
|
25
|
+
|
|
26
|
+
### Serverless (Vercel, Netlify, AWS Lambda)
|
|
27
|
+
|
|
28
|
+
For SSR apps or API routes that need server logic at request time without managing servers:
|
|
29
|
+
|
|
30
|
+
- **Best platforms**: Vercel (Next.js-native), Netlify Functions, AWS Lambda + API Gateway, Cloudflare Pages Functions
|
|
31
|
+
- **Cost model**: Pay per invocation and compute time. Typically very cheap at low traffic, can become expensive at sustained high traffic vs. a long-running server.
|
|
32
|
+
- **Cold starts**: The primary performance concern. Lambda cold starts: 100–500 ms (Node.js), 1–3 seconds (container-based). Vercel/Netlify Edge Functions: 0 ms (V8 isolates, not containers).
|
|
33
|
+
- **Limitations**: Execution time limits (Vercel: 10–300 seconds depending on plan; Lambda: 15 minutes max), no persistent memory between invocations, no long-lived connections
|
|
34
|
+
|
|
35
|
+
Minimize cold start impact: keep bundles small (Lambda-specific: prefer ESM + tree-shaking over CommonJS), use Provisioned Concurrency for latency-critical endpoints, or migrate latency-sensitive APIs to edge functions.
|
|
36
|
+
|
|
37
|
+
### Container (Docker, AWS ECS/Fargate, Google Cloud Run)
|
|
38
|
+
|
|
39
|
+
For apps that need more control than serverless, persistent connections, or custom runtime environments:
|
|
40
|
+
|
|
41
|
+
- **Best platforms**: AWS ECS/Fargate, Google Cloud Run, Azure Container Apps, Railway, Fly.io, self-managed Kubernetes
|
|
42
|
+
- **Cost model**: Per-container-hour (Fargate) or per-request with scale-to-zero (Cloud Run). More expensive than serverless at low traffic, cheaper at sustained high traffic.
|
|
43
|
+
- **Benefits over serverless**: No cold starts with min replicas > 0, persistent WebSocket connections, custom binaries/runtimes, larger memory limits
|
|
44
|
+
- **Operational overhead**: You manage container definitions, health checks, and scaling policies
|
|
45
|
+
|
|
46
|
+
Use multi-stage Docker builds to minimize image size. Target images under 200 MB:
|
|
47
|
+
|
|
48
|
+
```dockerfile
|
|
49
|
+
FROM node:20-alpine AS builder
|
|
50
|
+
WORKDIR /app
|
|
51
|
+
COPY package*.json ./
|
|
52
|
+
RUN npm ci
|
|
53
|
+
COPY . .
|
|
54
|
+
RUN npm run build
|
|
55
|
+
|
|
56
|
+
FROM node:20-alpine AS runner
|
|
57
|
+
WORKDIR /app
|
|
58
|
+
ENV NODE_ENV=production
|
|
59
|
+
COPY --from=builder /app/.next ./.next
|
|
60
|
+
COPY --from=builder /app/public ./public
|
|
61
|
+
COPY --from=builder /app/package.json ./
|
|
62
|
+
RUN npm ci --omit=dev
|
|
63
|
+
USER node
|
|
64
|
+
EXPOSE 3000
|
|
65
|
+
CMD ["npm", "start"]
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Edge (Cloudflare Workers, Vercel Edge Functions)
|
|
69
|
+
|
|
70
|
+
For global, low-latency request processing with simple logic:
|
|
71
|
+
|
|
72
|
+
- **Runtime**: V8 isolates (not Node.js). Fast startup (~0 ms), runs at 300+ edge locations globally, ~1–5 ms TTFB worldwide.
|
|
73
|
+
- **Use cases**: Auth token validation, A/B testing, geo-routing, request rewriting, rate limiting, personalized cache headers
|
|
74
|
+
- **Limitations**: No Node.js built-ins (`fs`, `crypto` partially available, `child_process` unavailable), no SQLite, execution time limits (50 ms CPU time on Cloudflare free tier), no persistent file system
|
|
75
|
+
- **Data access**: Use edge-native databases: Cloudflare D1 (SQLite), Cloudflare KV, Upstash Redis, PlanetScale edge
|
|
76
|
+
|
|
77
|
+
Never put complex business logic in edge functions. Their value is speed and global distribution for request/response transformations, not application logic.
|
|
78
|
+
|
|
79
|
+
### Long-Running Server (Express, Fastify, Node.js HTTP)
|
|
80
|
+
|
|
81
|
+
For apps that need WebSockets, background jobs, or full control over the request lifecycle:
|
|
82
|
+
|
|
83
|
+
- **Best platforms**: AWS EC2 + ALB, Fly.io, Railway, DigitalOcean Droplets, Hetzner (cost-efficient)
|
|
84
|
+
- **When to choose**: Real-time features (WebSockets, SSE), background workers, long-running database transactions, legacy apps that cannot be adapted to serverless constraints
|
|
85
|
+
|
|
86
|
+
### Blue-Green Deployments
|
|
87
|
+
|
|
88
|
+
Blue-green deployments eliminate downtime and reduce rollback time to seconds:
|
|
89
|
+
|
|
90
|
+
1. **Blue** = current production (100% of traffic)
|
|
91
|
+
2. **Green** = new version (deployed but receiving 0% of traffic)
|
|
92
|
+
3. Run smoke tests against the green environment
|
|
93
|
+
4. Switch the load balancer to route 100% of traffic to green
|
|
94
|
+
5. Monitor for 5–15 minutes
|
|
95
|
+
6. If healthy: decommission blue. If unhealthy: switch back to blue (rollback complete in < 30 seconds)
|
|
96
|
+
|
|
97
|
+
Requirements: stateless app servers (session data in Redis/DB, not in-memory), database schema changes must be backward-compatible with both versions simultaneously.
|
|
98
|
+
|
|
99
|
+
### Platform Selection Decision Matrix
|
|
100
|
+
|
|
101
|
+
| Criteria | Static CDN | Serverless | Container | Edge | Long-Running |
|
|
102
|
+
|----------|-----------|------------|-----------|------|--------------|
|
|
103
|
+
| SSG only | Best | Overkill | Overkill | Good | Overkill |
|
|
104
|
+
| SSR with SEO | — | Best | Good | Good | Good |
|
|
105
|
+
| Real-time (WebSocket) | No | No | Best | No | Best |
|
|
106
|
+
| Low traffic / cost | Best | Best | Expensive | Best | Expensive |
|
|
107
|
+
| High sustained traffic | Best | Expensive | Best | Best | Best |
|
|
108
|
+
| Cold start sensitive | N/A | Problem | Solved | Solved | Solved |
|
|
109
|
+
| Ops complexity | Lowest | Low | Medium | Low | High |
|
|
110
|
+
|
|
111
|
+
### Health Checks and Readiness Probes
|
|
112
|
+
|
|
113
|
+
Every deployed service must expose health endpoints:
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
// app/api/health/route.ts
|
|
117
|
+
export async function GET() {
|
|
118
|
+
try {
|
|
119
|
+
// Check critical dependencies
|
|
120
|
+
await db.query("SELECT 1");
|
|
121
|
+
return Response.json({ status: "healthy", version: process.env.npm_package_version });
|
|
122
|
+
} catch (error) {
|
|
123
|
+
return Response.json({ status: "unhealthy", error: String(error) }, { status: 503 });
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Configure your load balancer or container orchestrator to route traffic only to healthy instances. Health check failure should trigger automatic rollback in your deployment pipeline.
|
|
129
|
+
|
|
130
|
+
### Cost Optimization
|
|
131
|
+
|
|
132
|
+
- Use serverless for variable or low traffic; switch to containers once monthly serverless cost exceeds 2–3 baseline container instances
|
|
133
|
+
- CDN cache hit rate should be above 90% for SSG content — if it is not, investigate cache-busting headers
|
|
134
|
+
- Set spending alerts at 50% and 100% of monthly budget on cloud providers — auto-remediation (scale down) if the alert fires on unexpected traffic
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: web-app-design-system
|
|
3
|
+
description: Responsive token systems, dark/light mode, component library patterns, and CSS methodology selection for web applications
|
|
4
|
+
topics: [web-app, design-system, css, tokens, dark-mode, responsive]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
A design system is the contract between design and engineering. Without one, components drift, spacing is inconsistent, and every engineer makes independent decisions about color, typography, and layout. A well-structured token system makes that contract explicit, machine-enforceable, and refactorable — changing a spacing scale or switching a brand color becomes a one-line edit rather than a codebase-wide search-and-replace.
|
|
8
|
+
|
|
9
|
+
## Summary
|
|
10
|
+
|
|
11
|
+
A design system encodes design decisions as tokens at three tiers: primitive (raw values), semantic (intent-based aliases), and component-scoped overrides. Support dark/light mode via CSS custom properties with both `prefers-color-scheme` and explicit `data-theme` toggle. Commit to a consistent breakpoint scale and CSS methodology. Use headless component libraries for accessible behavior with full visual control.
|
|
12
|
+
|
|
13
|
+
## Deep Guidance
|
|
14
|
+
|
|
15
|
+
### Token Architecture
|
|
16
|
+
|
|
17
|
+
Design tokens are the atoms of a design system. They encode decisions — not values — at three tiers:
|
|
18
|
+
|
|
19
|
+
1. **Primitive tokens** — Raw values with no semantic meaning: `--color-blue-500: #3b82f6`, `--spacing-4: 16px`, `--font-size-lg: 1.125rem`. Never use primitive tokens directly in components.
|
|
20
|
+
|
|
21
|
+
2. **Semantic tokens** — Intent-based aliases of primitives: `--color-interactive: var(--color-blue-500)`, `--space-component-padding: var(--spacing-4)`. Components consume semantic tokens.
|
|
22
|
+
|
|
23
|
+
3. **Component tokens** — Component-scoped overrides: `--button-background: var(--color-interactive)`. Allows per-component theming without touching semantic tokens.
|
|
24
|
+
|
|
25
|
+
Spacing, typography, and breakpoints belong in this hierarchy. A spacing scale (4/8/12/16/24/32/48/64px) enforced via tokens prevents the "just add a margin-top: 11px" habit that destroys visual rhythm.
|
|
26
|
+
|
|
27
|
+
### Dark/Light Mode
|
|
28
|
+
|
|
29
|
+
Use CSS custom properties with `prefers-color-scheme` and an explicit `data-theme` attribute override:
|
|
30
|
+
|
|
31
|
+
```css
|
|
32
|
+
/* Primitive layer */
|
|
33
|
+
:root {
|
|
34
|
+
--color-neutral-0: #ffffff;
|
|
35
|
+
--color-neutral-900: #111827;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/* Semantic layer — light mode defaults */
|
|
39
|
+
:root {
|
|
40
|
+
--color-surface: var(--color-neutral-0);
|
|
41
|
+
--color-text-primary: var(--color-neutral-900);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* Dark mode via media query */
|
|
45
|
+
@media (prefers-color-scheme: dark) {
|
|
46
|
+
:root {
|
|
47
|
+
--color-surface: var(--color-neutral-900);
|
|
48
|
+
--color-text-primary: var(--color-neutral-0);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/* Manual override via JS toggle */
|
|
53
|
+
[data-theme="dark"] {
|
|
54
|
+
--color-surface: var(--color-neutral-900);
|
|
55
|
+
--color-text-primary: var(--color-neutral-0);
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Always support both mechanisms: `prefers-color-scheme` for first-visit experience, `data-theme` for user preference stored in `localStorage`.
|
|
60
|
+
|
|
61
|
+
### CSS Methodology Selection
|
|
62
|
+
|
|
63
|
+
| Approach | Best For | Trade-offs |
|
|
64
|
+
|---|---|---|
|
|
65
|
+
| Utility-first (Tailwind) | Rapid iteration, small teams, consistent constraints | Verbose JSX, limited custom design expression |
|
|
66
|
+
| CSS Modules | Scoped styles with full CSS power, no runtime cost | Manual naming, no global token enforcement |
|
|
67
|
+
| CSS-in-JS (Emotion, styled-components) | Dynamic theming, colocation, TypeScript safety | Runtime cost, hydration complexity in SSR |
|
|
68
|
+
| Zero-runtime (Vanilla Extract, Linaria) | SSR-safe, type-safe tokens, no runtime overhead | Build-time complexity, less dynamic |
|
|
69
|
+
|
|
70
|
+
For most production web apps, the recommendation is: **Tailwind + CSS custom properties** for utility-heavy UIs, or **CSS Modules + tokens** for design-system-first projects where designers own the token layer.
|
|
71
|
+
|
|
72
|
+
### Responsive Breakpoints
|
|
73
|
+
|
|
74
|
+
Commit to a consistent breakpoint scale and never deviate:
|
|
75
|
+
|
|
76
|
+
```css
|
|
77
|
+
/* Mobile-first breakpoints */
|
|
78
|
+
--bp-sm: 640px; /* Large phones */
|
|
79
|
+
--bp-md: 768px; /* Tablets */
|
|
80
|
+
--bp-lg: 1024px; /* Small desktops */
|
|
81
|
+
--bp-xl: 1280px; /* Large desktops */
|
|
82
|
+
--bp-2xl: 1536px; /* Wide screens */
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Use `min-width` queries exclusively (mobile-first). Avoid magic numbers in media queries — always reference the token scale.
|
|
86
|
+
|
|
87
|
+
### Component Library Patterns
|
|
88
|
+
|
|
89
|
+
A component library is the implementation layer of the design system. Key architectural decisions:
|
|
90
|
+
|
|
91
|
+
**Compound components over prop explosion:**
|
|
92
|
+
|
|
93
|
+
```tsx
|
|
94
|
+
// BAD: Props explode as requirements grow
|
|
95
|
+
<Select
|
|
96
|
+
label="Country"
|
|
97
|
+
options={countries}
|
|
98
|
+
placeholder="Select..."
|
|
99
|
+
isSearchable
|
|
100
|
+
isClearable
|
|
101
|
+
isMulti
|
|
102
|
+
maxSelectedItems={3}
|
|
103
|
+
/>
|
|
104
|
+
|
|
105
|
+
// GOOD: Compound pattern — composable, extensible
|
|
106
|
+
<Select value={value} onChange={setValue}>
|
|
107
|
+
<Select.Trigger>
|
|
108
|
+
<Select.Value placeholder="Select country..." />
|
|
109
|
+
</Select.Trigger>
|
|
110
|
+
<Select.Content>
|
|
111
|
+
<Select.Search />
|
|
112
|
+
{countries.map(c => (
|
|
113
|
+
<Select.Item key={c.code} value={c.code}>{c.name}</Select.Item>
|
|
114
|
+
))}
|
|
115
|
+
</Select.Content>
|
|
116
|
+
</Select>
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**Headless components for styling flexibility:**
|
|
120
|
+
Use Radix UI, Headless UI, or React Aria as the unstyled behavior layer. Wire your token system on top. This gives accessible keyboard navigation and ARIA semantics for free while preserving full visual control.
|
|
121
|
+
|
|
122
|
+
**Token enforcement via linting:**
|
|
123
|
+
Use `stylelint-no-invalid-hex` and custom Stylelint rules (or ESLint for CSS-in-JS) to reject hardcoded color values not referencing a token. Automate this in CI.
|
|
124
|
+
|
|
125
|
+
### Typography Scale
|
|
126
|
+
|
|
127
|
+
Build a modular type scale with explicit roles:
|
|
128
|
+
|
|
129
|
+
```css
|
|
130
|
+
:root {
|
|
131
|
+
/* Scale steps — use a modular scale ratio (1.25 or 1.333) */
|
|
132
|
+
--text-xs: 0.75rem; /* 12px — labels, captions */
|
|
133
|
+
--text-sm: 0.875rem; /* 14px — body secondary */
|
|
134
|
+
--text-base: 1rem; /* 16px — body primary */
|
|
135
|
+
--text-lg: 1.125rem; /* 18px — subheadings */
|
|
136
|
+
--text-xl: 1.25rem; /* 20px — section headings */
|
|
137
|
+
--text-2xl: 1.5rem; /* 24px — page headings */
|
|
138
|
+
--text-3xl: 1.875rem; /* 30px — hero headings */
|
|
139
|
+
|
|
140
|
+
/* Line heights tied to text size for proper vertical rhythm */
|
|
141
|
+
--leading-tight: 1.25;
|
|
142
|
+
--leading-normal: 1.5;
|
|
143
|
+
--leading-relaxed: 1.75;
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Never use pixel values for font sizes in component code — only reference scale tokens. This ensures user font size preferences (browser zoom, accessibility settings) are respected.
|
|
148
|
+
|
|
149
|
+
### Design Token Pipeline
|
|
150
|
+
|
|
151
|
+
For teams with a Figma design system, automate the token pipeline:
|
|
152
|
+
|
|
153
|
+
1. Designers export tokens from Figma using the Tokens Studio plugin as a JSON file
|
|
154
|
+
2. CI runs a token transformer (Style Dictionary) that converts JSON to CSS custom properties, TypeScript constants, and platform-specific formats
|
|
155
|
+
3. The generated files are committed to the repository and reviewed in PRs
|
|
156
|
+
4. Token changes are flagged in design review before code review
|
|
157
|
+
|
|
158
|
+
This makes "design changed the brand blue" a designer-owned PR rather than an engineering ticket.
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: web-app-dev-environment
|
|
3
|
+
description: Dev server configuration, HMR setup, API proxy, environment variables, Docker for local services, and browser devtools for web app development
|
|
4
|
+
topics: [web-app, dev-environment, vite, webpack, hmr, docker, debugging]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
A fast, reliable local development environment is a force multiplier for the entire team. The goal is sub-second feedback loops for code changes and zero friction getting from a fresh checkout to a running app. Every minute spent fighting the dev environment is a minute not spent building the product.
|
|
8
|
+
|
|
9
|
+
## Summary
|
|
10
|
+
|
|
11
|
+
A fast web app dev environment targets sub-second feedback loops with HMR and zero-friction onboarding. Use Vite for new projects (or the framework's built-in server for Next.js). Configure an API proxy to avoid CORS issues. Validate environment variables at startup with a schema. Run local dependencies in Docker Compose.
|
|
12
|
+
|
|
13
|
+
## Deep Guidance
|
|
14
|
+
|
|
15
|
+
### Dev Server Choice: Vite vs webpack
|
|
16
|
+
|
|
17
|
+
For new projects in 2024 and beyond, use **Vite** unless you have a specific reason not to:
|
|
18
|
+
|
|
19
|
+
- **Vite**: Native ESM dev server, near-instant startup regardless of project size, esbuild-powered transforms (10–100x faster than Babel), first-class support for React, Vue, Svelte, and TypeScript out of the box.
|
|
20
|
+
- **webpack (via Create React App, Next.js with webpack, or custom)**: Slower cold starts and HMR, but battle-tested and required by some frameworks. Next.js 13+ defaults to Turbopack (Rust-based, approaching Vite speed).
|
|
21
|
+
|
|
22
|
+
If you are on Next.js, you get the dev server bundled with the framework. Do not fight the framework's built-in tooling — configure it via `next.config.ts`, not by ejecting or customizing webpack directly unless absolutely necessary.
|
|
23
|
+
|
|
24
|
+
### HMR Configuration
|
|
25
|
+
|
|
26
|
+
Hot Module Replacement keeps the page live-updating without full reloads. Ensure it is working correctly:
|
|
27
|
+
|
|
28
|
+
- With Vite: HMR works out of the box. If it stops working after upgrading, check `server.hmr` in `vite.config.ts`. Common issue: HMR fails silently when a module has a circular dependency.
|
|
29
|
+
- With React: Install `@vitejs/plugin-react` (uses Babel with Fast Refresh) or `@vitejs/plugin-react-swc` (uses SWC, 3–5x faster). Fast Refresh preserves component state on save — test that it works for your components.
|
|
30
|
+
- Watch for HMR performance degradation in large projects: if HMR is slow, profile with `vite --debug hmr`. The usual cause is a large shared module being invalidated on every change.
|
|
31
|
+
|
|
32
|
+
### API Proxy Configuration
|
|
33
|
+
|
|
34
|
+
During development, your app's origin is `localhost:3000` but your API backend is `localhost:8000`. Avoid CORS issues and hardcoded localhost URLs by configuring a dev proxy:
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
// vite.config.ts
|
|
38
|
+
export default defineConfig({
|
|
39
|
+
server: {
|
|
40
|
+
proxy: {
|
|
41
|
+
"/api": {
|
|
42
|
+
target: "http://localhost:8000",
|
|
43
|
+
changeOrigin: true,
|
|
44
|
+
rewrite: (path) => path.replace(/^\/api/, ""),
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
This means your frontend code always calls `/api/users` and the proxy handles routing to the backend. The same relative URL works in production when the API is behind the same domain. Never hardcode `http://localhost:8000` in application code.
|
|
52
|
+
|
|
53
|
+
### Environment Variables
|
|
54
|
+
|
|
55
|
+
Use `.env` files for environment-specific configuration. Establish clear conventions:
|
|
56
|
+
|
|
57
|
+
- `.env.example` — committed, documents all variables with dummy values
|
|
58
|
+
- `.env.local` — gitignored, developer-specific overrides (actual API keys, local service URLs)
|
|
59
|
+
- `.env.development` — gitignored, shared dev defaults (can be committed if values are non-sensitive)
|
|
60
|
+
- `.env.production` — injected by CI/CD, never committed
|
|
61
|
+
|
|
62
|
+
Validate all required variables at startup. An app that silently uses `undefined` for a missing API URL is worse than one that crashes immediately with a clear error:
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
// lib/env.ts — validate at module load time
|
|
66
|
+
import { z } from "zod";
|
|
67
|
+
|
|
68
|
+
const envSchema = z.object({
|
|
69
|
+
VITE_API_URL: z.string().url(),
|
|
70
|
+
VITE_FEATURE_FLAGS: z.string().default(""),
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
export const env = envSchema.parse(import.meta.env);
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Docker for Local Services
|
|
77
|
+
|
|
78
|
+
Run local dependencies (databases, caches, queues, email servers) in Docker to keep developer machines clean and ensure consistency:
|
|
79
|
+
|
|
80
|
+
```yaml
|
|
81
|
+
# docker-compose.yml
|
|
82
|
+
services:
|
|
83
|
+
postgres:
|
|
84
|
+
image: postgres:16-alpine
|
|
85
|
+
ports: ["5432:5432"]
|
|
86
|
+
environment:
|
|
87
|
+
POSTGRES_DB: myapp_dev
|
|
88
|
+
POSTGRES_USER: dev
|
|
89
|
+
POSTGRES_PASSWORD: dev
|
|
90
|
+
volumes:
|
|
91
|
+
- postgres_data:/var/lib/postgresql/data
|
|
92
|
+
|
|
93
|
+
redis:
|
|
94
|
+
image: redis:7-alpine
|
|
95
|
+
ports: ["6379:6379"]
|
|
96
|
+
|
|
97
|
+
mailpit:
|
|
98
|
+
image: axllent/mailpit
|
|
99
|
+
ports:
|
|
100
|
+
- "1025:1025" # SMTP
|
|
101
|
+
- "8025:8025" # Web UI
|
|
102
|
+
|
|
103
|
+
volumes:
|
|
104
|
+
postgres_data:
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Document the setup in the README: `docker compose up -d` starts all services. Never require developers to install PostgreSQL, Redis, or other services directly on their machines.
|
|
108
|
+
|
|
109
|
+
### Getting to Zero-Friction Setup
|
|
110
|
+
|
|
111
|
+
Document the new developer setup flow and time it. Target under 10 minutes from fresh checkout to running app. Anything over 15 minutes will be skipped and developers will use workarounds.
|
|
112
|
+
|
|
113
|
+
Minimum `package.json` scripts:
|
|
114
|
+
|
|
115
|
+
```json
|
|
116
|
+
{
|
|
117
|
+
"scripts": {
|
|
118
|
+
"dev": "vite",
|
|
119
|
+
"dev:full": "docker compose up -d && vite",
|
|
120
|
+
"build": "tsc && vite build",
|
|
121
|
+
"preview": "vite preview",
|
|
122
|
+
"test": "vitest",
|
|
123
|
+
"test:ui": "vitest --ui",
|
|
124
|
+
"lint": "eslint src --ext .ts,.tsx",
|
|
125
|
+
"typecheck": "tsc --noEmit"
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Include a `Makefile` or `justfile` for multi-step setup commands that developers run once (`make setup` installs deps, configures git hooks, copies `.env.example`).
|
|
131
|
+
|
|
132
|
+
### Browser Devtools Configuration
|
|
133
|
+
|
|
134
|
+
Install and configure browser extensions that accelerate debugging:
|
|
135
|
+
|
|
136
|
+
- **React Developer Tools**: Component tree inspection, props/state browser, profiler for render performance.
|
|
137
|
+
- **Redux DevTools** (if using Redux): Action/state history, time-travel debugging.
|
|
138
|
+
- **Vite plugin for browser devtools**: Install `vite-plugin-inspect` to visualize the Vite plugin pipeline and module graph.
|
|
139
|
+
|
|
140
|
+
Configure source maps in development (`devtool: "eval-source-map"` in webpack or `sourcemap: true` in Vite) so stack traces point to TypeScript source, not compiled JavaScript. Without this, debugging is nearly impossible.
|
|
141
|
+
|
|
142
|
+
### TypeScript Strict Mode
|
|
143
|
+
|
|
144
|
+
Enable strict mode from day one in `tsconfig.json`:
|
|
145
|
+
|
|
146
|
+
```json
|
|
147
|
+
{
|
|
148
|
+
"compilerOptions": {
|
|
149
|
+
"strict": true,
|
|
150
|
+
"noUncheckedIndexedAccess": true,
|
|
151
|
+
"exactOptionalPropertyTypes": true
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Disabling strict mode to make TypeScript "less annoying" creates a false sense of safety. The errors strict mode surfaces are real bugs. Fix them instead of disabling the check.
|
|
157
|
+
|
|
158
|
+
### VS Code Workspace Settings
|
|
159
|
+
|
|
160
|
+
Commit a `.vscode/settings.json` with recommended settings so all developers use consistent formatting:
|
|
161
|
+
|
|
162
|
+
```json
|
|
163
|
+
{
|
|
164
|
+
"editor.formatOnSave": true,
|
|
165
|
+
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
|
166
|
+
"editor.codeActionsOnSave": {
|
|
167
|
+
"source.fixAll.eslint": true
|
|
168
|
+
},
|
|
169
|
+
"typescript.preferences.importModuleSpecifier": "non-relative"
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Commit `.vscode/extensions.json` with recommended extensions. Developers are prompted to install them on workspace open.
|