# Environment Variables Guide **For:** ThrillWiki Next.js 15 Migration **Last Updated:** November 9, 2025 --- ## 🎯 Overview This guide covers all environment variables required for the ThrillWiki migration from Reactβ†’Next.js 15 and Supabaseβ†’Django. ## πŸ”‘ Critical Rules 1. **NO HARDCODED VALUES** - All configuration must use environment variables 2. **Client vs Server** - Understand NEXT_PUBLIC_ prefix usage 3. **Never commit secrets** - .env.local in .gitignore 4. **.env.example** - Document all required vars (without values) 5. **Validate on startup** - Fail fast if required vars missing --- ## πŸ“‹ Required Environment Variables ### Next.js Client-Side (Public) These variables are exposed to the browser. Use `NEXT_PUBLIC_` prefix. ```bash # Django API (required) NEXT_PUBLIC_DJANGO_API_URL=https://api.thrillwiki.com # CloudFlare Images (required for uploads) NEXT_PUBLIC_CLOUDFLARE_ACCOUNT_ID=your_account_id_here ``` ### Next.js Server-Side (Private) These variables are ONLY available server-side. NO `NEXT_PUBLIC_` prefix. ```bash # CloudFlare API Token (for image uploads from server) CLOUDFLARE_API_TOKEN=your_secret_token_here # Django Admin Credentials (if needed for server-side operations) DJANGO_ADMIN_KEY=your_admin_key_here ``` ### Legacy Supabase (Temporary - Remove in Phase 14) Keep these ONLY during migration phases 1-13: ```bash # Supabase (to be removed) NEXT_PUBLIC_SUPABASE_URL=https://xxx.supabase.co NEXT_PUBLIC_SUPABASE_ANON_KEY=your_anon_key_here ``` --- ## πŸ“ File Structure ``` project-root/ β”œβ”€β”€ .env.local # Local development (git-ignored) β”œβ”€β”€ .env.example # Template (git-committed) β”œβ”€β”€ .env.production # Production (if needed, git-ignored) └── .env.test # Testing (git-ignored) ``` ### .env.local (Development) ```bash # ================================ # Next.js Environment Variables # ================================ # Django REST API NEXT_PUBLIC_DJANGO_API_URL=http://localhost:8000/api/v1 # CloudFlare Images NEXT_PUBLIC_CLOUDFLARE_ACCOUNT_ID=your_dev_account_id CLOUDFLARE_API_TOKEN=your_dev_token # Supabase (temporary - remove after Phase 14) NEXT_PUBLIC_SUPABASE_URL=https://xxx.supabase.co NEXT_PUBLIC_SUPABASE_ANON_KEY=your_anon_key # Development flags NODE_ENV=development ``` ### .env.example (Template) ```bash # ================================ # Next.js Environment Variables # Copy to .env.local and fill in values # ================================ # Django REST API (required) NEXT_PUBLIC_DJANGO_API_URL= # CloudFlare Images (required) NEXT_PUBLIC_CLOUDFLARE_ACCOUNT_ID= CLOUDFLARE_API_TOKEN= # Supabase (temporary - will be removed) NEXT_PUBLIC_SUPABASE_URL= NEXT_PUBLIC_SUPABASE_ANON_KEY= ``` ### .env.production (Production) ```bash # Django REST API NEXT_PUBLIC_DJANGO_API_URL=https://api.thrillwiki.com # CloudFlare Images NEXT_PUBLIC_CLOUDFLARE_ACCOUNT_ID=production_account_id CLOUDFLARE_API_TOKEN=production_secret_token # Production settings NODE_ENV=production ``` --- ## πŸ” Security Best Practices ### 1. Client vs Server Variables ```typescript // ❌ WRONG - Exposes secret to browser const apiKey = process.env.CLOUDFLARE_API_TOKEN; // βœ… CORRECT - Only available server-side // In Server Component or API Route const apiKey = process.env.CLOUDFLARE_API_TOKEN; // βœ… CORRECT - Public variable in client const apiUrl = process.env.NEXT_PUBLIC_DJANGO_API_URL; ``` ### 2. Never Log Secrets ```typescript // ❌ WRONG console.log('API Token:', process.env.CLOUDFLARE_API_TOKEN); // βœ… CORRECT console.log('API URL:', process.env.NEXT_PUBLIC_DJANGO_API_URL); ``` ### 3. Validate Environment Variables ```typescript // lib/env.ts import { z } from 'zod'; const envSchema = z.object({ NEXT_PUBLIC_DJANGO_API_URL: z.string().url(), NEXT_PUBLIC_CLOUDFLARE_ACCOUNT_ID: z.string().min(1), CLOUDFLARE_API_TOKEN: z.string().min(1).optional(), // Server-only }); // Validate on app start export const env = envSchema.parse({ NEXT_PUBLIC_DJANGO_API_URL: process.env.NEXT_PUBLIC_DJANGO_API_URL, NEXT_PUBLIC_CLOUDFLARE_ACCOUNT_ID: process.env.NEXT_PUBLIC_CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_API_TOKEN: process.env.CLOUDFLARE_API_TOKEN, }); // Usage import { env } from '@/lib/env'; const apiUrl = env.NEXT_PUBLIC_DJANGO_API_URL; ``` --- ## πŸš€ Deployment Environments ### Vercel Set environment variables in Vercel dashboard: 1. Go to Project Settings β†’ Environment Variables 2. Add each variable: - `NEXT_PUBLIC_DJANGO_API_URL` = `https://api.thrillwiki.com` - `NEXT_PUBLIC_CLOUDFLARE_ACCOUNT_ID` = `your_account` - `CLOUDFLARE_API_TOKEN` = `your_token` (mark as secret) ### Docker Pass via docker-compose.yml: ```yaml services: nextjs: environment: - NEXT_PUBLIC_DJANGO_API_URL=https://api.thrillwiki.com - NEXT_PUBLIC_CLOUDFLARE_ACCOUNT_ID=${CLOUDFLARE_ACCOUNT_ID} - CLOUDFLARE_API_TOKEN=${CLOUDFLARE_API_TOKEN} ``` --- ## πŸ§ͺ Testing ### Check Variables Are Loaded ```typescript // Test in dev console (browser) console.log('API URL:', process.env.NEXT_PUBLIC_DJANGO_API_URL); // Should show the URL console.log('Secret Token:', process.env.CLOUDFLARE_API_TOKEN); // Should show 'undefined' (not exposed to client) ``` ### Verify Build-Time Variables ```bash # Build with verbose output bun run build # Check if variables are embedded grep -r "NEXT_PUBLIC_DJANGO_API_URL" .next/ ``` --- ## πŸ“Š Migration Phases ### Phase 1-13: Dual Variables ```bash # Keep both during migration NEXT_PUBLIC_DJANGO_API_URL=... NEXT_PUBLIC_SUPABASE_URL=... ``` ### Phase 14: Remove Supabase ```bash # Remove these completely # NEXT_PUBLIC_SUPABASE_URL=... # NEXT_PUBLIC_SUPABASE_ANON_KEY=... # Keep only Django NEXT_PUBLIC_DJANGO_API_URL=... ``` --- ## ⚠️ Common Issues ### Issue: Variable is undefined in browser **Cause:** Missing `NEXT_PUBLIC_` prefix **Fix:** Rename variable: ```bash # Wrong DJANGO_API_URL=https://api.thrillwiki.com # Right NEXT_PUBLIC_DJANGO_API_URL=https://api.thrillwiki.com ``` ### Issue: Variable not updating after change **Cause:** Next.js caches env vars at build time **Fix:** Restart dev server: ```bash # Stop server (Ctrl+C) bun run dev ``` ### Issue: Hardcoded URL slipped through **Find:** Search codebase: ```bash grep -r "https://api.thrillwiki.com" src/ --exclude-dir=node_modules ``` **Fix:** Replace with env var: ```typescript // Before const API_URL = "https://api.thrillwiki.com"; // After const API_URL = process.env.NEXT_PUBLIC_DJANGO_API_URL; ``` --- ## πŸ”— Related Documentation - [Phase 1: Foundation](./PHASE_01_FOUNDATION.md) - Initial setup - [Phase 13: Next.js Optimization](./PHASE_13_NEXTJS_OPTIMIZATION.md) - Security - [Bun Guide](./BUN_GUIDE.md) - Package manager - Next.js Docs: https://nextjs.org/docs/app/building-your-application/configuring/environment-variables --- **Document Version:** 1.0 **Last Updated:** November 9, 2025