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:
Florian Wilde
2026-08-09 00:48:50 +02:00
parent a8b196e92b
commit b0c4e9e9b9
101 changed files with 3651 additions and 7695 deletions
+96 -86
View File
@@ -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
```