Skip to main content

Environment Variables

Reportr requires several environment variables for database connections, authentication, API integrations, and third-party services.

Quick Reference

Copy .env.example from the repository root to get started:
cp .env.example .env

Required Variables

These variables are required for the application to function:

Database

DATABASE_URL
string
required
PostgreSQL connection string for direct database access (migrations)
DATABASE_URL="postgresql://username:password@host:5432/reportr"
postgresql://[user]:[password]@[host]:[port]/[database]?[parameters]
Parameters:
  • sslmode=require - Enforce SSL connection
  • connect_timeout=10 - Connection timeout in seconds
PRISMA_DATABASE_URL
string
PostgreSQL connection string with connection pooling (runtime queries)
PRISMA_DATABASE_URL="postgresql://username:password@host:6543/reportr?pgbouncer=true"
For serverless deployments (Vercel), use a pooled connection to avoid “too many connections” errors.

Authentication

NEXTAUTH_SECRET
string
required
Random secret for encrypting JWTs and session tokens
NEXTAUTH_SECRET="your-random-secret-here-min-32-chars"
# Using OpenSSL
openssl rand -base64 32

# Using Node.js
node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"
NEXTAUTH_URL
string
required
Public URL of your application
# Development
NEXTAUTH_URL="http://localhost:3000"

# Production
NEXTAUTH_URL="https://reportr.agency"
Vercel automatically sets this in production. Only required for local development.
NEXT_PUBLIC_APP_URL
string
required
Client-side accessible app URL (same as NEXTAUTH_URL)
NEXT_PUBLIC_APP_URL="https://reportr.agency"
Variables prefixed with NEXT_PUBLIC_ are accessible in browser JavaScript.

Google OAuth & APIs

GOOGLE_CLIENT_ID
string
required
Google OAuth client ID for authentication
GOOGLE_CLIENT_ID="123456789-abcdefghijklmnop.apps.googleusercontent.com"
  1. Go to Google Cloud Console
  2. Create or select a project
  3. Enable Google+ API
  4. Create OAuth 2.0 credentials
  5. Add authorized redirect URI: https://yourdomain.com/api/auth/callback/google
GOOGLE_CLIENT_SECRET
string
required
Google OAuth client secret
GOOGLE_CLIENT_SECRET="GOCSPX-abcdefghijklmnopqrstuvwxyz"
GOOGLE_REDIRECT_URI
string
required
OAuth callback URL for Google authentication
GOOGLE_REDIRECT_URI="https://reportr.agency/api/auth/callback/google"
Must match exactly with the redirect URI configured in Google Cloud Console.
PAGESPEED_API_KEY
string
required
Google PageSpeed Insights API key for performance data
PAGESPEED_API_KEY="AIzaSyABCDEFGHIJKLMNOPQRSTUVWXYZ1234567"
  1. Go to Google Cloud Console
  2. Click Create Credentials → API Key
  3. Enable PageSpeed Insights API
  4. Restrict key to PageSpeed Insights API only (recommended)

AI Services

ANTHROPIC_API_KEY
string
required
Anthropic Claude API key for generating report insights
ANTHROPIC_API_KEY="sk-ant-api03-abcdefghijklmnopqrstuvwxyz1234567890"
  1. Sign up at console.anthropic.com
  2. Go to API Keys
  3. Create a new API key
  4. Copy and store securely
Pricing: Claude 3.5 Sonnet costs ~$3 per million input tokens.

Queue System

UPSTASH_REDIS_REST_URL
string
required
Upstash Redis REST API URL for background job queue
UPSTASH_REDIS_REST_URL="https://us1-example-12345.upstash.io"
UPSTASH_REDIS_REST_TOKEN
string
required
Upstash Redis authentication token
UPSTASH_REDIS_REST_TOKEN="AabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890="
  1. Go to console.upstash.com
  2. Create a new Redis database
  3. Select region closest to your deployment
  4. Copy REST URL and REST Token from database details
Free tier: 10,000 commands/day

File Storage

BLOB_READ_WRITE_TOKEN
string
required
Vercel Blob Storage token for PDF file uploads
BLOB_READ_WRITE_TOKEN="vercel_blob_rw_ABCdefGHIjkl123_mnoPQRstuVWXyzAbcdEFghijKLmnopQRSTuvwxYZ"
  1. Go to vercel.com/dashboard/stores
  2. Create a new Blob store
  3. Link to your project
  4. Copy the read-write token
Free tier: 1GB storage, 100GB bandwidth/month

Email Service

RESEND_API_KEY
string
required
Resend API key for sending transactional emails
RESEND_API_KEY="re_AbCdEfGhIj_1234567890KlMnOpQrStUvWxYz"
FROM_EMAIL
string
required
Sender email address for transactional emails
FROM_EMAIL="[email protected]"
Must be a verified domain in Resend dashboard.
REPLY_TO_EMAIL
string
required
Reply-to email address for customer responses
REPLY_TO_EMAIL="[email protected]"

Optional Variables

These variables are optional but enable additional features:

Payment Processing

PAYPAL_CLIENT_ID
string
PayPal REST API client ID for subscription payments
PAYPAL_CLIENT_ID="AabCdefGHIjklMNOpqRSTuvWXyzABcDEFghiJKLmnOPqrsTUvwxYZ1234567890"
PAYPAL_CLIENT_SECRET
string
PayPal REST API client secret
PAYPAL_CLIENT_SECRET="EabCdefGHIjklMNOpqRSTuvWXyzABcDEFghiJKLmnOPqrsTUvwxYZ1234567890"
PAYPAL_MODE
string
default:"sandbox"
PayPal environment mode
# Development
PAYPAL_MODE="sandbox"

# Production
PAYPAL_MODE="live"
PAYPAL_WEBHOOK_ID
string
PayPal webhook ID for signature verification
PAYPAL_WEBHOOK_ID="1AB23456CD789012E"
  1. Go to PayPal Developer Dashboard
  2. Navigate to Apps & Credentials → Webhooks
  3. Create webhook with URL: https://yourdomain.com/api/webhooks/paypal
  4. Select event types:
    • BILLING.SUBSCRIPTION.CREATED
    • BILLING.SUBSCRIPTION.UPDATED
    • BILLING.SUBSCRIPTION.CANCELLED
    • PAYMENT.SALE.COMPLETED
  5. Copy the Webhook ID

PayPal Plan IDs

These configure subscription plans:
PAYPAL_STARTER_TRIAL_PLAN_ID
string
Starter plan with 7-day trial
PAYPAL_STARTER_TRIAL_PLAN_ID="P-0X464499YG9822634NEQJ5XQ"
PAYPAL_STARTER_DIRECT_PLAN_ID
string
Starter plan without trial
PAYPAL_STARTER_DIRECT_PLAN_ID="P-6PJ50716H4431863PNEQKBLQ"
PAYPAL_PRO_TRIAL_PLAN_ID
string
Professional plan with 7-day trial
PAYPAL_PRO_TRIAL_PLAN_ID="P-09P26662R8680522DNEQJ7XY"
PAYPAL_PRO_DIRECT_PLAN_ID
string
Professional plan without trial
PAYPAL_PRO_DIRECT_PLAN_ID="P-90W906144W5364313NEQKB5I"
PAYPAL_AGENCY_TRIAL_PLAN_ID
string
Agency plan with 7-day trial
PAYPAL_AGENCY_TRIAL_PLAN_ID="P-7SU477161L382370MNEQKCQQ"
PAYPAL_AGENCY_DIRECT_PLAN_ID
string
Agency plan without trial
PAYPAL_AGENCY_DIRECT_PLAN_ID="P-0KW62605U4011430FNEQKDCY"

Client-Side PayPal Plan IDs

These are duplicates of server-side plan IDs but accessible in browser JavaScript (prefixed with NEXT_PUBLIC_).
NEXT_PUBLIC_PAYPAL_STARTER_TRIAL_PLAN_ID
string
NEXT_PUBLIC_PAYPAL_STARTER_TRIAL_PLAN_ID="P-0X464499YG9822634NEQJ5XQ"
NEXT_PUBLIC_PAYPAL_STARTER_DIRECT_PLAN_ID
string
NEXT_PUBLIC_PAYPAL_STARTER_DIRECT_PLAN_ID="P-6PJ50716H4431863PNEQKBLQ"
NEXT_PUBLIC_PAYPAL_PRO_TRIAL_PLAN_ID
string
NEXT_PUBLIC_PAYPAL_PRO_TRIAL_PLAN_ID="P-09P26662R8680522DNEQJ7XY"
NEXT_PUBLIC_PAYPAL_PRO_DIRECT_PLAN_ID
string
NEXT_PUBLIC_PAYPAL_PRO_DIRECT_PLAN_ID="P-90W906144W5364313NEQKB5I"
NEXT_PUBLIC_PAYPAL_AGENCY_TRIAL_PLAN_ID
string
NEXT_PUBLIC_PAYPAL_AGENCY_TRIAL_PLAN_ID="P-7SU477161L382370MNEQKCQQ"
NEXT_PUBLIC_PAYPAL_AGENCY_DIRECT_PLAN_ID
string
NEXT_PUBLIC_PAYPAL_AGENCY_DIRECT_PLAN_ID="P-0KW62605U4011430FNEQKDCY"

Alternative Payment (Stripe)

STRIPE_SECRET_KEY
string
Stripe secret key (alternative to PayPal)
# Test mode
STRIPE_SECRET_KEY="sk_test_51ABcdefGHIjklMNOpqrSTUvwxYZ123456789"

# Live mode
STRIPE_SECRET_KEY="sk_live_51ABcdefGHIjklMNOpqrSTUvwxYZ123456789"
STRIPE_WEBHOOK_SECRET
string
Stripe webhook signing secret
STRIPE_WEBHOOK_SECRET="whsec_abcdefghijklmnopqrstuvwxyz1234567890"

Cron Job Security

CRON_SECRET
string
required
Secret token for authenticating cron job requests
CRON_SECRET="PiVKrJew9gQyWTohW/LiUV3J+xZPFIC7UkXrqLXoFgI="
# Using OpenSSL
openssl rand -base64 32

# Using Node.js
node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"
This prevents unauthorized access to cron endpoints like /api/cron/process-cancellations.

Environment-Specific Configuration

Development (.env.local)

# Database
DATABASE_URL="postgresql://postgres:password@localhost:5432/reportr_dev"

# Auth
NEXTAUTH_URL="http://localhost:3000"
NEXT_PUBLIC_APP_URL="http://localhost:3000"

# PayPal
PAYPAL_MODE="sandbox"

# Email (use test mode)
RESEND_API_KEY="re_test_abcdefghijklmnopqrstuvwxyz"

Production (.env.production)

# Database (with connection pooling)
DATABASE_URL="postgresql://user:pass@host:5432/reportr"
PRISMA_DATABASE_URL="postgresql://user:pass@host:6543/reportr?pgbouncer=true"

# Auth
NEXTAUTH_URL="https://reportr.agency"
NEXT_PUBLIC_APP_URL="https://reportr.agency"

# PayPal
PAYPAL_MODE="live"

# Email (production API key)
RESEND_API_KEY="re_prod_abcdefghijklmnopqrstuvwxyz"

Setting Variables in Vercel

Via Dashboard

1

Open project settings

Navigate to Settings → Environment Variables in Vercel dashboard
2

Add variable

Click Add and enter:
  • Key: Variable name (e.g., DATABASE_URL)
  • Value: Variable value
  • Environment: Select Production, Preview, or Development
3

Redeploy

Trigger a new deployment for changes to take effect:
vercel --prod

Via CLI

# Add single variable
vercel env add DATABASE_URL production

# Import from .env file
vercel env pull .env.local

# List all variables
vercel env ls

# Remove variable
vercel env rm DATABASE_URL production

Validation

Reportr validates required environment variables at build time:
// src/lib/env.ts
const requiredEnvVars = [
  'DATABASE_URL',
  'NEXTAUTH_SECRET',
  'NEXTAUTH_URL',
  'GOOGLE_CLIENT_ID',
  'GOOGLE_CLIENT_SECRET',
  'ANTHROPIC_API_KEY',
  // ... more
]

for (const envVar of requiredEnvVars) {
  if (!process.env[envVar]) {
    throw new Error(`Missing required environment variable: ${envVar}`)
  }
}
Build will fail if any required variables are missing.

Security Best Practices

1

Never commit secrets to Git

Add .env to .gitignore:
# .gitignore
.env
.env.local
.env.production
2

Use different values per environment

  • Development: Use test/sandbox credentials
  • Production: Use live credentials
  • Rotate production secrets regularly
3

Limit access to production variables

Use Vercel team permissions to restrict who can view/edit production environment variables.
4

Monitor for exposed secrets

Use tools like:

Deployment Checklist

Before deploying to production, verify:
  • DATABASE_URL points to production database
  • PRISMA_DATABASE_URL uses connection pooling
  • Database migrations have been run
  • Backups are configured
  • NEXTAUTH_SECRET is unique and secure (32+ chars)
  • NEXTAUTH_URL matches production domain
  • GOOGLE_REDIRECT_URI is configured in Google Console
  • OAuth callback URLs are whitelisted
  • ANTHROPIC_API_KEY has sufficient credits
  • PAGESPEED_API_KEY is restricted to PageSpeed API
  • UPSTASH_REDIS_REST_URL and token are valid
  • BLOB_READ_WRITE_TOKEN has correct permissions
  • RESEND_API_KEY domain is verified
  • PAYPAL_MODE is set to live
  • PayPal plan IDs are for production plans
  • PAYPAL_WEBHOOK_ID is configured
  • Webhook endpoint is publicly accessible
  • CRON_SECRET is set for cron endpoints
  • No secrets are committed to Git
  • Production values differ from development
  • Access to variables is restricted

Troubleshooting

Error: process.env.VARIABLE_NAME is undefinedSolutions:
  1. Check variable is set in Vercel dashboard
  2. Ensure correct environment (Production/Preview/Development)
  3. Redeploy application after adding variable
  4. For client-side variables, use NEXT_PUBLIC_ prefix
Error: Can't reach database serverSolutions:
  1. Verify DATABASE_URL format is correct
  2. Check database is accessible from Vercel IPs
  3. Use PRISMA_DATABASE_URL with connection pooling
  4. Ensure database credentials are correct
Error: redirect_uri_mismatchSolutions:
  1. Match GOOGLE_REDIRECT_URI exactly in Google Console
  2. Include http:// or https:// in URI
  3. No trailing slashes in callback URL
  4. Case-sensitive matching required
Error: Webhook signature verification failedSolutions:
  1. Verify PAYPAL_WEBHOOK_ID is correct
  2. Check webhook URL in PayPal dashboard matches deployment
  3. Ensure PAYPAL_MODE matches webhook environment (sandbox/live)
  4. Verify webhook events are enabled

Additional Resources

Vercel Deployment

Deploy to Vercel with environment variables

Database Setup

Configure PostgreSQL database

.env.example

View complete example file

Vercel Env Docs

Official Vercel documentation

Build docs developers (and LLMs) love