Environment Variables
Configure environment variables for Plainform integrations
Environment Variables
Plainform uses environment variables to configure integrations securely. All variables are validated at runtime using @t3-oss/env-nextjs and Zod schemas.
If any required variable is missing or invalid, the application won't start. This prevents runtime errors and security issues.
Quick Setup
Copy template
Use the template below and fill in your values from each service provider.
Validation
The app automatically validates all variables on startup via env.ts.
Complete .env Template
# Application
SITE_URL="http://localhost:3000"
NEXT_PUBLIC_SITE_URL="http://localhost:3000"
# Clerk (Authentication)
NEXT_PUBLIC_CLERK_SIGN_IN_URL="/sign-in"
NEXT_PUBLIC_CLERK_SIGN_UP_URL="/sign-up"
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY="pk_test_xxxx"
CLERK_SECRET_KEY="sk_test_xxxx"
# Stripe (Payments)
STRIPE_SECRET_KEY="sk_test_xxxx"
STRIPE_PUBLISHABLE_KEY="pk_test_xxxx"
STRIPE_WEBHOOK_SECRET="whsec_xxxx"
# Supabase (Database)
DATABASE_URL="postgresql://user:password@host:6543/postgres?pgbouncer=true"
DIRECT_URL="postgresql://user:password@host:5432/postgres"
# AWS S3 (Storage)
AWS_ACCESS_KEY_ID="AKIAXXXXXXXXXXXX"
AWS_SECRET_ACCESS_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
AWS_S3_ENDPOINT="https://your-bucket.s3.region.amazonaws.com"
AWS_S3_REGION="us-east-1"
AWS_S3_BUCKET="your-bucket-name"
# Resend (Emails)
RESEND_API_KEY="re_xxxx"
# Mailchimp (Newsletter)
MAILCHIMP_API_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-us19"
MAILCHIMP_API_SERVER="us6"
MAILCHIMP_AUDIENCE_ID="xxxxxxxxxx"
# PostHog (Analytics)
NEXT_PUBLIC_POSTHOG_KEY="phc_xxxx"
NEXT_PUBLIC_POSTHOG_HOST="https://us.i.posthog.com"Variable Reference
Application
| Env Variable | Type | Default |
|---|---|---|
SITE_URL | string | http://localhost:3000 |
NEXT_PUBLIC_SITE_URL | string | http://localhost:3000 |
Use http://localhost:3000 in development and your production domain in production (e.g., https://yourdomain.com).
Clerk (Authentication)
| Env Variable | Type | Default |
|---|---|---|
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY | string | pk_test_xxxx |
CLERK_SECRET_KEY | string | sk_test_xxxx |
NEXT_PUBLIC_CLERK_SIGN_IN_URL | string | /sign-in |
NEXT_PUBLIC_CLERK_SIGN_UP_URL | string | /sign-up |
Where to find:
- Go to Clerk Dashboard
- Select your application
- Navigate to API Keys section
- Copy the keys for your environment
Stripe (Payments)
| Env Variable | Type | Default |
|---|---|---|
STRIPE_SECRET_KEY | string | sk_test_xxxx |
STRIPE_PUBLISHABLE_KEY | string | pk_test_xxxx |
STRIPE_WEBHOOK_SECRET | string | whsec_xxxx |
Where to find:
- Go to Stripe Dashboard
- Navigate to Developers → API keys
- Copy Secret key and Publishable key
- For webhook secret: Developers → Webhooks → Add endpoint → Copy signing secret
Use test keys (sk_test_, pk_test_) in development. Switch to live keys in production.
Supabase (Database)
| Env Variable | Type | Default |
|---|---|---|
DATABASE_URL | string | postgresql://user:password@host:6543/postgres?pgbouncer=true |
DIRECT_URL | string | postgresql://user:password@host:5432/postgres |
Where to find:
- Go to Supabase Dashboard
- Select your project
- Navigate to Settings → Database
- Copy "Connection string" for
DATABASE_URL(Transaction mode) - Copy "Connection string" for
DIRECT_URL(Session mode)
DATABASE_URL uses port 6543 with pgbouncer for connection pooling. DIRECT_URL uses port 5432 for direct connections (required for Prisma migrations).
AWS S3 (Storage)
| Env Variable | Type | Default |
|---|---|---|
AWS_ACCESS_KEY_ID | string | - |
AWS_SECRET_ACCESS_KEY | string | - |
AWS_S3_ENDPOINT | string | https://your-bucket.s3.region.amazonaws.com |
AWS_S3_REGION | string | - |
AWS_S3_BUCKET | string | - |
Where to find:
- Go to AWS Console
- Navigate to IAM → Users → Create user
- Attach policy:
AmazonS3FullAccess - Create access key → Copy Access Key ID and Secret Access Key
- Navigate to S3 → Create bucket → Copy bucket name and region
Resend (Emails)
| Env Variable | Type | Default |
|---|---|---|
RESEND_API_KEY | string | re_xxxx |
Where to find:
- Go to Resend Dashboard
- Navigate to API Keys
- Create API key → Copy the key
Mailchimp (Newsletter)
| Env Variable | Type | Default |
|---|---|---|
MAILCHIMP_API_KEY | string | - |
MAILCHIMP_API_SERVER | string | - |
MAILCHIMP_AUDIENCE_ID | string | - |
Where to find:
- Go to Mailchimp Dashboard
- Navigate to Account → Extras → API keys
- Create API key → Copy the key (note the server prefix like
us6) - Navigate to Audience → Settings → Audience name and defaults → Copy Audience ID
PostHog (Analytics)
| Env Variable | Type | Default |
|---|---|---|
NEXT_PUBLIC_POSTHOG_KEY | string | phc_xxxx |
NEXT_PUBLIC_POSTHOG_HOST | string | https://us.i.posthog.com |
Where to find:
- Go to PostHog Dashboard
- Navigate to Project Settings
- Copy Project API Key
- Copy Host URL (use EU endpoint for GDPR compliance)
Validation Schema
All environment variables are validated in env.ts using Zod:
// From env.ts
import { createEnv } from '@t3-oss/env-nextjs';
import { z } from 'zod';
export const env = createEnv({
server: {
STRIPE_SECRET_KEY: z.string().min(5),
DATABASE_URL: z.string().min(5),
// ... other server variables
},
client: {
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: z.string().min(5),
NEXT_PUBLIC_POSTHOG_KEY: z.string().min(5),
// ... other client variables
},
experimental__runtimeEnv: {
NEXT_PUBLIC_SITE_URL: process.env.NEXT_PUBLIC_SITE_URL,
// ... other client variables
},
});Local vs Production
Development (.env file):
- Use test/sandbox keys for all services
- Use
http://localhost:3000for URLs - Stripe:
sk_test_andpk_test_keys - Clerk:
pk_test_andsk_test_keys - Database: Development database connection
Production (Vercel/hosting platform):
- Use live/production keys
- Use your production domain for URLs
- Stripe:
sk_live_andpk_live_keys - Clerk:
pk_live_andsk_live_keys - Database: Production database connection
- Set variables in hosting platform dashboard (e.g., Vercel → Settings → Environment Variables)
Security Best Practices
- Never commit .env files - Already in
.gitignore - Use different keys per environment - Test keys in dev, live keys in production
- Rotate keys regularly - Especially after team member changes
- Limit key permissions - Use least-privilege principle (e.g., read-only keys where possible)
- Validate on startup - The
env.tsschema prevents missing/invalid variables
Never expose server-side variables to the client. Only variables prefixed with NEXT_PUBLIC_ are accessible in the browser.
Troubleshooting
Next Steps
- Git Workflow - Set up version control
- Build & Deploy - Deploy to production
- Authentication Setup - Configure Clerk
- Payments Setup - Configure Stripe
How is this guide ?
Last updated on