Loading...
Loading...
> Complete guide to configuring all environment variables for development and production.
All variables validated at startup with Zod. Client-side variables use NEXT_PUBLIC_ prefix. Different values for dev/preview/production.
DESC: Start with the example environment file
1$cp .env.example .env.local
DESC: Create a secure NEXTAUTH_SECRET for encrypting authentication cookies
1$openssl rand -base64 3223$# Expected output:4$# dGhpc2lzYXJhbmRvbWJhc2U2NGVuY29kZWRzdHJpbmc=5$#6$# Copy this entire output and paste it as NEXTAUTH_SECRET in your .env.local7$# This encrypts user session cookies - keep it secret and never commit it to git
DESC: Set your actual PostgreSQL connection string from your database provider
1$# Replace with YOUR actual connection string from your database provider23$# Supabase (pooler recommended for serverless):4$DATABASE_URL="postgresql://postgres.abcdefghij:[YOUR_PASSWORD]@aws-0-us-west-1.pooler.supabase.com:6543/postgres?pgbouncer=true"56$# Neon (pooler with SSL):7$DATABASE_URL="postgresql://user:password@ep-cool-name-123456-pooler.us-east-2.aws.neon.tech/dbname?sslmode=require"89$# Railway (direct connection):10$DATABASE_URL="postgresql://postgres:password@containers-us-west-123.railway.app:5432/railway"
DESC: Configure Stripe, email, and OAuth providers
These must be set for the application to function
1$# .env.local23$# Database - Replace with YOUR actual PostgreSQL connection string4$# Get this from your database provider's dashboard (Supabase, Neon, or Railway)5$DATABASE_URL="postgresql://postgres.abcdefghij:[YOUR_PASSWORD]@aws-0-us-west-1.pooler.supabase.com:6543/postgres?pgbouncer=true"67$# NextAuth - Authentication8$NEXTAUTH_URL="http://localhost:3000" # Your app URL (use your production domain for prod)9$NEXTAUTH_SECRET="your-32-character-secret-here" # Generate with: openssl rand -base64 321011$# App URL (used for links in emails, redirects, etc.)12$NEXT_PUBLIC_APP_URL="http://localhost:3000"
Configure OAuth providers
1$# Google OAuth (optional - enables Google login)2$GOOGLE_CLIENT_ID="your-client-id.apps.googleusercontent.com"3$GOOGLE_CLIENT_SECRET="your-client-secret"45$# Setup:6$# 1. Go to https://console.cloud.google.com/apis/credentials7$# 2. Create OAuth 2.0 Client ID8$# 3. Add redirect URI:9$# - Dev: http://localhost:3000/api/auth/callback/google10$# - Prod: https://your-domain.com/api/auth/callback/google
Configure email sending
1$# Resend API Key2$RESEND_API_KEY="re_..."34$# From address (must be from verified domain)5$EMAIL_FROM="noreply@your-domain.com"67$# Setup:8$# 1. Sign up at https://resend.com9$# 2. Verify your domain10$# 3. Create API key11$# 4. Add DNS records for domain verification
Configure payment processing with Stripe
1$# Stripe API Keys (get from https://dashboard.stripe.com/test/apikeys)2$STRIPE_SECRET_KEY="sk_test_..." # Server-side only (never expose to browser)3$NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY="pk_test_..." # Client-side safe (can be in browser)45$# Stripe Webhook Secret (get from stripe listen command or Stripe Dashboard)6$STRIPE_WEBHOOK_SECRET="whsec_..."78$# Product Lookup Key (NOT a price ID)9$# Create in Stripe Dashboard: Products → Your Product → Pricing → Lookup key field10$# Lookup keys let you change prices in Stripe without updating code11$NEXT_PUBLIC_STRIPE_PRICE_FABRK="fabrk_purchase" # This is a lookup key, not price_12345678901213$# Optional: Promotion code for early adopters ($100 off)14$STRIPE_COUPON_EARLY_ADOPTER="promo_1SVGK4P7kSSEYWlXBq1LtaNM" # Promotion Code ID from Stripe Dashboard1516$# Development vs Production:17$# Development (test mode):18$# - sk_test_... and pk_test_...19$# - Test with card 4242 4242 4242 424220$#21$# Production (live mode):22$# - sk_live_... and pk_live_...23$# - Real credit cards, real money2425$# Test webhooks locally:26$# Install Stripe CLI: brew install stripe/stripe-cli/stripe27$# Then run: stripe listen --forward-to localhost:3000/api/webhooks/stripe
Track user behavior and metrics
1$# PostHog Analytics2$NEXT_PUBLIC_POSTHOG_KEY="phc_..."3$NEXT_PUBLIC_POSTHOG_HOST="https://app.posthog.com"45$# Setup:6$# 1. Sign up at https://posthog.com7$# 2. Create project8$# 3. Copy API key from Project Settings910$# Google Analytics (alternative)11$NEXT_PUBLIC_GA_MEASUREMENT_ID="G-..."
All variables validated at startup in src/lib/env.ts
1// src/lib/env.ts2import { z } from "zod";34const serverSchema = z.object({5 DATABASE_URL: z.string().url(),6 NEXTAUTH_SECRET: z.string().min(32),7 STRIPE_SECRET_KEY: z.string().startsWith("sk_").optional(),8});910const clientSchema = z.object({11 NEXT_PUBLIC_APP_URL: z.string().url(),12 NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY: z.string().startsWith("pk_").optional(),13});1415// Validates at startup - fails loudly if invalid16/* eslint-disable no-process-env -- This is showing users HOW to set up env.ts */17export const env = {18 server: serverSchema.parse(process.env),19 client: clientSchema.parse({20 NEXT_PUBLIC_APP_URL: process.env.NEXT_PUBLIC_APP_URL,21 NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY:22 process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY,23 }),24};25/* eslint-enable no-process-env */2627// Usage in code:28import { env } from "@/lib/env";2930const dbUrl = env.server.DATABASE_URL; // Type-safe!31const appUrl = env.client.NEXT_PUBLIC_APP_URL;
Use different values for different environments
1$# Development (.env.local)2$NODE_ENV="development"3$NEXTAUTH_URL="http://localhost:3000"4$STRIPE_SECRET_KEY="sk_test_..."5$DATABASE_URL="postgresql://localhost:5432/fabrk_dev"67$# Preview (Vercel Preview Environment)8$NODE_ENV="production"9$NEXTAUTH_URL="https://preview.your-domain.vercel.app"10$STRIPE_SECRET_KEY="sk_test_..." # Still use test keys11$DATABASE_URL="postgresql://...preview-db..."1213$# Production (Vercel Production Environment)14$NODE_ENV="production"15$NEXTAUTH_URL="https://your-domain.com"16$STRIPE_SECRET_KEY="sk_live_..." # Live keys!17$DATABASE_URL="postgresql://...production-db..."
Full development environment setup
1$# .env.local - Complete Development Setup23$# Core4$NODE_ENV="development"5$DATABASE_URL="postgresql://postgres:password@localhost:5432/fabrk"6$NEXT_PUBLIC_APP_URL="http://localhost:3000"78$# Auth9$NEXTAUTH_URL="http://localhost:3000"10$NEXTAUTH_SECRET="your-32-character-development-secret"11$GOOGLE_CLIENT_ID="your-google-client-id"12$GOOGLE_CLIENT_SECRET="your-google-client-secret"1314$# Email15$RESEND_API_KEY="re_test_..."16$EMAIL_FROM="dev@your-domain.com"1718$# Payments19$STRIPE_SECRET_KEY="sk_test_..."20$STRIPE_WEBHOOK_SECRET="whsec_test_..."21$NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY="pk_test_..."22$NEXT_PUBLIC_STRIPE_PRICE_STARTER="price_..."23$NEXT_PUBLIC_STRIPE_PRICE_PROFESSIONAL="price_..."2425$# Analytics (optional)26$NEXT_PUBLIC_POSTHOG_KEY="phc_..."27$NEXT_PUBLIC_POSTHOG_HOST="https://app.posthog.com"