Environment Variables Reference
This page provides a complete reference for all environment variables used across the BookWish platform.
Backend Environment Variables
The backend uses a .env file in the backend/ directory. Copy .env.example to .env and configure.
Core Infrastructure
Database
# PostgreSQL connection string (Supabase or local)
DATABASE_URL=postgresql://postgres:[PASSWORD]@db.[PROJECT_REF].supabase.co:5432/postgres
Format: postgresql://[user]:[password]@[host]:[port]/[database]
Required: Yes
Example (local): postgresql://postgres:password@localhost:5432/bookwish
Example (Supabase): postgresql://postgres.abc123:password@aws-0-us-east-1.pooler.supabase.com:5432/postgres
Redis
# Redis connection URL (local or Railway)
REDIS_URL=redis://localhost:6379
Required: Yes
Default: redis://localhost:6379
Used for: Rate limiting, caching, Bull job queues
Server Configuration
# Server port
PORT=3000
# Node environment
NODE_ENV=development # development | production | test
PORT Default: 3000 NODE_ENV Default: development
Authentication & Security
JWT Secrets
# JWT signing secret (minimum 32 characters)
JWT_SECRET=your_secure_random_string_at_least_32_chars
# JWT refresh token secret (minimum 32 characters)
JWT_REFRESH_SECRET=another_secure_random_string_at_least_32_chars
Required: Yes
Generate with: openssl rand -hex 32
Validation: Must be at least 32 characters each
Encryption
# Encryption key for OAuth tokens (base64 encoded, 32 bytes)
ENCRYPTION_KEY=your_base64_encryption_key
Required: For stores using Square OAuth
Generate with: openssl rand -base64 32
Used for: Encrypting Square OAuth tokens in database
Book Data APIs
ISBNdb
# ISBNdb API key for book metadata
ISBNDB_API_KEY=your_isbndb_api_key
Required: Yes Get from: https://isbndb.com/apidocs/v2 Used for: Looking up book data by ISBN
Google Books API
# Google Books API key
GOOGLE_BOOKS_API_KEY=your_google_books_api_key
Required: Yes Get from: Google Cloud Console Used for: Fallback book data, cover images
Payment & Commerce
Stripe
# Stripe API keys
STRIPE_SECRET_KEY=sk_live_xxx
STRIPE_PUBLISHABLE_KEY=pk_live_xxx # Not used in backend
STRIPE_WEBHOOK_SECRET=whsec_xxx
Required: For payment processing Get from: Stripe Dashboard > API Keys
Stripe Product Price IDs:
# Premium Subscriptions (Web checkout - mobile uses RevenueCat)
STRIPE_PRICE_PREMIUM_MONTHLY=price_... # $4.99/month
STRIPE_PRICE_PREMIUM_YEARLY=price_... # $29.99/year
STRIPE_PRICE_PREMIUM_LIFETIME=price_... # $79.99 one-time
# Bookstore Subscriptions (B2B - web only)
STRIPE_PRODUCT_BOOKSTORE=price_... # $49.99/month
STRIPE_PRODUCT_CUSTOM_DOMAIN=price_... # $9.99/month add-on
Required: For subscriptions Get from: Stripe Dashboard > Products (create products first)
Square
# Square OAuth integration
SQUARE_APP_ID=sq0idp-xxx
SQUARE_APP_SECRET=sq0csp-xxx
SQUARE_ENVIRONMENT=production # sandbox | production
SQUARE_WEBHOOK_SIGNATURE_KEY=your_webhook_signature_key
Required: For stores using Square POS integration Get from: Square Developer Dashboard
RevenueCat
# RevenueCat for mobile subscriptions
REVENUECAT_API_KEY=your_revenuecat_api_key
REVENUECAT_WEBHOOK_SECRET=your_webhook_secret
Required: For mobile in-app purchases Get from: RevenueCat Dashboard
Fulfillment & Shipping
EasyPost
# EasyPost for shipping labels
EASYPOST_API_KEY=your_easypost_api_key
Required: For shipping functionality Get from: EasyPost Dashboard
BooksRun
# BooksRun for trade-in quotes
BOOKSRUN_API_KEY=your_booksrun_api_key
Required: For trade-in feature Get from: BooksRun API
Ingram Content Group
# Ingram wholesaler integration (future)
INGRAM_API_URL=https://api.ingramcontent.com
INGRAM_USERNAME=your_ingram_username
INGRAM_PASSWORD=your_ingram_password
INGRAM_SAN=your_standard_address_number
Required: No (not yet implemented) Used for: Direct book ordering from wholesaler
Warehouse Configuration
# BookWish warehouse address (for direct fulfillment)
WAREHOUSE_NAME=BookWish Fulfillment
WAREHOUSE_STREET1=123 Distribution Way
WAREHOUSE_CITY=Columbus
WAREHOUSE_STATE=OH
WAREHOUSE_ZIP=43215
WAREHOUSE_COUNTRY=US
Required: For direct fulfillment orders Defaults provided in code
Firebase (Push Notifications)
# Firebase Admin SDK credentials
FIREBASE_PROJECT_ID=your_project_id
FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\nYour key here\n-----END PRIVATE KEY-----\n"
FIREBASE_CLIENT_EMAIL=firebase-adminsdk-xxxxx@your-project.iam.gserviceaccount.com
Required: For push notifications Get from: Firebase Console > Project Settings > Service Accounts > Generate New Private Key
Note: The private key should include \n for newlines in the .env file. The code will replace \\n with actual newlines.
Email (AWS SES)
# AWS Simple Email Service
AWS_REGION=us-east-1
AWS_SES_ACCESS_KEY_ID=your_access_key_id
AWS_SES_SECRET_ACCESS_KEY=your_secret_access_key
AWS_SES_EMAIL_SOURCE=noreply@bookwish.io
# BookWish operations email (receives order notifications)
BOOKWISH_OPS_EMAIL=orders@bookwish.io
Required: For sending email notifications Get from: AWS Console > IAM > Create Access Key with SES permissions
Store Websites
# Store website base URL (bookwish.shop deployment)
STORE_WEBSITE_URL=https://bookwish.shop
Required: For Stripe checkout redirects on store websites
Default: https://bookwish.shop
Economics Configuration
# Ingram wholesale cost percentage
INGRAM_COST_PERCENTAGE=60 # 60% of retail price
# Stripe payment processing fees
STRIPE_FEE_PERCENTAGE=2.9 # 2.9%
STRIPE_FEE_FIXED_CENTS=30 # $0.30
Required: No (defaults provided) Used for: Revenue calculations and economics modeling
Web Project Environment Variables
The Next.js customer-facing website uses .env.local in the web/ directory.
# Backend API URL
NEXT_PUBLIC_API_URL=https://bookwishmonorepo-production.up.railway.app/v1
# Main app URL
NEXT_PUBLIC_APP_URL=https://www.bookwish.io
# Site URL (this project)
NEXT_PUBLIC_SITE_URL=https://wishlist.bookwish.io
# Stripe (for web checkout)
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_xxx
STRIPE_SECRET_KEY=sk_live_xxx
STRIPE_WEBHOOK_SECRET=whsec_xxx
Note: Variables prefixed with NEXT_PUBLIC_ are exposed to the browser.
Stores Project Environment Variables
The Next.js bookstore websites use .env.local in the stores/ directory.
# Backend API URL
NEXT_PUBLIC_API_URL=https://bookwishmonorepo-production.up.railway.app
# Main BookWish app URL
NEXT_PUBLIC_MAIN_APP_URL=https://bookwish.io
# Stores base URL (this project)
NEXT_PUBLIC_STORES_URL=https://bookwish.shop
# Stripe Bookstore subscription price ID
NEXT_PUBLIC_STRIPE_BOOKSTORE_PRICE_ID=price_...
Flutter App Configuration
The Flutter app uses Firebase for configuration. Environment-specific values are configured in:
app/lib/firebase_options.dart(generated from Firebase console)app/ios/Runner/GoogleService-Info.plistapp/android/app/google-services.json
API URL is hardcoded in the app or configured via build flavors (future enhancement).
Security Best Practices
Never Commit Secrets
Add to .gitignore:
.env
.env.local
.env.*.local
GoogleService-Info.plist
google-services.json
Use Strong Secrets
Generate secure random strings:
# For JWT secrets (hex encoding)
openssl rand -hex 32
# For encryption keys (base64 encoding)
openssl rand -base64 32
Environment-Specific Configuration
Use different values for:
- Development: Local services, test API keys
- Staging: Sandbox/test mode for payment providers
- Production: Production API keys, live mode
Validate Required Variables
The backend uses Zod schema validation (see backend/src/config/env.ts) to ensure all required variables are present at startup.
Development vs. Production
Development Defaults
NODE_ENV=development
PORT=3000
REDIS_URL=redis://localhost:6379
DATABASE_URL=postgresql://postgres:password@localhost:5432/bookwish
SQUARE_ENVIRONMENT=sandbox
Production Configuration
NODE_ENV=production
# Use hosted services (Supabase, Railway Redis)
# Use production API keys for Stripe, Square, etc.
# Enable all monitoring and error tracking
Troubleshooting
Missing Required Variables
If you see validation errors on startup:
Environment validation failed:
JWT_SECRET: String must contain at least 32 character(s)
Check that all required variables are set in .env and meet validation requirements.
Firebase Private Key Issues
If push notifications fail with authentication errors:
- Ensure the private key includes literal
\ncharacters in the.envfile - Verify the service account has Firebase Cloud Messaging permissions
- Check that the project ID and client email match your Firebase project
Database Connection Issues
Can't connect to database:
- Verify
DATABASE_URLformat - Check network access (Supabase IP allowlisting)
- Test with:
psql $DATABASE_URL
Next Steps
After configuring environment variables:
- Continue to Running Locally
- Check Troubleshooting for common issues