Skip to main content

Environment Variables

This page is the canonical list of environment variables used across the codebase (backend, frontend, admin frontend, mobile apps). It is kept in sync with actual usage in code.

Backend Environment Variables

Create backend/.env file:

# Server Configuration
PORT=8080

# Database Configuration
DATABASE_URL=postgres://username:password@localhost:5432/filesharing?sslmode=disable

# JWT Authentication (must be 32+ characters in production)
JWT_SECRET=your-super-secret-jwt-key-at-least-32-characters-long

# CORS (required in production; comma-separated origins, no *)
# Development: leave unset for localhost defaults
ALLOWED_ORIGINS=https://yourapp.vercel.app,https://admin.yourapp.vercel.app

# Payment Gateway (Razorpay)
RAZORPAY_KEY_ID=rzp_test_xxxxxxxxxxxxx
RAZORPAY_KEY_SECRET=your_razorpay_secret_here
RAZORPAY_WEBHOOK_SECRET=your_webhook_secret_here
RAZORPAY_ENV=test # 'test' or 'live'

# Email Service (Resend API - Recommended)
RESEND_API_KEY=re_xxxxxxxxxxxxx
FROM_EMAIL=noreply@yourdomain.com
FROM_NAME=Qprint
FRONTEND_URL=http://localhost:3000

# Email Service (SMTP - Alternative)
# SMTP_HOST=smtp.resend.com
# SMTP_PORT=587
# SMTP_USER=your_smtp_user
# SMTP_PASSWORD=your_smtp_password

# File Storage
# Option 1: Local Storage (Default)
USE_LOCAL_STORAGE=true
UPLOADS_DIR=uploads

# Option 2: AWS S3 (Production)
# AWS_S3_BUCKET=your-bucket-name
# AWS_REGION=us-east-1
# AWS_ACCESS_KEY_ID=your_access_key
# AWS_SECRET_ACCESS_KEY=your_secret_key

# Production: set so test mode is disabled
ENVIRONMENT=development # 'development' or 'production'
TEST_MODE=false # Do not set true in production

# Optional: Restrict admin panel to specific IPs (comma-separated). Leave unset to allow all IPs.
# ALLOWED_ADMIN_IPS=1.2.3.4,5.6.7.8

# Optional: HTTPS directly on server (cert and key paths)
# TLS_CERT_FILE=/path/to/fullchain.pem
# TLS_KEY_FILE=/path/to/privkey.pem

# Optional: Shop auto-close sweeper (heartbeat + web activity)
# SHOP_SWEEPER_INTERVAL_SECONDS=60 # How often to run (default: 60)
# SHOP_APP_HEARTBEAT_TIMEOUT_MINUTES=12 # Close if app heartbeat older than this (default: 12)
# SHOP_WEB_ACTIVITY_TIMEOUT_MINUTES=25 # Close if web activity older than this (default: 25)

# Optional: Stuck-printing sweeper (revert "printing" → "uploaded" when shop heartbeat is stale, e.g. app crashed)
# SHOP_PRINTING_STALE_MINUTES=10 # Revert printing orders if no heartbeat for this many minutes (default: 10)
# SHOP_STUCK_PRINTING_INTERVAL_SECONDS # How often to run stuck-printing sweep (default: same as SHOP_SWEEPER_INTERVAL_SECONDS)

# Optional: Price per page (in rupees). Print cost = pages × copies × rate; rate depends on color_mode.
# COST_PER_PAGE_BW=1 # Black & white (default 1)
# COST_PER_PAGE_COLOR=10 # Colour (default 10)

# Optional: Auth cookie — set to true to disable setting auth cookie on login.
# When true, only requests with Authorization: Bearer <token> are authenticated;
# opening the API URL (e.g. /shops) in the browser will not send credentials (401).
# SKIP_AUTH_COOKIE=true

# Optional: Bypass sign-up email OTP (dev/test only). When true, POST /register does not require signup_token.
# SKIP_SIGNUP_OTP=true

# Optional: Referral (Refer & Earn) — see docs/development/referral-and-earn.md
# REFERRAL_BASE_URL=https://qprint.co.in
# REFERRAL_BONUS_REFERRER=50
# REFERRAL_BONUS_REFEREE=25
# REFERRAL_INVITE_MAX_PER_DAY=20
# REFERRAL_QUALIFY_DAYS=30
# REFERRAL_CAP_PER_REFERRER=100

# Optional: App download / shop redirect URLs (e.g. for QR or links)
# SHOP_REDIRECT_WEBSITE_URL=https://qprint.co.in
# ANDROID_APP_URL=https://play.google.com/store/apps/details?id=...
# IOS_APP_URL=https://apps.apple.com/app/...

# Optional: Support email (shown in app/emails)
# SUPPORT_EMAIL=support@qprint.co.in

# Optional: Behind reverse proxy (e.g. Render) — set so rate-limit uses X-Forwarded-For
# TRUST_PROXY_HEADERS=true

# Optional: Push notifications (FCM) — JSON path or inline JSON
# FIREBASE_SERVICE_ACCOUNT_JSON=/path/to/service-account.json
# GOOGLE_APPLICATION_CREDENTIALS=/path/to/credentials.json

# Optional: Debug/Logging
# LOG_LEVEL=debug # Set to 'debug' for verbose logging
# DEBUG=true # Alternative to LOG_LEVEL
# PAYMENT_LINK_EXPIRY_MINUTES=30 # Payment link expiry (default: 30)

Frontend Environment Variables

Create frontend/.env.local (optional, defaults to localhost:8080):

NEXT_PUBLIC_API_URL=http://localhost:8080

Note: Razorpay key is fetched from the backend during payment order creation, so no frontend Razorpay key is needed.

Admin Frontend Environment Variables

Create admin_frontend/.env.local:

NEXT_PUBLIC_API_URL=http://localhost:8080
# Optional: Main site URL for "Preview download page" link on App Download Links page
# NEXT_PUBLIC_MAIN_APP_URL=https://yourapp.vercel.app

Mobile Apps Configuration

Environment values for mobile apps are set at build time via --dart-define (not runtime .env).

Customer App (customer_app/)

Dart defineDescriptionExample
BASE_URLBackend API base URLhttps://qprint-72wr.onrender.com
MAPS_API_KEYGoogle Maps API key (optional; can use AndroidManifest/iOS plist)AIza...
CERT_PINSComma-separated SHA-256 cert pins for pinning (optional)-
  • Release builds: If BASE_URL is empty or localhost, the app uses the hardcoded productionBaseUrl in lib/config/app_config.dart. Override with --dart-define=BASE_URL=https://... for a different backend.
  • Debug: BASE_URL from dart-define or production default.
  • Example: flutter run --dart-define=BASE_URL=https://your-api.com
  • Google Maps can also be set in android/app/src/main/AndroidManifest.xml and iOS plist.

Shopkeeper App (shopkeeper_app/)

Dart defineDescription
BASE_URLBackend API base URL (same as customer app).

Example: flutter run --dart-define=BASE_URL=https://your-api.com

Environment Variable Reference

Required Variables

VariableDescriptionExample / Notes
DATABASE_URLPostgreSQL connection stringpostgres://user:pass@localhost:5432/db
JWT_SECRETSecret key for JWT tokens; must be 32+ charactersopenssl rand -base64 32
PORTBackend server port8080 (local), 10000 (Render)
ALLOWED_ORIGINSCORS allowed origins (production); comma-separatedhttps://yourapp.vercel.app (no * in production)

Optional Variables

VariableDescriptionDefault
ENVIRONMENTdevelopment or production; production disables test mode-
TEST_MODEBypass payment validation (do not use in production)false
RAZORPAY_KEY_IDRazorpay API key ID-
RAZORPAY_KEY_SECRETRazorpay API secret-
RAZORPAY_WEBHOOK_SECRETRequired for payment webhooks-
RESEND_API_KEYResend API key for emails-
FRONTEND_URLBase URL for password-reset links-
USE_LOCAL_STORAGEUse local file storagetrue
AWS_S3_BUCKET, AWS_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEYS3 file storage-
TLS_CERT_FILE, TLS_KEY_FILEPaths to TLS cert and key for HTTPS on server-
SHOP_SWEEPER_INTERVAL_SECONDSInterval (seconds) for shop auto-close sweeper60
SHOP_APP_HEARTBEAT_TIMEOUT_MINUTESAuto-close shop if app heartbeat older than this12
SHOP_WEB_ACTIVITY_TIMEOUT_MINUTESAuto-close shop if web activity older than this25
COST_PER_PAGE_BWPrice per page for black & white (rupees). Invalid or negative → 1.1
COST_PER_PAGE_COLORPrice per page for colour (rupees). Invalid or negative → 10.10
SKIP_AUTH_COOKIEIf true, do not set auth cookie on login; only Bearer token auth is accepted (prevents direct API URL access in browser)-
SKIP_SIGNUP_OTPIf true, POST /register does not require signup_token (bypass email verification). Use only in dev/test.-
RAZORPAY_ENVRazorpay mode: test or live (must match key type)-
PAYMENT_LINK_EXPIRY_MINUTESPayment link/order expiry in minutes30
REFERRAL_BASE_URLBase URL for referral links (e.g. https://qprint.co.in)-
REFERRAL_BONUS_REFERRERBonus (₹) to referrer when referee qualifies50
REFERRAL_BONUS_REFEREEWelcome bonus (₹) to referee25
REFERRAL_INVITE_MAX_PER_DAYMax invite emails per referrer per 24h20
REFERRAL_QUALIFY_DAYSDays after signup within which referee must qualify (omit = no limit)-
REFERRAL_CAP_PER_REFERRERMax credited referrals per referrer lifetime (omit = no cap)-
SHOP_REDIRECT_WEBSITE_URLWebsite URL for shop redirect / QR-
ANDROID_APP_URLPlay Store URL for app download links-
IOS_APP_URLApp Store URL for app download links-
SUPPORT_EMAILSupport email shown in app or emails-
TRUST_PROXY_HEADERSIf true, use X-Forwarded-For for client IP (e.g. behind Render)-
FIREBASE_SERVICE_ACCOUNT_JSONPath or JSON string for FCM (push notifications)-
GOOGLE_APPLICATION_CREDENTIALSFallback path for FCM credentials-
LOG_LEVELSet to debug for verbose logging-
DEBUGSet to true for debug logging (alternative to LOG_LEVEL)-
ALLOWED_ADMIN_IPSComma-separated IPs allowed for admin panel (optional; omit to allow all)-

Security Notes

  • Never commit .env files to version control
  • JWT_SECRET must be at least 32 characters in production (server will not start otherwise)
  • ALLOWED_ORIGINS must be set in production to your real frontend URL(s); no default *
  • Set ENVIRONMENT=production on production hosts (e.g. Render)
  • Keep API keys and secrets secure; use different values for development and production
  • Consider using secret management services in production