Files
ai-coding-starter-kit-v2/.claude/skills/deploy/SKILL.md
T
patrickandClaude Sonnet 5 4a19335a1e feat: rework starter kit for self-hosted deploy (Vite/React + Fastify/Drizzle/Postgres)
Replace Next.js/Supabase/Vercel stack with a self-hostable setup: Vite+React
frontend, Fastify+Drizzle+PostgreSQL backend with own JWT auth, deploy via
git pull + rsync + systemd (checkout/service separated, updates pulled from
Gitea). Adds a reference auth route (register/login/me) as the canonical
pattern for new routes. Updates all skills/rules/agents/docs to match.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BMdBJfD9TT6XUU2NqGG1PN
2026-09-08 11:42:47 +02:00

5.6 KiB

name, description, argument-hint, user-invocable, allowed-tools, model
name description argument-hint user-invocable allowed-tools model
deploy Deploy to a self-managed Linux server via git pull + rsync + systemd, with production-ready checks.
feature-spec-path or "to production"
true Read, Write, Edit, Glob, Grep, Bash, AskUserQuestion sonnet

DevOps Engineer

Role

You are an experienced DevOps Engineer handling deployment, environment setup, and production readiness on a self-hosted server (no PaaS/Vercel).

Server Layout Convention

Checkout and running service are kept separate, so a git pull never silently swaps out a running process's code:

/opt/<project>/repo       git checkout only, pulled from Gitea
/opt/<project>/backend    running backend service, own .env, own node_modules
/var/www/<project>        built frontend static files, served by nginx

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."

Workflow

1. Pre-Deployment Checks

  • npm run build succeeds locally (frontend and backend)
  • 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.example
  • No secrets committed to git
  • All Drizzle migrations generated and committed
  • All code committed and pushed to Gitea

2. Server Setup (first deployment only)

Guide the user through, on the target server:

  • git clone <gitea-url> /opt/<project>/repo
  • Create /opt/<project>/backend, copy backend files in, create .env from .env.example
  • Create PostgreSQL database + role for the app
  • Create a systemd unit for the backend (/etc/systemd/system/<project>-backend.service), ExecStart=node dist/server.js, WorkingDirectory=/opt/<project>/backend, EnvironmentFile=/opt/<project>/backend/.env
  • Configure nginx: reverse proxy /api/ to the backend port, serve /var/www/<project> as static root for everything else
  • systemctl enable --now <project>-backend

3. Deploy (update)

Run from a machine with SSH access to the server:

ssh <user>@<server> "cd /opt/<project>/repo && git pull --ff-only \
  && rsync -a --exclude='.env' --exclude='node_modules' /opt/<project>/repo/backend/ /opt/<project>/backend/ \
  && cd /opt/<project>/backend && npm ci --omit=dev && npm run db:migrate \
  && systemctl restart <project>-backend \
  && cd /opt/<project>/repo/frontend && npm ci && npm run build \
  && rsync -a --delete dist/ /var/www/<project>/"
  • Frontend-only change → skip the backend rsync/migrate/restart block, just rebuild and rsync dist/
  • Updates are pulled from Gitea (git pull --ff-only) — never edit code directly on the server

4. Post-Deployment Verification

  • Production URL loads correctly
  • Deployed feature works as expected
  • Database connections work (check backend logs: journalctl -u <project>-backend -f)
  • Authentication flows work (if applicable)
  • No errors in browser console
  • No errors in journalctl -u <project>-backend

5. Production-Ready Essentials

For first deployment, guide the user through these setup guides:

Error Tracking: See error-tracking.md Security Headers: See security-headers.md Performance Check: See performance.md Database Optimization: See database-optimization.md Rate Limiting: See rate-limiting.md

6. Post-Deployment Bookkeeping

  • Update feature spec: Add deployment section with 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

Common Issues

Build works locally but fails on server

  • Check Node.js version matches between local and server (node -v)
  • Ensure all dependencies are in dependencies, not just devDependencies, if npm ci --omit=dev is used for the backend

Environment variables not available

  • Verify .env exists in /opt/<project>/backend (it is excluded from rsync on purpose, so it survives deploys)
  • Frontend vars need the VITE_ prefix and are baked in at build time — rebuild after changing them

Database connection errors

  • Verify DATABASE_URL in the server's .env
  • Check the app's database role has the needed grants
  • journalctl -u <project>-backend for the actual driver error

Rollback Instructions

If production is broken:

  1. Immediate: on the server, cd /opt/<project>/repo && git checkout <last-good-tag>, redo step 3's rsync/build for that commit
  2. Fix locally: debug the issue, npm run build, commit, push
  3. Redeploy via step 3

Full Deployment Checklist

  • Pre-deployment checks all pass
  • Build successful (frontend + backend)
  • Production URL loads and works
  • Feature tested in production environment
  • No console errors, no backend log errors
  • Error tracking setup
  • Security headers configured (nginx or @fastify/helmet)
  • 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

Git Commit

deploy(PROJ-X): Deploy [feature name] to production

- Deployed: YYYY-MM-DD