Skip to main content
Featul requires several environment variables for authentication, database access, and third-party integrations. This guide covers all required and optional variables.

Configuration File

Environment variables are stored in .env.local (development) or configured in your hosting platform (production).
Never commit .env.local or .env files to version control. Use .env.example as a template.
Reference: apps/app/.env.example

Required Variables

These variables are essential for Featul to function:

Application URLs

NEXT_PUBLIC_APP_URL=https://app.featul.com
  • NEXT_PUBLIC_APP_URL: Public-facing application URL
  • Used for OAuth callbacks, email links, and API endpoints
  • Must include protocol (https://)
  • Should match your production domain

Database

DATABASE_URL=postgresql://user:password@host:5432/database?sslmode=require
  • DATABASE_URL: PostgreSQL connection string
  • Must use postgresql:// protocol
  • For Neon: Use the pooled connection string from dashboard
  • Format: postgresql://[user]:[password]@[host]:[port]/[database]?sslmode=require
Always use SSL mode (sslmode=require) for production databases.

Authentication

BETTER_AUTH_SECRET=your-super-secret-random-string-min-32-chars
AUTH_COOKIE_DOMAIN=featul.com
AUTH_TRUSTED_ORIGINS=https://featul.com,https://app.featul.com,https://*.featul.com
  • BETTER_AUTH_SECRET: Secret key for JWT signing and encryption
    • Minimum 32 characters
    • Generate: openssl rand -base64 32
    • Must be consistent across deployments
  • AUTH_COOKIE_DOMAIN: Root domain for cross-subdomain authentication
    • Use root domain without protocol: featul.com
    • Enables authentication across workspace subdomains
  • AUTH_TRUSTED_ORIGINS: Comma-separated list of allowed origins
    • Include main domain and wildcard for subdomains
    • Used for CORS and OAuth redirects

Passkeys (WebAuthn)

PASSKEY_RP_ID=featul.com
PASSKEY_RP_NAME=Featul
PASSKEY_ORIGIN=https://app.featul.com
  • PASSKEY_RP_ID: Relying party identifier (typically your domain)
  • PASSKEY_RP_NAME: Display name for passkey prompts
  • PASSKEY_ORIGIN: Full origin URL for WebAuthn

Optional Variables

Redis (Rate Limiting & Caching)

UPSTASH_REDIS_REST_URL=https://your-region.upstash.io
UPSTASH_REDIS_REST_TOKEN=your-upstash-token
  • UPSTASH_REDIS_REST_URL: Upstash Redis REST API endpoint
  • UPSTASH_REDIS_REST_TOKEN: Authentication token from Upstash dashboard
  • Used for: Rate limiting, session storage, caching
  • Get from: console.upstash.com

AI Features (OpenRouter)

OPENROUTER_API_KEY=sk-or-v1-...
OPENROUTER_MODEL=openrouter/auto
OPENROUTER_APP_NAME=Featul
OPENROUTER_REFERER=https://app.featul.com
  • OPENROUTER_API_KEY: API key from OpenRouter
  • OPENROUTER_MODEL: Model to use (default: openrouter/auto)
  • OPENROUTER_APP_NAME: Application name for tracking
  • OPENROUTER_REFERER: Referer URL for API requests

OAuth Providers

GOOGLE_CLIENT_ID=your-google-client-id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your-google-client-secret
Configure at: Google Cloud Console
  • Create OAuth 2.0 credentials
  • Add authorized redirect URI: https://app.featul.com/api/auth/callback/google

Payments (Polar)

POLAR_ACCESS_TOKEN=polar_at_...
POLAR_WEBHOOK_SECRET=whsec_...
POLAR_SERVER=sandbox # or 'production'
POLAR_PRODUCT_ID_STARTER_MONTHLY=prod_...
POLAR_PRODUCT_ID_STARTER_YEARLY=prod_...
POLAR_PRODUCT_ID_PROFESSIONAL_MONTHLY=prod_...
POLAR_PRODUCT_ID_PROFESSIONAL_YEARLY=prod_...
  • POLAR_ACCESS_TOKEN: API token from Polar dashboard
  • POLAR_WEBHOOK_SECRET: Webhook signing secret
  • POLAR_SERVER: Use sandbox for testing, production for live
  • POLAR_PRODUCT_ID_*: Product IDs for subscription tiers

Monitoring (Sentry)

SENTRY_AUTH_TOKEN=your-sentry-auth-token
  • SENTRY_AUTH_TOKEN: Auth token for uploading source maps
  • Get from: Sentry Settings
  • Used during build for source map uploads
  • Sentry is pre-configured in next.config.ts

Credential Encryption (Notra)

NOTRA_CREDENTIALS_ENCRYPTION_KEY=your-long-random-secret-min-32-chars
  • NOTRA_CREDENTIALS_ENCRYPTION_KEY: Encryption key for stored credentials
  • Minimum 32 characters
  • Generate: openssl rand -base64 32
  • Used for encrypting third-party integration credentials

Storage (Cloudflare R2)

R2_ACCOUNT_ID=your-cloudflare-account-id
R2_ACCESS_KEY_ID=your-r2-access-key-id
R2_SECRET_ACCESS_KEY=your-r2-secret-access-key
R2_BUCKET=your-bucket-name
R2_PUBLIC_BASE_URL=https://your-bucket.r2.dev
  • R2_ACCOUNT_ID: Cloudflare account ID for R2 storage
  • R2_ACCESS_KEY_ID: R2 API access key ID
  • R2_SECRET_ACCESS_KEY: R2 API secret access key
  • R2_BUCKET: Name of your R2 bucket
  • R2_PUBLIC_BASE_URL: Public base URL for accessing uploaded files
Setup instructions:
  1. Go to Cloudflare Dashboard > R2
  2. Create a new bucket or use existing one
  3. Generate R2 API tokens from “Manage R2 API Tokens”
  4. Configure public access or custom domain for R2_PUBLIC_BASE_URL
R2 storage is used for file uploads (avatars, attachments, etc.). Without these variables, file upload features will not work.

Email (Resend)

RESEND_API_KEY=re_...
RESEND_FROM=Featul <[email protected]>
  • RESEND_API_KEY: API key from Resend for sending emails
  • RESEND_FROM: Email address and name for outgoing emails
  • Used for: Authentication emails, password resets, notifications
  • Get from: resend.com/api-keys
Without Resend configured, email verification and password reset will not work in production.

Custom Domains (Vercel API)

VERCEL_TOKEN=your-vercel-api-token
VERCEL_PROJECT_ID=prj_...
# OR
VERCEL_PROJECT_NAME=your-project-name
CUSTOM_DOMAIN_CNAME_TARGET=origin.featul.com
  • VERCEL_TOKEN: Vercel API token for managing custom domains
  • VERCEL_PROJECT_ID or VERCEL_PROJECT_NAME: Your Vercel project identifier
  • CUSTOM_DOMAIN_CNAME_TARGET: CNAME target for custom workspace domains (default: origin.featul.com)
  • Used for: Automated custom domain configuration for workspaces
  • Get token from: Vercel Settings > Tokens
Required only if you want to support custom domains for user workspaces.

Platform-Specific Configuration

Set environment variables in:
  1. Project Settings > Environment Variables
  2. Add variables for Production, Preview, and Development
  3. Use Vercel CLI: vercel env add [name]
Vercel automatically sets:
  • VERCEL_URL: Deployment URL
  • VERCEL_ENV: Environment (production, preview, development)

Validation

Verify your environment variables are correctly set:
1

Check Database Connection

# Test database connectivity
bun run db:studio
Should open Drizzle Studio at https://local.drizzle.studio
2

Verify Build

# Build with environment variables
bun run build
Should complete without errors about missing variables
3

Test Authentication

Start the dev server and attempt to:
  • Sign up with email
  • Log in with OAuth providers
  • Test passkey registration (if configured)

Security Best Practices

Follow these security practices to protect your deployment.
  • Rotate secrets regularly: Change BETTER_AUTH_SECRET and API keys periodically
  • Use separate environments: Different secrets for development, staging, production
  • Limit access: Use environment-specific database users with minimal permissions
  • Enable audit logs: Track environment variable changes in your platform
  • Never log secrets: Ensure secrets aren’t logged or exposed in error messages

Troubleshooting

Database Connection Fails

Error: DATABASE_URL is not set
Solution: Ensure DATABASE_URL is set and uses correct format:
postgresql://user:password@host:5432/database?sslmode=require

Authentication Errors

Error: Invalid JWT signature
Solution:
  • Verify BETTER_AUTH_SECRET is set and consistent
  • Ensure it’s at least 32 characters
  • Check it’s the same across all deployment instances

OAuth Redirect Mismatch

Error: redirect_uri_mismatch
Solution:
  • Verify NEXT_PUBLIC_APP_URL matches your OAuth callback URL
  • Update redirect URIs in Google/GitHub OAuth settings
  • Include both http://localhost:3000 (dev) and production URLs

Next Steps

Database Setup

Configure PostgreSQL and run migrations

Deploy to Vercel

Deploy with environment variables to Vercel

Build docs developers (and LLMs) love