Docs
Environment Variables
Environment Variables
Complete reference for every required and optional environment variable.
Environment variables are validated at build time using @t3-oss/env-nextjs. If you add a new variable, you must update both your .env file and the env.mjs schema — otherwise the build will fail.
Core App
| Variable | Required | Description |
|---|---|---|
NEXT_PUBLIC_APP_URL | Yes | The public base URL. Used in email links and QStash callbacks. E.g. http://localhost:3000 |
APP_NAME | Yes | Shown in emails and the UI. E.g. My SaaS App |
Authentication
| Variable | Required | Description |
|---|---|---|
BETTER_AUTH_SECRET | Yes | Random secret for token encryption. Generate with openssl rand -base64 32 |
GOOGLE_CLIENT_ID | Yes | Google OAuth client ID from Google Cloud Console |
GOOGLE_CLIENT_SECRET | Yes | Google OAuth client secret |
Database
| Variable | Required | Description |
|---|---|---|
DATABASE_URL | Yes | PostgreSQL connection string. E.g. postgres://user:pass@host/db |
AI
| Variable | Required | Description |
|---|---|---|
OPENAI_API_KEY | Yes | Used by the orchestrator (gpt-4o-mini), agents (gpt-4o), and image generation |
ANTHROPIC_API_KEY | Optional | Required only if using Claude models via resolveModel() in lib/ai/models.ts |
TAVILY_API_KEY | Yes | Used by the web_search and web_extract tools |
| Variable | Required | Description |
|---|---|---|
RESEND_API_KEY | Yes | API key from Resend for all transactional email |
EMAIL_FROM | Yes | Sender address. E.g. Ship AI SaaS <noreply@yourdomain.com> |
Storage
| Variable | Required | Description |
|---|---|---|
SUPABASE_URL | Yes | Your Supabase project URL |
SUPABASE_SERVICE_ROLE_KEY | Yes | Server-side service role key for storage uploads. Never expose this to the browser. |
Payments
| Variable | Required | Description |
|---|---|---|
STRIPE_API_KEY | Yes | Stripe secret key (starts with sk_) |
STRIPE_WEBHOOK_SECRET | Yes | Signing secret from Stripe dashboard or stripe listen |
NEXT_PUBLIC_STRIPE_PRO_MONTHLY_PLAN_ID | Optional | Stripe Price ID for the Pro monthly plan |
NEXT_PUBLIC_STRIPE_PRO_YEARLY_PLAN_ID | Optional | Stripe Price ID for the Pro yearly plan |
NEXT_PUBLIC_STRIPE_BUSINESS_MONTHLY_PLAN_ID | Optional | Stripe Price ID for the Business monthly plan |
NEXT_PUBLIC_STRIPE_BUSINESS_YEARLY_PLAN_ID | Optional | Stripe Price ID for the Business yearly plan |
Background Jobs (QStash)
| Variable | Required | Description |
|---|---|---|
QSTASH_TOKEN | Yes | Upstash QStash token for publishing messages |
QSTASH_URL | Yes | QStash publish URL from Upstash console |
QSTASH_CURRENT_SIGNING_KEY | Yes | Used by verifySignatureAppRouter to authenticate incoming step requests |
QSTASH_NEXT_SIGNING_KEY | Yes | Rotated signing key for zero-downtime key rotation |
WORKFLOW_TOKEN_SECRET | Yes | Signs JWT tokens for workflow plan and step approvals |
QSTASH_BASE_URL must be set to your production domain in production (e.g. https://yourdomain.com). QStash will POST step invocations to ${QSTASH_BASE_URL}/api/workflows/step.