Nutze diese Checkliste, um jedes System vor dem Launch deiner Kit-Anwendung zu überprüfen. Jeder Abschnitt deckt einen kritischen Bereich ab — Umgebungskonfiguration, Datenbankbereitschaft, Sicherheitshärtung, Authentifizierung, Zahlungen, Performance, SEO und Monitoring. Schließe alle Punkte ab, bevor du echte Nutzer auf deine Production-URL weiterleitest.
Diese Checkliste setzt voraus, dass du bereits auf Vercel deployt hast (siehe Vercel Deployment) und deine CI/CD-Pipeline konfiguriert hast (siehe CI/CD Pipeline). Der Fokus liegt hier auf production-spezifischer Konfiguration, die über das initiale Deployment hinausgeht.
Umgebungsvariablen
Jeder externe Dienst benötigt Production-Zugangsdaten. Die Verwendung von Entwicklungs- oder Test-Schlüsseln in Production führt zu stillen Fehlern, Datenverlust oder Sicherheitslücken.
1
Production-App-URL setzen
bash
NEXT_PUBLIC_APP_URL=https://yourdomain.com
Dieser Wert wird für absolute URLs in E-Mails, Sitemap-Generierung, Open Graph Tags und Webhook-Callbacks verwendet. Ein falscher Wert führt zu defekten Links in der gesamten Anwendung.
2
CORS-Origins konfigurieren
bash
ALLOWED_ORIGINS=https://yourdomain.com
Verwende niemals
* für ALLOWED_ORIGINS in Production. Das deaktiviert den CORS-Schutz vollständig. Liste nur deine Production-Domain und vertrauenswürdige Subdomains auf.3
Rate Limiting aktivieren
bash
UPSTASH_REDIS_REST_URL=https://your-redis.upstash.io
UPSTASH_REDIS_REST_TOKEN=your-token
Rate Limiting ist in Production erforderlich. Ohne Upstash Redis ist das gesamte API Rate Limiting deaktiviert und deine Endpunkte sind Missbrauch ausgesetzt. Kit verwendet kategoriebasiertes Rate Limiting (Auth, API, KI, Webhooks) mit unterschiedlichen Limits pro Kategorie.
4
Cron Secret setzen
bash
CRON_SECRET=your-random-32-char-string
Generiere mit
openssl rand -base64 32. Vercel Cron Jobs senden diesen Wert im Authorization-Header. Ohne ihn lehnen die Trial-Check- und Credit-Expiry-Endpunkte alle Anfragen ab.5
Alle Service-Schlüssel auf Production-Schlüssel prüfen
Bestätige, dass jeder API-Schlüssel von der Production-Instanz des jeweiligen Dienstes stammt, nicht von Entwicklung oder Test:
| Dienst | Entwicklungsschlüssel-Muster | Production-Schlüssel-Muster |
|---|---|---|
| Clerk | pk_test_... / sk_test_... | pk_live_... / sk_live_... |
| Lemon Squeezy | Testmodus im Dashboard | Live-Modus im Dashboard |
| Supabase | Lokales oder Staging-Projekt | Production-Projekt |
| Resend | Entwicklungsdomain | Verifizierte Production-Domain |
| Upstash | Beliebige Instanz | Production-Tier-Instanz |
| KI-Provider | AI_API_KEY=... oder individuelle Schlüssel | Production-Schlüssel vom jeweiligen Provider-Dashboard |
6
KI-Provider-Schlüssel konfigurieren
Falls deine Anwendung KI-Features verwendet (LLM Chat, RAG Chat, Vision Chat), stelle sicher, dass mindestens ein Provider-Schlüssel konfiguriert ist:
| Setup | Benötigte Variablen |
|---|---|
| Einfach (einzelner Provider) | AI_PROVIDER + AI_API_KEY |
| Erweitert (Multi-Provider-Fallback) | Provider-spezifische Schlüssel: OPENAI_API_KEY, ANTHROPIC_API_KEY, etc. |
| RAG-Features | OPENAI_API_KEY ist erforderlich für die Embedding-Generierung, auch wenn dein Chat-Provider Anthropic/Google/xAI ist |
Konfiguriere KI-Feature-Flags entsprechend deinen Anforderungen:
| Flag | Standard | Zweck |
|---|---|---|
NEXT_PUBLIC_AI_LLM_CHAT_ENABLED | true | LLM Chat auf /dashboard/chat-llm |
NEXT_PUBLIC_AI_RAG_CHAT_ENABLED | true | RAG Chat auf /dashboard/chat-rag |
NEXT_PUBLIC_AI_VISION_ENABLED | true | Bildanalyse im LLM Chat (erfordert aktivierten LLM Chat) |
NEXT_PUBLIC_AI_AUDIO_INPUT_ENABLED | true | Spracheingabe im LLM Chat (erfordert aktivierten LLM Chat) |
NEXT_PUBLIC_AI_PDF_CHAT_ENABLED | true | PDF-Analyse im LLM Chat (erfordert aktivierten LLM Chat) |
NEXT_PUBLIC_AI_IMAGE_GEN_ENABLED | true | Bildgenerierung auf /dashboard/image-gen (erfordert OPENAI_API_KEY) |
NEXT_PUBLIC_AI_CONTENT_GEN_ENABLED | true | Content Generator auf /dashboard/content |
Siehe KI-Provider für die vollständige Provider-Einrichtungsanleitung.
Datenbank
1
Migrationen in Production ausführen
bash
cd apps/boilerplate && npx prisma migrate deploy
Das wendet alle ausstehenden Migrationen auf deine Production-Datenbank an. Im Gegensatz zu
prisma db push (für die Entwicklung) ist migrate deploy sicher für Production — es wendet nur neue Migrationen an und setzt niemals Daten zurück.prisma db push kann Spalten und Tabellen löschen, um das Schema anzupassen. Verwende immer prisma migrate deploy für Production-Datenbanken.2
Connection Pooling überprüfen
Kit verwendet zwei Datenbankverbindungs-Strings:
| Variable | Zweck | Verbindungstyp |
|---|---|---|
DATABASE_URL | Anwendungsabfragen | Gepoolte Verbindung (via PgBouncer, Port 6543) |
DIRECT_URL | Prisma-Migrationen | Direkte Verbindung (Port 5432) |
Supabase stellt beide URLs in den Projekteinstellungen bereit. Die gepoolte Verbindung verarbeitet gleichzeitige Anfragen effizient, während die direkte Verbindung für Schema-Migrationen benötigt wird.
3
pgvector-Erweiterung überprüfen
Falls du RAG-Features verwendest (KI-Dokumenten-Chat), muss die pgvector-Erweiterung aktiviert sein:
sql
CREATE EXTENSION IF NOT EXISTS vector;
Supabase aktiviert das automatisch, aber überprüfe es, falls du von einem anderen Provider migriert bist.
Sicherheit
Kit enthält eine umfassende Sicherheitsschicht, die standardmäßig aktiv ist. Überprüfe, ob diese Einstellungen für deine Production-Umgebung korrekt konfiguriert sind.
1
Sicherheits-Header (automatisch konfiguriert)
Die folgenden Header werden auf alle Routen via
next.config.mjs angewendet:next.config.mjs — Production Security Headers
// Security Headers
async headers() {
return [
{
source: '/:path*',
headers: [
{
key: 'X-DNS-Prefetch-Control',
value: 'on',
},
{
key: 'X-Frame-Options',
value: 'SAMEORIGIN',
},
{
key: 'X-Content-Type-Options',
value: 'nosniff',
},
{
key: 'X-XSS-Protection',
value: '1; mode=block',
},
{
key: 'Referrer-Policy',
value: 'strict-origin-when-cross-origin',
},
{
key: 'Permissions-Policy',
value: 'camera=(), microphone=(self), geolocation=(), interest-cohort=(), payment=(), usb=()',
},
{
key: 'Content-Security-Policy',
value: ContentSecurityPolicy.replace(/\s{2,}/g, ' ').trim(),
},
],
},
]
},
| Header | Schutz |
|---|---|
| Content-Security-Policy | Verhindert XSS durch Einschränkung von Script-/Style-/Bildquellen |
| X-Frame-Options | Verhindert Clickjacking durch Blockierung von iframe-Einbettung |
| X-Content-Type-Options | Verhindert MIME-Type-Sniffing-Angriffe |
| X-XSS-Protection | Legacy-XSS-Filter für ältere Browser |
| Referrer-Policy | Kontrolliert Informationen, die im Referer-Header gesendet werden |
| Permissions-Policy | Schränkt Kamera und Geolocation ein; Mikrofon für Same-Origin-Audioeingabe erlaubt |
Diese werden automatisch angewendet — keine Konfiguration erforderlich. Falls du neue vertrauenswürdige Script-Quellen hinzufügst (Analytics, Chat-Widgets), aktualisiere das
TRUSTED_SCRIPT_SOURCES-Array in next.config.mjs.2
CORS-Origins eingeschränkt
Überprüfe, ob
ALLOWED_ORIGINS nur deine Production-Domain enthält. Die Sicherheits-Middleware lehnt API-Anfragen von Origins ab, die nicht in dieser Liste stehen.3
Rate Limiting aktiv
Überprüfe, ob Upstash Redis-Zugangsdaten gesetzt sind. Teste, indem du den Health-Endpunkt aufrufst:
bash
curl https://yourdomain.com/api/health
Falls Rate Limiting aktiv ist, geben schnell wiederholte Anfragen
429 Too Many Requests zurück.4
API-Schlüssel-Rotationsplan erstellen
Setze Erinnerungen für regelmäßige Schlüssel-Rotation:
| Kategorie | Rotationsintervall | Dienste |
|---|---|---|
| Kritisch | Alle 90 Tage | Clerk, Lemon Squeezy, Supabase Service Role |
| Standard | Alle 180 Tage | Resend, Upstash, Vercel Blob, KI-Provider |
Siehe die Sicherheitsübersicht für detaillierte Rotationsverfahren.
5
Eingabe-Sanitierung (eingebaut)
Kit sanitiert alle Benutzereingaben serverseitig gegen XSS und SQL-Injection. Das ist standardmäßig in API-Routen und Server Actions aktiv — keine Konfiguration erforderlich.
Authentifizierung
1
Clerk Production-Instanz verwenden
Clerk trennt Entwicklungs- und Production-Instanzen. Dein Production Deployment muss die Production-Instanz verwenden:
- Publishable Key beginnt mit
pk_live_ - Secret Key beginnt mit
sk_live_
Die Verwendung von
pk_test_-Schlüsseln in Production zeigt ein Entwicklungs-Banner und schränkt die Funktionalität ein.2
Webhook-Endpunkt konfigurieren
Setze die Clerk-Webhook-URL auf deine Production-Domain:
https://yourdomain.com/api/webhooks/clerk
Füge das Webhook-Secret als
CLERK_WEBHOOK_SECRET in deinen Vercel-Umgebungsvariablen hinzu. Kit verwendet Clerk-Webhooks, um Benutzerdaten mit der lokalen Datenbank zu synchronisieren.3
Social-Login-Provider aktivieren
Aktiviere und konfiguriere im Clerk Dashboard mindestens:
- Google — Deckt die meisten Nutzer ab
- GitHub — Wichtig für entwicklerorientierte SaaS
Jeder Provider benötigt OAuth-Zugangsdaten von der jeweiligen Plattform. Das Clerk-Dashboard führt dich durch die Einrichtung.
4
Authentifizierungsflow testen
Überprüfe nach dem Deployment den vollständigen Flow:
- Neues Konto registrieren
- Mit E-Mail und Passwort einloggen
- Mit einem Social-Provider einloggen
- Passwort per E-Mail zurücksetzen
- Eine geschützte Route aufrufen (
/dashboard) - Ausloggen und Weiterleitung überprüfen
Zahlungen
1
Zu Lemon Squeezy Production-Modus wechseln
Stelle im Lemon Squeezy Dashboard sicher, dass dein Shop im Live-Modus ist (nicht im Testmodus). Testmodus-Transaktionen verarbeiten keine echten Zahlungen.
2
Production-Webhook konfigurieren
Setze die Webhook-URL im Lemon Squeezy Dashboard:
https://yourdomain.com/api/webhooks/lemonsqueezy
Überprüfe, ob das Webhook-Secret mit
LEMONSQUEEZY_WEBHOOK_SECRET in deiner Vercel-Umgebung übereinstimmt.3
Alle Plan-Variant-IDs setzen
Jeder Preisplan benötigt seine konfigurierte Lemon Squeezy Variant-ID:
bash
# Abonnementbasierte Preisgestaltung
NEXT_PUBLIC_LEMONSQUEEZY_BASIC_MONTHLY_VARIANT_ID=...
NEXT_PUBLIC_LEMONSQUEEZY_BASIC_YEARLY_VARIANT_ID=...
NEXT_PUBLIC_LEMONSQUEEZY_PRO_MONTHLY_VARIANT_ID=...
NEXT_PUBLIC_LEMONSQUEEZY_PRO_YEARLY_VARIANT_ID=...
NEXT_PUBLIC_LEMONSQUEEZY_ENTERPRISE_MONTHLY_VARIANT_ID=...
NEXT_PUBLIC_LEMONSQUEEZY_ENTERPRISE_YEARLY_VARIANT_ID=...
# Kreditbasierte Preisgestaltung (bei Verwendung von NEXT_PUBLIC_PRICING_MODEL=credit_based)
NEXT_PUBLIC_CREDIT_BASIC_MONTHLY_VARIANT_ID=...
NEXT_PUBLIC_CREDIT_PRO_MONTHLY_VARIANT_ID=...
NEXT_PUBLIC_CREDIT_ENTERPRISE_MONTHLY_VARIANT_ID=...
# Bonus-Credit-Pakete (falls NEXT_PUBLIC_BONUS_CREDITS_ENABLED=true)
NEXT_PUBLIC_BONUS_BASIC_PACKAGE1_VARIANT_ID=...
NEXT_PUBLIC_BONUS_BASIC_PACKAGE2_VARIANT_ID=...
NEXT_PUBLIC_BONUS_PRO_PACKAGE1_VARIANT_ID=...
NEXT_PUBLIC_BONUS_PRO_PACKAGE2_VARIANT_ID=...
NEXT_PUBLIC_BONUS_ENTERPRISE_PACKAGE1_VARIANT_ID=...
NEXT_PUBLIC_BONUS_ENTERPRISE_PACKAGE2_VARIANT_ID=...
Fehlende Variant-IDs führen dazu, dass der Checkout-Button lautlos fehlschlägt. Bonus-Paket-Variant-IDs sind nur erforderlich, wenn
NEXT_PUBLIC_BONUS_CREDITS_ENABLED=true — siehe Lemon Squeezy Setup zum Erstellen der Einmalkauf-Produkte.4
Kunden-Portal-URL setzen
bash
NEXT_PUBLIC_LEMONSQUEEZY_CUSTOMER_PORTAL_URL=https://your-store.lemonsqueezy.com/billing
Diese URL ermöglicht es Kunden, Abonnements zu verwalten, Zahlungsmethoden zu aktualisieren und Rechnungen direkt über Lemon Squeezy's gehostetes Portal herunterzuladen.
5
Zahlungsflow testen
Führe eine echte Transaktion in Production durch:
- Preisseite aufrufen
- Auf Upgrade für einen Plan klicken
- Checkout mit einer echten Zahlungsmethode abschließen
- Überprüfen, ob der Webhook das Abonnement verarbeitet
- Bestätigen, dass der Plan des Nutzers im Dashboard aktualisiert wird
- Kündigung und Rückerstattung über das Kunden-Portal testen
Performance
1
Bundle-Größe analysieren
Führe den Bundle-Analyzer aus, um zu überprüfen, ob dein Production-Bundle Kits Performance-Ziele erfüllt:
bash
ANALYZE=true pnpm build:boilerplate
Das generiert HTML-Berichte in
apps/boilerplate/.next/analyze/, die die genaue Größe jedes Moduls zeigen.| Metrik | Ziel |
|---|---|
| Initiales JS-Load | < 200 KB (gzipped) |
| Pro-Route-Chunks | < 50 KB (gzipped) |
| Lighthouse Performance | > 90 |
2
Bildoptimierung überprüfen
Kit verhandelt automatisch das beste Bildformat pro Browser:
next.config.mjs — Image Configuration
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'images.unsplash.com',
port: '',
pathname: '/**',
},
{
protocol: 'https',
hostname: 'images.clerk.dev',
port: '',
pathname: '/**',
},
{
protocol: 'https',
hostname: 'img.clerk.com',
port: '',
pathname: '/**',
},
{
protocol: 'https',
hostname: '*.clerkstatic.com',
port: '',
pathname: '/**',
},
{
protocol: 'https',
hostname: 'lh3.googleusercontent.com',
port: '',
pathname: '/**',
},
{
protocol: 'https',
hostname: 'avatars.githubusercontent.com',
port: '',
pathname: '/**',
},
],
formats: ['image/avif', 'image/webp'],
},
Die Einstellung
formats: ['image/avif', 'image/webp'] liefert automatisch AVIF an Browser, die es unterstützen (40-50% kleiner als WebP), und fällt für andere auf WebP zurück. Keine manuelle Konvertierung nötig — Next.js übernimmt das am Edge.3
Lighthouse-Audit ausführen
Führe einen Lighthouse-Audit gegen deine Production-URL aus:
- Chrome DevTools öffnen > Lighthouse
- Performance, Accessibility, Best Practices, SEO auswählen
- Auf Analyze page load klicken
Zielwerte:
| Kategorie | Ziel |
|---|---|
| Performance | > 90 |
| Accessibility | > 90 |
| Best Practices | > 90 |
| SEO | > 90 |
SEO
1
robots.txt überprüfen
Kit generiert
robots.txt dynamisch und blockiert sensible Routen vor Suchmaschinen:src/app/robots.ts
import { MetadataRoute } from 'next'
/**
* robots.txt Generator
*
* Blocks search engines from accessing protected routes:
* - /api/* - API endpoints (internal)
* - /dashboard/* - Authenticated app pages
* - /(auth)/* - Authentication flow pages
* - /admin/* - Admin pages
* - /_next/* - Next.js internals
* - /private/* - Private resources
*
* AI Crawlers: llms.txt available at /llms.txt per llmstxt.org standard.
*/
export default function robots(): MetadataRoute.Robots {
const baseUrl = process.env.NEXT_PUBLIC_APP_URL || 'https://localhost:3000'
return {
rules: [
{
userAgent: '*',
allow: '/',
disallow: [
'/api/',
'/dashboard/',
'/(dashboard)/',
'/(auth)/',
'/admin/',
'/_next/',
'/private/',
],
},
],
sitemap: `${baseUrl}/sitemap.xml`,
host: baseUrl,
}
}
Wichtige Regeln:
- Erlaubt alle öffentlichen Seiten (
/,/login,/register,/privacy,/terms,/imprint) - Blockiert API-Routen (
/api/), Dashboard (/dashboard/), Auth-Seiten, Admin und interne Next.js-Routen
2
Sitemap überprüfen
Kit generiert
sitemap.xml dynamisch aus deinen Routen:src/app/sitemap.ts
import { MetadataRoute } from 'next'
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const baseUrl = process.env.NEXT_PUBLIC_APP_URL || 'https://localhost:3000'
// Static pages
const staticPages = [
'',
'/login',
'/register',
'/privacy',
'/terms',
'/imprint',
].map((route) => ({
url: `${baseUrl}${route}`,
lastModified: new Date().toISOString(),
changeFrequency: (route === '' ? 'daily' : 'weekly') as 'daily' | 'weekly',
priority: route === '' ? 1 : 0.8,
}))
return staticPages
}
Die Sitemap verwendet
NEXT_PUBLIC_APP_URL für alle URLs. Überprüfe, ob sie deine Production-Domain zurückgibt, indem du https://yourdomain.com/sitemap.xml aufrufst.3
llms.txt überprüfen
Kit generiert
llms.txt gemäß dem llmstxt.org-Standard und bietet KI-Crawlern (ChatGPT, Claude, Perplexity) strukturierten Zugriff auf deine Website:src/app/llms.txt/route.ts
/**
* ============================================================================
* llms.txt Route Handler
* ============================================================================
*
* Generates a Markdown file following the llmstxt.org standard.
* Provides AI crawlers (ChatGPT, Claude, Perplexity) with structured
* access to your site's public content.
*
* CUSTOMIZATION AFTER PURCHASE:
* 1. Update the description text to match your product
* 2. Add your public pages/features to the "Pages" section
* 3. Add a "## Docs" section if you have public documentation
* 4. Add a "## API" section if you have a public API
*
* @see https://llmstxt.org
* ============================================================================
*/
import { siteConfig } from '@/config/site'
export const dynamic = 'force-static'
export async function GET() {
const baseUrl = process.env.NEXT_PUBLIC_APP_URL || 'https://localhost:3000'
const lines: string[] = []
// Title (H1) — per llmstxt.org spec
lines.push(`# ${siteConfig.name}`)
lines.push('')
// Blockquote description
lines.push(`> ${siteConfig.tagline} — ${siteConfig.description}`)
lines.push('')
// Detailed description
lines.push(
`${siteConfig.name} is a SaaS application built with Next.js.`
)
lines.push('')
// Public pages
lines.push('## Pages')
lines.push('')
lines.push(`- [Login](${baseUrl}/login): Sign in to your account`)
lines.push(`- [Register](${baseUrl}/register): Create a new account`)
lines.push(
`- [Privacy Policy](${baseUrl}/privacy): Privacy policy and data handling`
)
lines.push(
`- [Terms of Service](${baseUrl}/terms): Terms and conditions`
)
lines.push(
`- [Legal Notice](${baseUrl}/imprint): Legal notice and company information`
)
lines.push('')
const content = lines.join('\n')
return new Response(content, {
headers: {
'Content-Type': 'text/plain; charset=utf-8',
'Cache-Control':
'public, s-maxage=86400, stale-while-revalidate=604800',
},
})
}
Überprüfe, ob gültiges Markdown zurückgegeben wird, indem du
https://yourdomain.com/llms.txt aufrufst. Eine .well-known/llms.txt-Weiterleitung ist ebenfalls für Crawler enthalten, die diesen Pfad prüfen.4
Benutzerdefinierte Fehlerseiten überprüfen
Kit enthält benutzerdefinierte 404- und 500-Fehlerseiten. Teste sie:
- 404 — Rufe
https://yourdomain.com/nonexistent-pageauf - 500 — Überprüfe, ob die Error-Boundary eine benutzerfreundliche Meldung rendert (teste in der Entwicklung mit einem absichtlichen Fehler)
Monitoring
1
Health-Endpunkt überprüfen
Kit enthält einen Health-Check-Endpunkt, der die Datenbankverbindung und Speichernutzung überwacht:
src/app/api/health/route.ts
import { NextResponse } from 'next/server'
import { prisma } from '@/lib/db'
export const runtime = 'nodejs'
export const dynamic = 'force-dynamic'
interface HealthCheck {
status: 'healthy' | 'unhealthy'
timestamp: string
version: string
environment: string
checks: {
database: 'healthy' | 'unhealthy' | 'unknown'
memory: {
used: number
limit: number
percentage: number
}
}
error?: string
}
export async function GET() {
const startTime = Date.now()
try {
// Check database connection
let databaseStatus: 'healthy' | 'unhealthy' | 'unknown' = 'unknown'
try {
await prisma.$queryRaw`SELECT 1`
databaseStatus = 'healthy'
} catch (dbError) {
console.error('Database health check failed:', dbError)
databaseStatus = 'unhealthy'
}
// Memory usage
const memoryUsage = process.memoryUsage()
const memoryLimit = 512 * 1024 * 1024 // 512MB default for Vercel
const memoryPercentage = (memoryUsage.heapUsed / memoryLimit) * 100
const healthCheck: HealthCheck = {
status: databaseStatus === 'healthy' ? 'healthy' : 'unhealthy',
timestamp: new Date().toISOString(),
version: process.env.NEXT_PUBLIC_APP_VERSION || '1.0.0',
environment: process.env.NODE_ENV || 'development',
checks: {
database: databaseStatus,
memory: {
used: Math.round(memoryUsage.heapUsed / 1024 / 1024),
limit: Math.round(memoryLimit / 1024 / 1024),
percentage: Math.round(memoryPercentage),
},
},
}
const responseTime = Date.now() - startTime
return NextResponse.json(
{
...healthCheck,
responseTime: `${responseTime}ms`,
},
{
status: healthCheck.status === 'healthy' ? 200 : 503,
headers: {
'Cache-Control': 'no-cache, no-store, must-revalidate',
},
}
)
} catch (error) {
console.error('Health check error:', error)
return NextResponse.json(
{
status: 'unhealthy',
timestamp: new Date().toISOString(),
version: process.env.NEXT_PUBLIC_APP_VERSION || '1.0.0',
environment: process.env.NODE_ENV || 'development',
error: error instanceof Error ? error.message : 'Unknown error',
responseTime: `${Date.now() - startTime}ms`,
},
{
status: 503,
headers: {
'Cache-Control': 'no-cache, no-store, must-revalidate',
},
}
)
}
}
Teste ihn nach dem Deployment:
bash
curl https://yourdomain.com/api/health
Erwartete Antwort:
json
{
"status": "healthy",
"timestamp": "2026-01-15T10:30:00.000Z",
"version": "1.0.0",
"environment": "production",
"checks": {
"database": "healthy",
"memory": {
"used": 85,
"limit": 512,
"percentage": 17
}
},
"responseTime": "45ms"
}
Eine
200-Antwort bedeutet, dass die Datenbank verbunden und der Speicher innerhalb der Limits ist. Eine 503-Antwort bedeutet, dass der Datenbankcheck fehlgeschlagen ist.2
Cron Jobs überprüfen
Prüfe das Vercel Dashboard unter dem Cron-Tab, um zu bestätigen, dass beide geplanten Jobs registriert sind:
| Job | Zeitplan | Nächster Durchlauf |
|---|---|---|
/api/cron/check-trials | 0 2 * * * (2 Uhr UTC) | Zeigt nächste Ausführungszeit |
/api/cron/expire-bonus-credits | 0 3 * * * (3 Uhr UTC) | Zeigt nächste Ausführungszeit |
Du kannst jeden Cron Job manuell über das Dashboard auslösen, um zu überprüfen, ob er korrekt ausgeführt wird.
3
Error Tracking einrichten (empfohlen)
Kit enthält keinen spezifischen Error-Tracking-Dienst, aber wir empfehlen, einen für Production-Sichtbarkeit hinzuzufügen:
| Dienst | Integration |
|---|---|
| Sentry | @sentry/nextjs — Automatische Fehlererfassung für Client und Server |
| Vercel Analytics | Eingebaut — Im Vercel Dashboard aktivieren |
| Vercel Speed Insights | Eingebaut — Real-User-Performance-Monitoring |
Sentry ist die umfassendste Option. Füge das
@sentry/nextjs-Paket hinzu und konfiguriere es mit deinem DSN, um unbehandelte Fehler, Performance-Traces und Session-Replays zu erfassen.Nach dem Launch
Nachdem deine Anwendung live ist, überwache diese Bereiche in den ersten 24-48 Stunden:
1
Deployment überprüfen
bash
# Health Check
curl https://yourdomain.com/api/health
# HTTPS-Weiterleitung überprüfen
curl -I http://yourdomain.com
# Sollte 301/308 Weiterleitung zu https:// zurückgeben
2
Kritische User Flows testen
Gehe den vollständigen User Journey durch:
- Registrierung — Neues Konto registrieren (E-Mail + Social Login)
- Anmeldung — Einloggen und Weiterleitung zum Dashboard überprüfen
- Zahlung — Abonnement- oder Credit-Kauf abschließen
- KI-Chat — Nachricht senden und Streaming-Antwort überprüfen. Falls Vision Chat aktiviert ist, Bild-Upload und Analyse testen. Falls Audio-Eingabe aktiviert ist, Sprachaufnahme und Transkription testen (falls KI aktiviert)
- Bildgenerierung — Bild generieren und korrekte Anzeige überprüfen (falls Image Gen aktiviert)
- Content Generator — Inhalt aus einer Vorlage generieren und Streaming-Ausgabe überprüfen (falls Content Gen aktiviert)
- Datei-Upload — Datei hochladen und persistente Speicherung überprüfen (falls Storage aktiviert)
- E-Mail — Transaktions-E-Mail auslösen und Zustellung überprüfen
3
Fehlerraten überwachen
Achte auf Spitzen bei:
- Vercel Functions — Im Functions-Tab auf 500-Fehler prüfen
- Webhook-Zustellung — Überprüfen, ob Clerk- und Lemon Squeezy-Webhooks erfolgreich sind
- Cron-Ausführung — Bestätigen, dass der erste geplante Durchlauf erfolgreich abschließt
Cron Jobs laufen um 2 Uhr und 3 Uhr UTC. Falls du am Nachmittag deployest, findet der erste Durchlauf über Nacht statt. Prüfe den Vercel Cron-Tab am nächsten Morgen, um den Erfolg zu bestätigen.
4
Uptime-Monitoring einrichten (empfohlen)
Richte einen Uptime-Monitor für deinen Health-Endpunkt ein:
GET https://yourdomain.com/api/health
Expected: 200 OK
Interval: 5 minutes
Kostenlose Optionen umfassen UptimeRobot, Better Stack oder Checkly. Konfiguriere Alerts für Ausfallzeiten, damit du sofort benachrichtigt wirst, wenn die Datenbankverbindung fehlschlägt oder die Anwendung abstürzt.
Vollständige Checkliste
Nutze diese Übersicht, um deinen Fortschritt zu verfolgen:
| Kategorie | Punkt | Status |
|---|---|---|
| Umgebung | NEXT_PUBLIC_APP_URL auf Production-Domain gesetzt | |
| Umgebung | ALLOWED_ORIGINS konfiguriert (keine Wildcards) | |
| Umgebung | Upstash Redis-Zugangsdaten gesetzt | |
| Umgebung | CRON_SECRET konfiguriert | |
| Umgebung | Alle Service-Schlüssel sind Production-Schlüssel | |
| Umgebung | KI-Provider-Schlüssel konfiguriert | |
| Umgebung | KI-Feature-Flags gesetzt (LLM_CHAT_ENABLED, RAG_CHAT_ENABLED, VISION_ENABLED, AUDIO_INPUT_ENABLED, PDF_CHAT_ENABLED, IMAGE_GEN_ENABLED, CONTENT_GEN_ENABLED) | |
| Datenbank | prisma migrate deploy ausgeführt | |
| Datenbank | Connection Pooling überprüft | |
| Sicherheit | CORS-Origins eingeschränkt | |
| Sicherheit | Rate Limiting aktiv | |
| Sicherheit | Schlüssel-Rotationsplan geplant | |
| Auth | Clerk Production-Instanz aktiv | |
| Auth | Webhook-Endpunkt konfiguriert | |
| Auth | Social-Login-Provider aktiviert | |
| Zahlungen | Lemon Squeezy im Live-Modus | |
| Zahlungen | Webhook-URL auf Production-Domain gesetzt | |
| Zahlungen | Alle Variant-IDs konfiguriert | |
| Zahlungen | Kunden-Portal-URL gesetzt | |
| Performance | Bundle-Größe unter Zielwerten | |
| Performance | Lighthouse-Score > 90 | |
| SEO | robots.txt überprüft | |
| SEO | sitemap.xml überprüft | |
| SEO | llms.txt überprüft | |
| Monitoring | Health-Endpunkt gibt 200 zurück | |
| Monitoring | Cron Jobs registriert | |
| Monitoring | Error Tracking konfiguriert | |
| Nach dem Launch | Kritische Flows getestet | |
| Nach dem Launch | Uptime-Monitoring aktiv |