Template
refactor: rebuild template — Tailwind v4, Docker self-hosting, passkey auth
Toolchain fixes (all previously broken): - npm run lint: next lint was removed in Next 16 -> eslint with flat config - .eslintrc.json was ignored by ESLint 9 -> eslint.config.mjs - npm test / test:e2e exited 1 with no tests -> passWithNoTests - Vitest scanned tests/ and would have run Playwright specs -> scoped to src/ - Playwright targeted Mobile Safari while docs installed only chromium - reuseExistingServer silently tested a foreign server on :3000 -> E2E_PORT - 11 high-severity vulns -> npm audit fix - deny rule Read(**/.env*) also blocked .env.example -> precise patterns Stack changes: - Tailwind v3 -> v4 (CSS-first, no tailwind.config.ts, tw-animate-css) - shadcn regenerated for v4; 33 components -> 6 core, bundled radix-ui - Supabase removed entirely; data layer is now chosen per project - Vercel removed; Docker Compose self-hosting with scripts/update.sh - Better Auth + passkey plugin as the binding auth standard - ThemeProvider and Sonner mounted; dark mode and toasts now actually work Workflow system: - Sub-agents wired: /frontend, /backend, /qa delegate to .claude/agents - Checklists folded into their SKILL.md; one file per skill - Rules rewritten: DB-agnostic backend, passkey security, v4 frontend - Spec language settled as German, skill instructions English
This commit is contained in:
@@ -1,114 +1,124 @@
|
||||
---
|
||||
name: deploy
|
||||
description: Deploy to Vercel with production-ready checks, error tracking, and security headers setup.
|
||||
argument-hint: "feature-spec-path or 'to Vercel'"
|
||||
description: Deploy the Docker Compose stack to a server, with pre-flight checks and rollback.
|
||||
argument-hint: "PROJ-X or 'production'"
|
||||
user-invocable: true
|
||||
---
|
||||
|
||||
# DevOps Engineer
|
||||
# Deploy
|
||||
|
||||
## Role
|
||||
You are an experienced DevOps Engineer handling deployment, environment setup, and production readiness.
|
||||
Self-hosted Docker Compose. There is no Vercel, no managed platform. The stack runs
|
||||
one app container; TLS and routing are handled by a reverse proxy already present
|
||||
on the host.
|
||||
|
||||
## Before Starting
|
||||
1. Read `features/INDEX.md` to know what is being deployed
|
||||
2. Check QA status in the feature spec
|
||||
3. Verify no Critical/High bugs exist in QA results
|
||||
4. If QA has not been done, tell the user: "Run `/qa` first before deploying."
|
||||
## 1. Gate
|
||||
|
||||
## Workflow
|
||||
1. Read `features/INDEX.md` — what is being shipped
|
||||
2. Read the feature spec's QA section
|
||||
|
||||
### 1. Pre-Deployment Checks
|
||||
- [ ] `npm run build` succeeds locally
|
||||
- [ ] `npm run lint` passes
|
||||
- [ ] QA Engineer has approved the feature (check feature spec)
|
||||
- [ ] No Critical/High bugs in test report
|
||||
- [ ] All environment variables documented in `.env.local.example`
|
||||
- [ ] No secrets committed to git
|
||||
- [ ] All database migrations applied in Supabase (if applicable)
|
||||
- [ ] All code committed and pushed to remote
|
||||
**No QA section:** → "Für PROJ-X gibt es noch kein QA-Ergebnis. Führe erst `/qa` aus." → Stop.
|
||||
**Critical or High bugs open:** → name them and stop. Those get fixed first.
|
||||
|
||||
### 2. Vercel Setup (first deployment only)
|
||||
## 2. Pre-flight
|
||||
|
||||
> **Prerequisite (manual, do this first):** The user must create a Vercel account in the browser before this step — go to [vercel.com](https://vercel.com) and sign up (e.g. "Sign up with GitHub"). Account creation and login are browser/OAuth steps that cannot be automated by the skill. Also ensure the repo is pushed to a GitHub remote so Vercel can connect to it.
|
||||
Run and show the results — do not proceed on a failure:
|
||||
|
||||
Guide the user through:
|
||||
- [ ] Create Vercel project: `npx vercel` or via vercel.com
|
||||
- [ ] Connect GitHub repository for auto-deploy on push
|
||||
- [ ] Add all environment variables from `.env.local.example` in Vercel Dashboard
|
||||
- [ ] Build settings: Framework Preset = Next.js (auto-detected)
|
||||
- [ ] Configure domain (or use default `*.vercel.app`)
|
||||
```bash
|
||||
npm run lint
|
||||
npm run typecheck
|
||||
npm test
|
||||
npm run build
|
||||
```
|
||||
|
||||
### 3. Deploy
|
||||
- Push to main branch → Vercel auto-deploys
|
||||
- Or manual: `npx vercel --prod`
|
||||
- Monitor build in Vercel Dashboard
|
||||
Then check:
|
||||
- [ ] Every env var used in code is in `.env.example` with a dummy value
|
||||
- [ ] No secrets in the diff (`git diff --cached`)
|
||||
- [ ] Pending migrations are committed
|
||||
- [ ] Everything committed and pushed to the remote the server pulls from
|
||||
|
||||
### 4. Post-Deployment Verification
|
||||
- [ ] Production URL loads correctly
|
||||
- [ ] Deployed feature works as expected
|
||||
- [ ] Database connections work (if applicable)
|
||||
- [ ] Authentication flows work (if applicable)
|
||||
- [ ] No errors in browser console
|
||||
- [ ] No errors in Vercel function logs
|
||||
## 3. First deployment only
|
||||
|
||||
### 5. Production-Ready Essentials
|
||||
Walk the user through this once. It happens on the server, over SSH.
|
||||
|
||||
For first deployment, guide the user through these setup guides:
|
||||
**Prerequisites the user provides manually:** a server with Docker and the Compose
|
||||
plugin, a reverse proxy (nginx, Caddy, Traefik) terminating TLS, and a DNS record
|
||||
pointing at it.
|
||||
|
||||
**Error Tracking (5 min):** See [error-tracking.md](../../../docs/production/error-tracking.md)
|
||||
**Security Headers (copy-paste):** See [security-headers.md](../../../docs/production/security-headers.md)
|
||||
**Performance Check:** See [performance.md](../../../docs/production/performance.md)
|
||||
**Database Optimization:** See [database-optimization.md](../../../docs/production/database-optimization.md)
|
||||
**Rate Limiting (optional):** See [rate-limiting.md](../../../docs/production/rate-limiting.md)
|
||||
```bash
|
||||
git clone <repo-url> /srv/<app-name> && cd /srv/<app-name>
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
### 6. Post-Deployment Bookkeeping
|
||||
- Update feature spec: Add deployment section with production URL and date
|
||||
- Update `features/INDEX.md`: Set status to **Deployed**
|
||||
- Create git tag: `git tag -a v1.X.0-PROJ-X -m "Deploy PROJ-X: [Feature Name]"`
|
||||
- Push tag: `git push origin v1.X.0-PROJ-X`
|
||||
Then edit `.env`:
|
||||
- `NEXT_PUBLIC_APP_URL` — the real public URL. **If auth is used, this must match
|
||||
the domain exactly**: the WebAuthn relying-party ID comes from this hostname, and
|
||||
a mismatch makes every passkey fail without a useful error.
|
||||
- `APP_PORT` — the port the reverse proxy forwards to
|
||||
- `APP_BIND` — leave at `127.0.0.1` so the container is not exposed directly
|
||||
- `BETTER_AUTH_SECRET` — `openssl rand -base64 32`, unique per environment
|
||||
|
||||
## Common Issues
|
||||
```bash
|
||||
docker compose up -d --build
|
||||
curl -fsS http://127.0.0.1:${APP_PORT:-3000}/api/health
|
||||
```
|
||||
|
||||
### Build fails on Vercel but works locally
|
||||
- Check Node.js version (Vercel may use different version)
|
||||
- Ensure all dependencies are in package.json (not just devDependencies)
|
||||
- Review Vercel build logs for specific error
|
||||
Point the reverse proxy at `127.0.0.1:$APP_PORT` and make sure it forwards
|
||||
`X-Forwarded-Proto` and `X-Forwarded-Host`, otherwise redirects and WebAuthn origin
|
||||
checks break.
|
||||
|
||||
### Environment variables not available
|
||||
- Verify vars are set in Vercel Dashboard (Settings → Environment Variables)
|
||||
- Client-side vars need `NEXT_PUBLIC_` prefix
|
||||
- Redeploy after adding new env vars (they don't apply retroactively)
|
||||
Passkeys need HTTPS in production — confirm TLS works before testing auth.
|
||||
|
||||
### Database connection errors
|
||||
- Verify Supabase URL and anon key in Vercel env vars
|
||||
- Check RLS policies allow the operations being attempted
|
||||
- Verify Supabase project is not paused (free tier pauses after inactivity)
|
||||
## 4. Subsequent deployments
|
||||
|
||||
## Rollback Instructions
|
||||
If production is broken:
|
||||
1. **Immediate:** Vercel Dashboard → Deployments → Click "..." on previous working deployment → "Promote to Production"
|
||||
2. **Fix locally:** Debug the issue, `npm run build`, commit, push
|
||||
3. Vercel auto-deploys the fix
|
||||
On the server:
|
||||
|
||||
## Full Deployment Checklist
|
||||
- [ ] Pre-deployment checks all pass
|
||||
- [ ] Vercel build successful
|
||||
- [ ] Production URL loads and works
|
||||
- [ ] Feature tested in production environment
|
||||
- [ ] No console errors, no Vercel log errors
|
||||
- [ ] Error tracking setup (Sentry or alternative)
|
||||
- [ ] Security headers configured in next.config
|
||||
- [ ] Lighthouse score checked (target > 90)
|
||||
- [ ] Feature spec updated with deployment info
|
||||
- [ ] `features/INDEX.md` updated to Deployed
|
||||
- [ ] Git tag created and pushed
|
||||
- [ ] User has verified production deployment
|
||||
```bash
|
||||
./scripts/update.sh
|
||||
```
|
||||
|
||||
It pulls the branch, rebuilds, restarts, waits for the healthcheck, and rolls back
|
||||
to the previous commit if the new container never turns healthy. `--force` rebuilds
|
||||
without a new commit; `--branch <name>` deploys a different branch.
|
||||
|
||||
If a data layer exists, migrations run before the new container serves traffic —
|
||||
see `docs/DEPLOYMENT.md`.
|
||||
|
||||
## 5. Verify
|
||||
|
||||
- [ ] Public URL loads over HTTPS
|
||||
- [ ] `/api/health` returns `{"status":"ok"}`
|
||||
- [ ] The deployed feature works end to end
|
||||
- [ ] Sign-in works and offers passkey first (if auth exists)
|
||||
- [ ] No console errors, no errors in `docker compose logs app`
|
||||
- [ ] Security headers survived the proxy (DevTools → Network → Response Headers)
|
||||
|
||||
## 6. Bookkeeping
|
||||
|
||||
- Add a Deployment section to the spec: URL, date, commit SHA
|
||||
- `features/INDEX.md` → **Deployed** (write, then re-read to verify)
|
||||
- Tag: `git tag -a v1.X.0-PROJ-X -m "Deploy PROJ-X: [name]"` and push it
|
||||
|
||||
## Rollback
|
||||
|
||||
`scripts/update.sh` rolls back automatically on an unhealthy container. Manually:
|
||||
|
||||
```bash
|
||||
git reset --hard <previous-sha>
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
## Common failures
|
||||
|
||||
| Symptom | Cause |
|
||||
|---------|-------|
|
||||
| Build works locally, fails in Docker | A dependency sits in devDependencies but is needed at build time |
|
||||
| Env var undefined at runtime | Not in `.env` on the server, or missing `NEXT_PUBLIC_` for client use |
|
||||
| Container healthy, proxy returns 502 | Proxy points at the wrong port, or `APP_BIND` is not reachable from it |
|
||||
| Passkeys fail after deploy | `NEXT_PUBLIC_APP_URL` does not match the real domain, or TLS is missing |
|
||||
| Redirect loop | Proxy not forwarding `X-Forwarded-Proto` |
|
||||
|
||||
## Commit
|
||||
|
||||
## Git Commit
|
||||
```
|
||||
deploy(PROJ-X): Deploy [feature name] to production
|
||||
|
||||
- Production URL: https://your-app.vercel.app
|
||||
- Deployed: YYYY-MM-DD
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user