Environment Variables Reference
A comprehensive guide to understanding, configuring, and managing all environment variables in NEXTDEVKIT across different deployment platforms.
This guide provides a complete reference for all environment variables used in NEXTDEVKIT. You'll learn what each variable does, when you need it, and how to obtain the required values.
Understanding Environment Variables
Environment variables are configuration values that change based on where your application runs (development, staging, production). They keep sensitive information like API keys and database credentials out of your code.
Security Principles
Security First
- Never commit
.env
files to version control - Use different values for development and production
- Rotate secrets regularly (every 90 days recommended)
- Use environment-specific OAuth callbacks
File Organization
your-project/
├── .env.local # Local development (git-ignored)
├── .env.production # Production values (git-ignored)
└── .env.example # Template with dummy values (committed)
Progressive Configuration Journey
Let's configure your environment variables step by step, starting with the absolute essentials and progressively adding features.
Level 1: Minimal Setup (5 minutes)
Goal: Get NEXTDEVKIT running locally with core features.
What You'll Need:
- Authentication secret
- Database connection
- Public URL
Generate Authentication Secret
openssl rand -base64 32
This generates a random 32-character secret key for encrypting sessions.
Add to .env.local
:
# Core Authentication
BETTER_AUTH_SECRET=your-generated-secret-here
BETTER_AUTH_URL=http://localhost:3000
NEXT_PUBLIC_APP_URL=http://localhost:3000
Why these are required:
BETTER_AUTH_SECRET
: Encrypts user sessions and tokensBETTER_AUTH_URL
: Base URL for authentication callbacksNEXT_PUBLIC_APP_URL
: Public-facing application URL (exposed to browser)
Variables prefixed with NEXT_PUBLIC_
are exposed to the browser. Never put secrets in them!
Configure Database Connection
For PostgreSQL (Recommended for production):
# Database
DATABASE_URL=postgresql://username:password@host:5432/database?sslmode=require
Getting your database URL:
-
Local PostgreSQL:
postgresql://postgres:password@localhost:5432/nextdevkit
-
Neon (Free tier available):
- Visit neon.tech
- Create project → Copy connection string
- Use the pooled connection string
-
Supabase:
- Visit supabase.com
- Project Settings → Database → Connection String
- Use "Connection Pooling" string
Why you need this: Database stores user accounts, subscriptions, and application data.
See detailed database setup: Database Configuration
Run Database Migrations
# Generate migration files
pnpm db:generate
# Apply migrations to your database
pnpm db:migrate
What this does: Creates necessary tables for authentication, users, subscriptions, etc.
🎉 You can now run: pnpm dev
Your app is running with authentication and database! But you'll need more configuration to enable all features.
Level 2: Email Integration (10 minutes)
Goal: Enable password resets, email verification, and newsletter.
What You'll Need:
- Email service provider API key
Choose Email Provider
NEXTDEVKIT supports Resend by default (recommended for ease of use).
Why Resend:
- Free tier: 3,000 emails/month
- No credit card required
- Simple setup
- Good deliverability
Alternatives:
- SendGrid
- AWS SES
- Postmark
Get Resend API Key
- Visit resend.com and sign up
- Go to API Keys → Create API Key
- Name it (e.g., "NEXTDEVKIT Development")
- Copy the key (starts with
re_
)
Create Audience for Newsletter:
- Go to Audiences → Create Audience
- Name it (e.g., "NEXTDEVKIT Newsletter")
- Copy the Audience ID
Add Email Configuration
# Email Service
RESEND_API_KEY=re_your_api_key_here
RESEND_AUDIENCE_ID=your-audience-id-here
What these enable:
- Password reset emails
- Email verification
- Newsletter subscriptions
- Contact form submissions
📧 Features now available:
- Users can reset passwords
- Newsletter signup works
- Contact forms send emails
See email templates: Email Configuration
Level 3: Social Authentication (15 minutes)
Goal: Enable "Sign in with Google/GitHub" buttons.
Why add this:
- Improves conversion (easier signup)
- Reduces password fatigue
- Better user experience
Configure GitHub OAuth
1. Create GitHub OAuth App:
- Visit GitHub Developer Settings
- Click OAuth Apps → New OAuth App
2. Fill in details:
Application name: NEXTDEVKIT (Development)
Homepage URL: http://localhost:3000
Authorization callback URL: http://localhost:3000/api/auth/callback/github
3. Get credentials:
- Click Generate a new client secret
- Copy Client ID and Client Secret
4. Add to environment:
# GitHub OAuth
GITHUB_CLIENT_ID=Ov23xxxxxxxxxxxxx
GITHUB_CLIENT_SECRET=your-github-client-secret
Create separate OAuth apps for development, staging, and production with different callback URLs!
Configure Google OAuth
1. Create Google Cloud Project:
- Visit Google Cloud Console
- Create new project or select existing
2. Enable Google+ API:
- Go to APIs & Services → Library
- Search "Google+ API" → Enable
3. Create OAuth Credentials:
- Go to APIs & Services → Credentials
- Click Create Credentials → OAuth client ID
- Application type: Web application
4. Configure OAuth consent screen:
- User Type: External
- Add required information (app name, support email)
5. Add authorized origins and redirect URIs:
Authorized JavaScript origins:
http://localhost:3000
Authorized redirect URIs:
http://localhost:3000/api/auth/callback/google
6. Get credentials:
# Google OAuth
GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=GOCSPX-your-client-secret
🔐 Features now available:
- Social login buttons appear
- One-click sign up with Google/GitHub
- Automatic profile picture from OAuth provider
See authentication setup: Authentication
Level 4: Payment Integration (20 minutes)
Goal: Enable subscription billing and one-time purchases.
What You'll Need:
- Stripe account (or Creem)
- Product and price IDs
Choose Payment Provider
Stripe (Recommended):
- Industry standard
- Excellent documentation
- Supports most countries
- Advanced features (trials, metering, etc.)
Creem:
- Merchant of Record (handles tax compliance)
- Good for global sales
- Simpler tax handling
NEXTDEVKIT supports both providers. Choose based on your needs.
Configure Stripe
1. Create Stripe Account:
- Visit stripe.com
- Sign up and verify your account
2. Get API Keys:
- Go to Developers → API keys
- Copy Secret key (starts with
sk_test_
for testing)
3. Create Products:
Create three products in Stripe Dashboard:
Product 1: Pro Monthly
- Name: "Pro Plan - Monthly"
- Billing: Recurring
- Interval: Monthly
- Price: $9.99/month
- Trial: 7 days (optional)
Product 2: Pro Yearly
- Name: "Pro Plan - Yearly"
- Billing: Recurring
- Interval: Yearly
- Price: $99/year
- Trial: 30 days (optional)
Product 3: Lifetime
- Name: "Lifetime Access"
- Billing: One-time
- Price: $399
4. Copy Price IDs:
Each product has a Price ID (starts with price_
). Copy these for your .env.local
:
# Stripe Configuration
STRIPE_SECRET_KEY=sk_test_your_stripe_secret_key
# Subscription Price IDs
NEXT_PUBLIC_PRICE_ID_PRO_MONTHLY=price_xxxxxxxxxxxxx
NEXT_PUBLIC_PRICE_ID_PRO_YEARLY=price_xxxxxxxxxxxxx
NEXT_PUBLIC_PRICE_ID_LIFETIME=price_xxxxxxxxxxxxx
Configure Webhooks
Webhooks notify your app when payments succeed or fail.
1. Install Stripe CLI (for local testing):
# macOS
brew install stripe/stripe-cli/stripe
# Windows
scoop bucket add stripe https://github.com/stripe/scoop-stripe-cli.git
scoop install stripe
# Linux
# Download from https://github.com/stripe/stripe-cli/releases/latest
2. Login to Stripe:
stripe login
3. Forward webhooks to local server:
stripe listen --forward-to localhost:3000/api/webhooks/stripe
This command outputs a webhook secret (starts with whsec_
):
STRIPE_WEBHOOK_SECRET=whsec_your_local_webhook_secret
4. For Production:
- Go to Developers → Webhooks in Stripe Dashboard
- Click Add endpoint
- URL:
https://yourdomain.com/api/webhooks/stripe
- Select events:
checkout.session.completed
customer.subscription.created
customer.subscription.updated
customer.subscription.deleted
invoice.payment_succeeded
invoice.payment_failed
Important
Use different webhook secrets for development and production environments!
Alternative: Configure Creem
If you prefer Creem as your payment provider:
1. Sign up at creem.io
2. Get API credentials:
# Creem Configuration
CREEM_API_KEY=creem_test_your_api_key
CREEM_WEBHOOK_SECRET=whsec_your_webhook_secret
# Product IDs (create products in Creem dashboard)
NEXT_PUBLIC_PRICE_ID_PRO_MONTHLY=prod_your_monthly_id
NEXT_PUBLIC_PRICE_ID_PRO_YEARLY=prod_your_yearly_id
NEXT_PUBLIC_PRICE_ID_LIFETIME=prod_your_lifetime_id
3. Update payment provider in config:
payment: {
provider: "creem", // Change from "stripe"
// ... rest of config
}
💳 Features now available:
- Pricing page works
- Users can subscribe
- Payment webhooks update user subscriptions
- Billing portal for managing subscriptions
See payment setup: Payment Configuration
Level 5: File Storage (15 minutes)
Goal: Enable file uploads (user avatars, document uploads).
What You'll Need:
- S3-compatible storage provider (AWS S3, Cloudflare R2, etc.)
Choose Storage Provider
Cloudflare R2 (Recommended for most users):
- Free tier: 10GB storage, 1M reads/month
- No egress fees
- S3-compatible API
- Fast global CDN
AWS S3:
- Industry standard
- Pay-as-you-go pricing
- Extensive features
- Global availability
Alternatives:
- DigitalOcean Spaces
- Backblaze B2
- Wasabi
Configure Cloudflare R2
1. Create R2 Bucket:
- Go to Cloudflare Dashboard → R2
- Create bucket (e.g., "nextdevkit-avatars")
2. Get API Tokens:
- Go to R2 → Manage R2 API Tokens
- Create API Token with read/write permissions
- Copy Access Key ID and Secret Access Key
3. Get Account ID:
- Found in your R2 dashboard URL or settings
4. Add to environment:
# Storage Configuration
NEXT_PUBLIC_AVATARS_BUCKET_NAME=nextdevkit-avatars
# Cloudflare R2
STORAGE_REGION=auto
STORAGE_ACCESS_KEY_ID=your-access-key-id
STORAGE_SECRET_ACCESS_KEY=your-secret-access-key
STORAGE_ENDPOINT=https://your-account-id.r2.cloudflarestorage.com
For Cloudflare Workers deployment, add STORAGE_ACCOUNT_ID
as well.
Alternative: Configure AWS S3
1. Create S3 Bucket:
- Go to AWS Console
- Create bucket in your preferred region
2. Create IAM User:
- Go to IAM → Users → Create user
- Attach policy:
AmazonS3FullAccess
(or create custom policy) - Create access key → Copy credentials
3. Add to environment:
# Storage Configuration
NEXT_PUBLIC_AVATARS_BUCKET_NAME=nextdevkit-avatars
# AWS S3
STORAGE_REGION=us-east-1
STORAGE_ACCESS_KEY_ID=AKIA...
STORAGE_SECRET_ACCESS_KEY=your-secret-key
# STORAGE_ENDPOINT not needed for AWS S3
📁 Features now available:
- Users can upload avatars
- File upload components work
- Secure signed URLs for private files
See storage setup: Storage Configuration
Level 6: Analytics (10 minutes)
Goal: Track user behavior and site performance.
What You'll Need:
- Analytics service account (Google Analytics, Umami, or Plausible)
Option 1: Google Analytics
Free, feature-rich, widely used
1. Create GA4 Property:
- Visit Google Analytics
- Create account → Create property (GA4)
2. Get Measurement ID:
- Go to Admin → Data Streams → Select your stream
- Copy Measurement ID (starts with
G-
)
3. Add to environment:
# Google Analytics
NEXT_PUBLIC_GOOGLE_ANALYTICS_ID=G-XXXXXXXXXX
Automatically enabled when this variable is set.
Option 2: Umami Analytics
Privacy-friendly, self-hostable, GDPR compliant
1. Choose hosting:
- Self-host: umami.is/docs
- Cloud: cloud.umami.is
2. Create website:
- Add new website in dashboard
- Copy Website ID and Script URL
3. Add to environment:
# Umami Analytics
NEXT_PUBLIC_UMAMI_WEBSITE_ID=your-website-id
NEXT_PUBLIC_UMAMI_SCRIPT_URL=https://your-umami-instance.com/script.js
Option 3: Plausible Analytics
Privacy-focused, simple, no cookies
1. Sign up:
- Visit plausible.io
- Add your domain
2. Get configuration:
# Plausible Analytics
NEXT_PUBLIC_PLAUSIBLE_DOMAIN=yourdomain.com
NEXT_PUBLIC_PLAUSIBLE_SCRIPT_URL=https://plausible.io/js/script.js
📊 Features now available:
- Page view tracking
- Event tracking
- User journey analysis
- Performance monitoring
See analytics setup: Analytics Configuration
Level 7: AI Integration (5 minutes)
Goal: Enable AI features (chatbots, content generation).
What You'll Need:
- Google AI API key
Get Google AI API Key
1. Visit Google AI Studio:
- Go to aistudio.google.com
- Sign in with Google account
2. Create API Key:
- Click Get API key
- Create in new or existing project
- Copy the key (starts with
AIza
)
3. Add to environment:
# AI Configuration
GOOGLE_GENERATIVE_AI_API_KEY=AIzaXXXXXXXXXXXXXXXXXXXXXXXX
Google AI has a generous free tier. Monitor usage in the AI Studio.
🤖 Features now available:
- AI chat interface
- Content generation
- Smart suggestions
See AI setup: AI Integration
Level 8: Credits System (10 minutes)
Goal: Enable usage-based billing with credits.
What You'll Need:
- Stripe product IDs for credit packages
Create Credit Products in Stripe
Create four credit packages in Stripe Dashboard:
1. Lite Package:
- Name: "Credits - Lite"
- Price: $9 one-time
- Credits: 100
2. Standard Package:
- Name: "Credits - Standard"
- Price: $29 one-time
- Credits: 300
3. Pro Package:
- Name: "Credits - Pro"
- Price: $79 one-time
- Credits: 1,000
4. Max Package:
- Name: "Credits - Max"
- Price: $199 one-time
- Credits: 3,000
Add Credit Price IDs
# Credits System
CREDIT_LITE_PRICE_ID=price_xxxxxxxxxxxxx
CREDIT_STANDARD_PRICE_ID=price_xxxxxxxxxxxxx
CREDIT_PRO_PRICE_ID=price_xxxxxxxxxxxxx
CREDIT_MAX_PRICE_ID=price_xxxxxxxxxxxxx
🎯 Features now available:
- Usage-based billing
- Credit purchase flow
- Credit balance tracking
See credits setup: Credits System
Level 9: Scheduled Tasks (5 minutes)
Goal: Secure cron job endpoints.
What You'll Need:
- Random secret for cron authentication
Generate Cron Secret
openssl rand -base64 16
Add to environment:
# Cron Job Security
CRON_SECRET=your-generated-secret
How it's used: Cron endpoints check this secret to prevent unauthorized access:
// Example: /api/cron/cleanup
if (request.headers.get('Authorization') !== `Bearer ${process.env.CRON_SECRET}`) {
return new Response('Unauthorized', { status: 401 });
}
⏰ Features secured:
- Data cleanup jobs
- Report generation
- Scheduled notifications
Platform-Specific Configurations
Different deployment platforms require slightly different environment variable setups.
Next.js / Vercel Deployment
Best for: Traditional hosting, Vercel deployments, Docker containers
All variables from Levels 1-9 work as-is. No special configuration needed.
Deploy to Vercel:
- Import project from Git
- Add environment variables in Settings → Environment Variables
- Deploy
See detailed guide: Next.js Deployment
Cloudflare Workers Deployment
Best for: Edge computing, global distribution, cost optimization
Key Differences:
-
Database: Use Cloudflare D1 instead of PostgreSQL
# Remove DATABASE_URL # D1 binding configured in wrangler.toml
-
Storage: Add Account ID for R2
STORAGE_ACCOUNT_ID=your-cloudflare-account-id
-
Additional bindings configured in
wrangler.toml
:[[d1_databases]] binding = "DB" database_name = "nextdevkit" database_id = "your-database-id"
See detailed guide: Cloudflare Workers Deployment
AWS SST Deployment
Best for: Enterprise infrastructure, AWS integration, compliance requirements
Key Differences:
-
AWS Credentials:
AWS_ACCESS_KEY_ID=AKIA... AWS_SECRET_ACCESS_KEY=your-secret-key
-
RDS Database: Use AWS RDS PostgreSQL
DATABASE_URL=postgresql://username:password@your-rds-instance.region.rds.amazonaws.com:5432/database
-
S3 Storage: No endpoint needed
STORAGE_REGION=us-east-1 # STORAGE_ENDPOINT not used
-
Infrastructure as Code: Environment variables can be defined in
sst.config.ts
See detailed guide: SST AWS Deployment
Environment Variables Quick Reference
Required Variables (Minimum Setup)
Variable | Purpose | Example Value |
---|---|---|
BETTER_AUTH_SECRET | Session encryption | openssl rand -base64 32 |
BETTER_AUTH_URL | Auth callback base | http://localhost:3000 |
NEXT_PUBLIC_APP_URL | Public app URL | http://localhost:3000 |
DATABASE_URL | Database connection | postgresql://... |
Authentication
Variable | Required | Purpose | Get From |
---|---|---|---|
GITHUB_CLIENT_ID | For GitHub login | OAuth app ID | GitHub Settings |
GITHUB_CLIENT_SECRET | For GitHub login | OAuth secret | GitHub OAuth App |
GOOGLE_CLIENT_ID | For Google login | OAuth app ID | Google Cloud Console |
GOOGLE_CLIENT_SECRET | For Google login | OAuth secret | Google Cloud Console |
Variable | Required | Purpose | Get From |
---|---|---|---|
RESEND_API_KEY | For email sending | API authentication | resend.com |
RESEND_AUDIENCE_ID | For newsletter | Mailing list ID | Resend Dashboard |
Payment
Variable | Required | Purpose | Get From |
---|---|---|---|
STRIPE_SECRET_KEY | For payments | API authentication | Stripe Dashboard |
STRIPE_WEBHOOK_SECRET | For webhooks | Webhook verification | Stripe Webhooks settings |
NEXT_PUBLIC_PRICE_ID_PRO_MONTHLY | Subscription | Product price ID | Stripe Products |
NEXT_PUBLIC_PRICE_ID_PRO_YEARLY | Subscription | Product price ID | Stripe Products |
NEXT_PUBLIC_PRICE_ID_LIFETIME | One-time | Product price ID | Stripe Products |
CREEM_API_KEY | Alternative payment | API authentication | creem.io |
CREEM_WEBHOOK_SECRET | Alternative payment | Webhook verification | Creem Dashboard |
Storage
Variable | Required | Purpose | Get From |
---|---|---|---|
NEXT_PUBLIC_AVATARS_BUCKET_NAME | File uploads | Bucket identifier | Your storage provider |
STORAGE_REGION | File uploads | Storage region | R2: auto , S3: us-east-1 |
STORAGE_ACCESS_KEY_ID | File uploads | API authentication | R2/S3 API Keys |
STORAGE_SECRET_ACCESS_KEY | File uploads | API secret | R2/S3 API Keys |
STORAGE_ENDPOINT | R2 only | R2 endpoint URL | Cloudflare R2 Dashboard |
STORAGE_ACCOUNT_ID | R2 Workers | Account identifier | Cloudflare Dashboard |
Analytics
Variable | Required | Purpose | Get From |
---|---|---|---|
NEXT_PUBLIC_GOOGLE_ANALYTICS_ID | Optional | GA4 tracking | Google Analytics |
NEXT_PUBLIC_UMAMI_WEBSITE_ID | Optional | Umami tracking | Umami Dashboard |
NEXT_PUBLIC_UMAMI_SCRIPT_URL | Optional | Umami script | Umami instance URL |
NEXT_PUBLIC_PLAUSIBLE_DOMAIN | Optional | Plausible tracking | Your domain |
NEXT_PUBLIC_PLAUSIBLE_SCRIPT_URL | Optional | Plausible script | https://plausible.io/js/script.js |
AI & Credits
Variable | Required | Purpose | Get From |
---|---|---|---|
GOOGLE_GENERATIVE_AI_API_KEY | For AI features | API authentication | Google AI Studio |
CREDIT_LITE_PRICE_ID | Credits system | Product price ID | Stripe Products |
CREDIT_STANDARD_PRICE_ID | Credits system | Product price ID | Stripe Products |
CREDIT_PRO_PRICE_ID | Credits system | Product price ID | Stripe Products |
CREDIT_MAX_PRICE_ID | Credits system | Product price ID | Stripe Products |
Security
Variable | Required | Purpose | Get From |
---|---|---|---|
CRON_SECRET | Cron jobs | Endpoint protection | openssl rand -base64 16 |
AWS_ACCESS_KEY_ID | AWS deployment | AWS authentication | AWS IAM |
AWS_SECRET_ACCESS_KEY | AWS deployment | AWS secret | AWS IAM |
Troubleshooting
Common Issues
❌ "Missing BETTER_AUTH_SECRET"
# Generate a new secret
openssl rand -base64 32
# Add to .env.local
❌ "Database connection failed"
- Check
DATABASE_URL
format - Verify database is running
- Check network connectivity
- Ensure
sslmode=require
for cloud databases
❌ "Stripe webhook signature verification failed"
- Development: Use
stripe listen
webhook secret - Production: Use Stripe Dashboard webhook secret
- Ensure
STRIPE_WEBHOOK_SECRET
matches your environment
❌ "OAuth callback URL mismatch"
- Verify
BETTER_AUTH_URL
matches OAuth app settings - Check callback URL:
{BETTER_AUTH_URL}/api/auth/callback/{provider}
- Use different OAuth apps for dev/staging/production
❌ "Storage upload failed"
- Verify bucket name and permissions
- Check
STORAGE_ACCESS_KEY_ID
and secret - For R2: Ensure
STORAGE_ENDPOINT
is correct - For S3: Verify region
Environment-Specific Debugging
Check loaded variables:
// Add to any server component temporarily
console.log('Loaded env:', {
hasAuthSecret: !!process.env.BETTER_AUTH_SECRET,
hasDatabaseUrl: !!process.env.DATABASE_URL,
// Never log actual values!
});
Verify public variables in browser:
// Browser console
console.log('Public URL:', process.env.NEXT_PUBLIC_APP_URL);
Best Practices
Development Workflow
-
Use
.env.local
for local development- Git-ignored by default
- Overrides other
.env
files
-
Keep
.env.example
updated- Use dummy values
- Document all required variables
- Commit to repository
-
Separate environments
.env.local → Development .env.production → Production values
Security Checklist
- All secrets use strong random values
- No secrets committed to Git
- Different OAuth apps per environment
- Webhook secrets match environment
- API keys have minimum required permissions
- Production uses SSL/TLS (
https://
) - Rotate secrets every 90 days
Production Deployment
- Verify all required variables are set
- Use production API keys (not test keys)
- Update OAuth callback URLs
- Configure production webhook endpoints
- Set
BETTER_AUTH_URL
to production domain - Enable SSL for database connections
Migration Guide
Moving from Development to Production
Update Authentication URLs
# Development
BETTER_AUTH_URL=http://localhost:3000
# Production
BETTER_AUTH_URL=https://yourdomain.com
Switch to Production Keys
- Stripe:
sk_live_...
instead ofsk_test_...
- OAuth apps: Create production apps
- Database: Use production instance
- Email: Remove test mode
Update OAuth Callbacks
Register production callback URLs:
https://yourdomain.com/api/auth/callback/github
https://yourdomain.com/api/auth/callback/google
Configure Production Webhooks
- Stripe:
https://yourdomain.com/api/webhooks/stripe
- Use production webhook secrets
Next Steps
Now that you understand environment variables:
- Configure your deployment platform: Deployment Guide
- Set up your database: Database Setup
- Configure authentication: Authentication Guide
- Enable payments: Payment Integration
Questions? Check our Documentation or Contact Support