Skip to main content
Resonance uses @t3-oss/env-nextjs for type-safe environment variable validation. All server-side variables are validated at build time using Zod schemas defined in src/lib/env.ts:4.

Quick Setup

Create a .env.local file in your project root:
cp .env.example .env.local

Required Variables

Database

Type: string (required)PostgreSQL connection string for Prisma.
DATABASE_URL="postgresql://user:password@host:5432/database"
Resonance uses Prisma Postgres with the PostgreSQL adapter. Any PostgreSQL 12+ database will work.
Example providers:
  • Prisma Postgres (recommended)
  • Neon
  • Supabase
  • Railway Postgres

Chatterbox TTS (Modal)

Type: url (required)The deployed Modal endpoint URL for your Chatterbox TTS API.
CHATTERBOX_API_URL="https://your-workspace--chatterbox-tts-serve.modal.run"
This URL is displayed after running modal deploy chatterbox_tts.py. See Modal Deployment for setup instructions.
Type: string (required)API key for authenticating requests to the Chatterbox TTS endpoint.
CHATTERBOX_API_KEY="your-secret-api-key-here"
Use a strong random string. This key must match the CHATTERBOX_API_KEY secret configured in Modal.
Generate a secure key:
openssl rand -base64 32

Clerk Authentication

Type: string (required)Server-side Clerk secret key (starts with sk_).
CLERK_SECRET_KEY="sk_live_..."
Find this in your Clerk Dashboard under API Keys.
Type: string (required, client-side)Public Clerk key (starts with pk_).
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY="pk_live_..."
The NEXT_PUBLIC_ prefix makes this variable accessible in browser code.
Type: string (required, client-side)Path to your sign-in page.
NEXT_PUBLIC_CLERK_SIGN_IN_URL="/sign-in"
Type: string (required, client-side)Path to your sign-up page.
NEXT_PUBLIC_CLERK_SIGN_UP_URL="/sign-up"
See Clerk Authentication Setup for complete configuration.

Cloudflare R2 Storage

Type: string (required)Your Cloudflare account ID.
R2_ACCOUNT_ID="ea63931e6e8ff54c5be60feacd3026d6"
Find this in the Cloudflare Dashboard sidebar under R2.
Type: string (required)R2 API token access key ID.
R2_ACCESS_KEY_ID="abc123..."
Type: string (required)R2 API token secret access key.
R2_SECRET_ACCESS_KEY="xyz789..."
Never commit this to version control. Keep your .env.local file in .gitignore.
Type: string (required)Name of your R2 bucket.
R2_BUCKET_NAME="resonance-app"
See Cloudflare R2 Setup for bucket creation and token generation.

Polar Billing

Type: string (required)Your Polar API access token.
POLAR_ACCESS_TOKEN="polar_at_..."
Generate this in the Polar Dashboard under Settings → API Tokens.
Type: enum (required)Polar environment mode.
POLAR_SERVER="sandbox"
Options:
  • sandbox - Use for development (test card: 4242 4242 4242 4242)
  • production - Use for live payments
Default: sandbox (defined in src/lib/env.ts:7)
Type: string (required)The ID of your Polar product with usage-based metering.
POLAR_PRODUCT_ID="prod_..."
Create a product in Polar Dashboard and attach a character-based meter for TTS billing.
See Polar Billing Configuration for product and meter setup.

Application

Type: string (required)The base URL of your application.
# Development
APP_URL="http://localhost:3000"

# Production
APP_URL="https://resonance.yourdomain.com"
Used for:
  • Clerk redirect URLs (checkout success, billing portal)
  • Polar webhook verification
  • Email templates

Optional Variables

Development

Type: boolean (optional)Skip environment variable validation during build.
SKIP_ENV_VALIDATION="true"
Only use this for testing or when building without environment access. Never use in production.
Defined in src/lib/env.ts:19
Type: enum (automatic)Set automatically by Node.js.Values:
  • development - Local dev server (npm run dev)
  • production - Production builds (npm run build && npm start)
  • test - Testing environment
Used in src/lib/db.ts:14 to prevent Prisma connection pooling in development.

Validation

All environment variables are validated using Zod at application startup. If validation fails, the build will error with details about missing or invalid variables.
src/lib/env.ts
import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";

export const env = createEnv({
  server: {
    POLAR_ACCESS_TOKEN: z.string().min(1),
    POLAR_SERVER: z.enum(["sandbox", "production"]).default("sandbox"),
    POLAR_PRODUCT_ID: z.string().min(1),
    DATABASE_URL: z.string().min(1),
    APP_URL: z.string().min(1),
    R2_ACCOUNT_ID: z.string().min(1),
    R2_ACCESS_KEY_ID: z.string().min(1),
    R2_SECRET_ACCESS_KEY: z.string().min(1),
    R2_BUCKET_NAME: z.string().min(1),
    CHATTERBOX_API_URL: z.url(),
    CHATTERBOX_API_KEY: z.string().min(1),
  },
  experimental__runtimeEnv: {},
  skipValidation: !!process.env.SKIP_ENV_VALIDATION,
});

Environment File Structure

Here’s a complete .env.local template:
.env.local
# Database
DATABASE_URL="postgresql://..."

# Chatterbox TTS (Modal)
CHATTERBOX_API_URL="https://your-workspace--chatterbox-tts-serve.modal.run"
CHATTERBOX_API_KEY="your-api-key"

# Clerk
CLERK_SECRET_KEY="sk_..."
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY="pk_..."
NEXT_PUBLIC_CLERK_SIGN_IN_URL="/sign-in"
NEXT_PUBLIC_CLERK_SIGN_UP_URL="/sign-up"

# Cloudflare R2
R2_ACCOUNT_ID="your-account-id"
R2_ACCESS_KEY_ID="your-access-key"
R2_SECRET_ACCESS_KEY="your-secret-key"
R2_BUCKET_NAME="resonance-app"

# Polar (Billing)
POLAR_ACCESS_TOKEN="polar_at_..."
POLAR_SERVER="sandbox"
POLAR_PRODUCT_ID="prod_..."

# App
APP_URL="http://localhost:3000"

Security Best Practices

Never commit .env.local or any file containing secrets to version control.
1

Use .gitignore

Ensure .env.local is in your .gitignore file:
.env*.local
.env
2

Use strong secrets

Generate cryptographically secure keys for CHATTERBOX_API_KEY:
openssl rand -base64 32
3

Rotate keys regularly

Update API keys and tokens periodically, especially after team member changes.
4

Use environment-specific files

  • .env.local - Local development (not committed)
  • .env.production - Production secrets (use hosting provider’s secret management)

Troubleshooting

Validation errors at build time

❌ Invalid environment variables:
  CHATTERBOX_API_URL: Invalid url
Solution: Ensure the URL includes protocol (https://) and is properly formatted.

Variables not loading

1
Restart your dev server after changing .env.local
2
Check that Next.js recognizes the file (must be in project root)
3
Verify NEXT_PUBLIC_ prefix for client-side variables

SKIP_ENV_VALIDATION not working

This variable must be set before the Next.js build process runs:
SKIP_ENV_VALIDATION=true npm run build

Database Setup

Prisma schema and migrations

Cloudflare R2

Object storage configuration

Clerk Auth

Authentication and organizations

Polar Billing

Usage-based billing setup

Build docs developers (and LLMs) love