Kurzfassung
Für ein Next.js-Projekt auf Node 22, Next 15.5.18 und Build via scripts/build.cjs empfehlen wir eine GitHub-Actions-Pipeline: jeder PR = Qualität (lint + build), Merge auf main = Deploy auf Vercel. In diesem Repository gibt es noch keinen Ordner .github/workflows, der Artikel beschreibt den Zielzustand, den Sie gleich anlegen sollten, statt auf manuelles „bei mir geht’s“ zu vertrauen. Secrets (VERCEL_TOKEN, DATABASE_URL, API-Keys) nur in GitHub Secrets.
Für wen ist das
- Teams mit 1–5 Entwicklern auf Next.js + Vercel
- Projekte mit Prisma (
postinstall:prisma generate, Migrate im Build-Skript) - Firmen, die auditierbare Deploy-Historie und Preview-URL pro PR wollen
- Monorepos oder mehrere Apps in einem Repo (Abschnitt
paths:)
Keyword (SEO)
ci cd nextjs github actions, pipeline nextjs 2026, vercel deployment automatisieren, github actions build nextjs, branch protection main, vercel rollback
Ausgangspunkt: ehrlicher Repo-Status
In vielen Produktionsprojekten „existiert“ die Pipeline im Kopf des Teams, nicht im Repo. Hier:
package.jsonverlangt Node 22.x (engines.node),- Next.js 15.5.18, Skripte:
build→node scripts/build.cjs,lint→eslint,postinstall→prisma generate, - Keine Dateien
.github/workflows/*.yml, CI muss bewusst ergänzt werden.
Das ist kein Mangel, normaler Reifegrad. Problematisch wird es, wenn Deploy vom Laptop dieselben Schritte wie der PR umgeht. Ziel: ein Artefakt, Commit bestand lint und build in Actions → derselbe Commit landet auf Vercel.
Was scripts/build.cjs macht (und warum CI es braucht)
Rohes next build in CI reicht oft nicht, wenn:
- Prisma, Skript lädt
.env/.env.local(in Actions nicht im Repo), führtprisma generateaus und beiDATABASE_URLauchprisma migrate deploy, am Endenext build. - Lokal hat der Entwickler eine DB; in CI kann der Build ohne Migration durchlaufen, wenn kein Secret gesetzt ist, aber generate ist nach
npm cinötig (auch viapostinstall).
Pipeline-Folgerung: Build-Job muss npm run build (nicht rohes next build) mit passenden Env-Variablen in GitHub Secrets / Environments aufrufen. Für PR ohne DB reicht oft DATABASE_URL auf Shadow-DB oder Migration weglassen, je nach Team-Policy; Prod braucht volle Secrets im Environment production.
DATABASE_URL-Strategien in CI (Prisma)
| Strategie | Wann | Plus / Minus |
|---|---|---|
| Gleiche URL wie Staging | Kleines Team, eine Test-DB | Schnell; Migrations-Kollision bei parallelen PRs |
| Eigene DB pro PR (Branchly Branch) | Größeres Team | Schema-Isolation; passend zur DevStudio-Plattform |
Kein DATABASE_URL im PR |
Nur statisches Frontend | Build kann migrate deploy überspringen (Log in build.cjs); Schema muss im Repo aktuell sein |
Volle URL nur auf main |
Kompromiss | PR: lint + tsc + build ohne Migrate; Prod: volle Pipeline |
Im DevStudio-Style-Build ohne DATABASE_URL schreibt das Skript eine Meldung und überspringt prisma migrate deploy, führt aber prisma generate aus, konsistent mit postinstall, verhindert „Client not generated“.
Empfohlene Aufteilung: PR vs. main
| Schritt | Pull Request | Push auf main |
|---|---|---|
npm ci |
ja | ja |
npm run lint (ESLint) |
ja | ja |
npx tsc --noEmit |
ja (bei TypeScript) | ja |
npm run build |
ja | ja |
| Unit-Tests | ja, wenn vorhanden | ja |
| Vercel-Deploy Preview | ja (Git-Integration oder Actions) | , |
| Vercel-Deploy Production | , | ja |
| Lighthouse CI | optional | optional (z. B. Cron) |
Regel: nichts in main mergen, was nicht denselben build wie Produktion bestanden hat.
Vollständiges Workflow-Beispiel (.github/workflows/ci.yml)
Die folgende Datei ist kopierfertig anpassbar. Nutzt Node 22, npm-Cache, lint, typecheck und build wie in diesem Repo.
name: CI
on:
pull_request:
branches: [main]
push:
branches: [main]
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
quality:
runs-on: ubuntu-latest
timeout-minutes: 25
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js 22
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: ESLint
run: npm run lint
- name: TypeScript (no emit)
run: npx tsc --noEmit
- name: Build (Prisma + Next via scripts/build.cjs)
run: npm run build
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
NEXT_PUBLIC_SITE_URL: ${{ vars.NEXT_PUBLIC_SITE_URL || 'https://example.com' }}
deploy-preview:
if: github.event_name == 'pull_request'
needs: quality
runs-on: ubuntu-latest
environment: preview
steps:
- uses: actions/checkout@v4
- uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
github-token: ${{ secrets.GITHUB_TOKEN }}
scope: ${{ secrets.VERCEL_ORG_ID }}
deploy-production:
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
needs: quality
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4
- uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
vercel-args: '--prod'
github-token: ${{ secrets.GITHUB_TOKEN }}
scope: ${{ secrets.VERCEL_ORG_ID }}Einfachere Alternative: Vercel Git Integration aktivieren, Vercel baut Preview pro PR, Job quality in Actions bleibt Merge-Gate. Viele Teams kombinieren: Actions = lint/tsc/build, Vercel = Hosting + URL.
Secrets und Variablen, wo was liegt
| Name | Wo | Hinweise |
|---|---|---|
VERCEL_TOKEN |
GitHub Secret | Token aus Vercel Account Settings |
VERCEL_ORG_ID, VERCEL_PROJECT_ID |
GitHub Secret | Aus .vercel/project.json nach vercel link |
DATABASE_URL |
Secret + Vercel Env | Gleicher Wert wie Prod für migrate deploy |
OPENAI_API_KEY, Stripe usw. |
Secret / Vercel | Nie im Repo oder in Actions-Logs |
NEXT_PUBLIC_* |
Variables (nicht geheim) oder Vercel | Identisch in PR-Build und Prod, sonst kehrt „bei mir geht’s“ zurück |
Im Repo: Settings → Secrets and variables → Actions. Für Produktion Environment production mit optional Required reviewers (1–2 Personen).
Branch Protection auf main
Minimum ab Tag eins:
- Require pull request before merging
- Require status check quality (Job-Name aus Workflow)
- Require branch to be up to date
- Do not allow bypassing (auch Admin, wenn das Team diszipliniert ist)
- Optional: require signed commits
So landet kein Build in Prod, der npm run lint und npm run build auf Node 22 nicht bestanden hat.
Preview-URL pro PR
Vercel Git Integration (empfohlen zum Start):
- automatische URL wie
projekt-git-branch-xyz.vercel.app, - Bot-Kommentar im PR mit Link,
- QA und Kunde prüfen vor Merge.
GitHub Actions + vercel-action (wie im YAML oben):
- volle Kontrolle, derselbe Token wie Prod-Deploy,
- sinnvoll bei einem Pipeline-YAML statt Vercel-Panel.
In beiden Fällen: NEXT_PUBLIC_* auf Preview nicht leer, sonst grüner PR-Build, aber anderes UI auf Preview als Prod.
Env-Sync: in Vercel Variablen von Production nach Preview kopieren (oder Vercel CLI vercel env pull). In GitHub dieselben NEXT_PUBLIC_* als Variables, dann baut Job quality denselben Code wie Preview. Secrets (DATABASE_URL, STRIPE_SECRET_KEY) nur in Secrets.
Monorepo: nicht alles bei jedem PR bauen
Bei apps/web und packages/ui im selben Repo separate Workflows mit Pfadfilter:
on:
pull_request:
paths:
- 'apps/web/**'
- 'packages/ui/**'
- 'package-lock.json'Oder paths-ignore für Doku (docs/**, content/blog/**), um keinen 8-Minuten-Build bei Blog-Tippfehler zu starten, sofern der Blog nicht Teil desselben Next.js-Pakets ist (bei monolithischer Marketing-Site oft trotzdem Full-Build).
Rollback auf Vercel in ~60 Sekunden
Prod-Deploy auf Vercel ist ein neues Deployment; alte Builds bleiben.
Notfallprozedur:
- Vercel Dashboard → Deployments
- Letztes funktionierendes Deployment finden (vorheriger Commit)
- ⋯ → Promote to Production
Oft unter einer Minute. Pipeline ersetzt Rollback nicht, sie stellt sicher, dass der promotierte Build einmal grün im PR war. Deploy vom Laptop „schnell“ neben CI vermeiden, sonst kann Rollback im Panel eine andere Version wiederherstellen als erwartet.
Bei eigenem Server (Docker): Image-Tag = Commit-SHA; Rollback = vorheriger Tag im Orchestrator. Gleiche Regel: ein Artefakt aus CI.
Sicherheit in CI/CD
permissions: contents: readstandardmäßig, minimaleGITHUB_TOKEN-Rechte- separates Environment
productionmit Approval - Dependabot /
npm auditin wöchentlichem Workflow - Secrets und volle
.envnie in Logsechoen, Actions maskiertsecrets.*, eigene Skripte müssen sauber sein - Rotation von
VERCEL_TOKENund API-Keys quartalsweise oder nach Team-Austritt
Häufige Fehler (und Vermeidung)
| Fehler | Folge | Fix |
|---|---|---|
PR-Build ohne NEXT_PUBLIC_* |
Anderes Bundle als Prod | Variables in GitHub + Vercel Preview |
next build statt npm run build |
Kein Prisma migrate/generate | Immer Repo-Skript |
Node 20 in Actions, 22 in engines |
Zufällige native Modul-Fehler | node-version: '22' |
| Kein npm-Cache | 8 Min statt 3 | cache: 'npm' in setup-node |
| Deploy vom Laptop + CI | Zwei Wahrheiten | Nur Merge → main → Deploy |
| Keine Branch Protection | Prod-Bruch am Freitagabend | Pflicht-Check quality |
FAQ
Ersetzen GitHub Actions Vercel?
Nein. Actions = Qualitätskontrolle und optional CLI-Deploy; Vercel = Hosting, CDN, Preview, Rollback. Meist: Actions für lint/build, Vercel für App-Ausführung.
prisma migrate deploy in CI?
In diesem Projekt macht das scripts/build.cjs, wenn DATABASE_URL gesetzt ist. Im PR Test-DB oder Migration weglassen, Schema muss trotzdem passen (generate nötig). Auf main/prod muss DATABASE_URL vollständig sein.
Was ohne Tests?
Mit lint + tsc + build starten. Tests hinzufügen bei kritischen Pfaden (Zahlung, Vertrags-API). Pipeline liefert schon ~80 % Wert.
Monorepo mit drei Apps?
Drei Workflows mit paths: oder ein Workflow mit strategy.matrix, kein globaler Build ohne Filter.
Node-Version mit Vercel synchronisieren?
In Vercel Project Settings Node.js 22.x, passend zu engines in package.json.
Troubleshooting: roter Build in Actions
prisma generatefailed, Node (22), obnpm cifertig, Schema im Repo korrekt.migrate deployfailed, DB von GitHub aus unreachable (Firewall), falsche Migration, Konflikt mit manuellen DB-Änderungen.next buildOOM, Runner upgraden (selten) oder schwere Imports prüfen.- Lint fail im PR, lokal
npm run lintauf Node 22; nicht mit--no-verifymergen. - Preview OK, Prod nicht, Vercel Production vs. Preview Environment Variables vergleichen; oft fehlt ein
NEXT_PUBLIC_*.
Actions-Logs sind der Audit vor Produktion, genau einen Schritt lesen, der rot ist.
Cache und parallele PRs
Mit concurrency: cancel-in-progress: true bricht ein neuer Push auf demselben Branch den laufenden CI-Lauf ab, spart Minuten bei schnellen Fix-Commits. Ergänzen Sie npm- und .next/cache-Caching in Actions, wenn Builds regelmäßig über sechs Minuten dauern. Bei Prisma-Projekten: prisma generate läuft ohnehin über postinstall, teure Schritte sind meist next build und Typecheck; dort lohnt sich stabile Node-22-Version und identische Lockfile-Disziplin (npm ci, nie npm install in CI).
Plan, Implementierung an einem Tag
.github/workflows/ci.ymlhinzufügen (Fragment oben).- Secrets + Variables (DATABASE_URL, Vercel, NEXT_PUBLIC_*).
- Branch Protection auf
main. - Repo mit Vercel verbinden (falls noch nicht).
- Test-PR, grüner
quality+ Preview-URL. - Mergen, Production-Deployment prüfen, Rollback-Prozedur ins Team-README.
Zusammenfassung
CI/CD für Next.js 15 auf Node 22 ist kein Hexenwerk, wiederholbar: npm ci → lint → typecheck → npm run build (Prisma + Next) pro PR, Deploy auf Vercel nach Merge, Secrets außerhalb des Repos, Preview zur Abnahme, Rollback via Promote im Panel. Fehlende Workflows im Repository sind das Signal, das jetzt zu ergänzen, bevor manueller Deploy mehr kostet als ein Tag Produktions-Reparatur.
Pipeline für Ihr Projekt?
- Kontakt aufnehmen,
package.json, Vercel und Prisma für Ihren Fall prüfen - Web-Apps, Next.js, Hosting und DevOps aus einer Hand
Über den Autor
Wir bauen schnelle Websites, Web/Mobile-Apps, KI-Chatbots und Hosting — mit Fokus auf SEO und Conversion.
Empfohlene Links
Von Theorie zu Produktion — Branchly, Hosting-Stack und Referenzen.
