Skip to main content

Overview

FitAiid requires several environment variables for backend services, external APIs, and authentication. This guide explains each variable and how to obtain the necessary credentials.
Security Notice: Never commit .env files to Git. Always use platform-specific environment variable managers (Railway, Vercel) for production secrets.

Environment File Template

Use this template to create your .env file during local development:
# =============================================
# SERVER CONFIGURATION
# =============================================
PORT=5000
NODE_ENV=development

# =============================================
# DATABASE - MONGODB ATLAS
# =============================================
MONGODB_URI=mongodb+srv://username:[email protected]/FitAiid?retryWrites=true&w=majority

# =============================================
# AUTHENTICATION - JWT
# =============================================
JWT_SECRET=your-super-secure-jwt-secret-minimum-32-characters-long
JWT_EXPIRE=7d

# =============================================
# FRONTEND URLs
# =============================================
FRONTEND_URL=http://localhost:3000
FRONTEND_PROD_URL=https://fitaiid.vercel.app

# =============================================
# FIREBASE ADMIN SDK
# =============================================
FIREBASE_PROJECT_ID=your-project-id
FIREBASE_PRIVATE_KEY=-----BEGIN PRIVATE KEY-----\nYourKeyHere\n-----END PRIVATE KEY-----
FIREBASE_CLIENT_EMAIL=[email protected]
FIREBASE_DATABASE_URL=https://your-project.firebaseio.com

# =============================================
# OPENAI API (Workout Generation)
# =============================================
OPENAI_API_KEY=sk-proj-xxxxxxxxxxxxxxxxxxxxxxxxxxxx

# =============================================
# GOOGLE OAUTH (Sign-in with Google)
# =============================================
GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your-google-oauth-secret

# =============================================
# STRIPE (Payment Processing)
# =============================================
STRIPE_PUBLIC_KEY=pk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
STRIPE_SECRET_KEY=sk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
STRIPE_WEBHOOK_SECRET=whsec_xxxxxxxxxxxxxxxxxxxxxxxxxxxx

# =============================================
# EMAIL (Nodemailer)
# =============================================
EMAIL_SERVICE=gmail
EMAIL_USER=[email protected]
EMAIL_PASSWORD=your-gmail-app-password
EMAIL_FROM=[email protected]

# =============================================
# WEB PUSH NOTIFICATIONS (VAPID Keys)
# =============================================
VAPID_PUBLIC_KEY=BH5NRoA1tucvywFDHTef...
VAPID_PRIVATE_KEY=iYatNX1EcokCuw3ZNs4dg...
VAPID_EMAIL=mailto:[email protected]

# =============================================
# SENTRY (Error Tracking - Optional)
# =============================================
SENTRY_DSN=https://[email protected]/xxxxxxx

# =============================================
# LOGGING
# =============================================
LOG_LEVEL=debug
LOG_DIR=./logs

# =============================================
# RATE LIMITING
# =============================================
RATE_LIMIT_WINDOW_MS=900000
RATE_LIMIT_MAX_REQUESTS=100

# =============================================
# CORS ORIGINS (comma-separated)
# =============================================
CORS_ORIGINS=http://localhost:3000,http://localhost:3001,https://fitaiid.vercel.app

Variable Reference

Server Configuration

Description: Port number for the Express serverDefault: 5000Usage:
const PORT = process.env.PORT || 5000;
app.listen(PORT);
Railway automatically assigns a port, but FitAiid defaults to 5000 if not specified.
Description: Application environment modeOptions: development | production | testUsage:
  • Controls logging verbosity
  • Enables/disables error stack traces
  • Affects database connection pooling
if (process.env.NODE_ENV === 'development') {
  console.log('Debug information');
}

Database Configuration

Description: Complete connection string for MongoDB Atlas clusterFormat:
mongodb+srv://username:[email protected]/FitAiid?retryWrites=true&w=majority
How to Obtain:
1

Create MongoDB Atlas Account

2

Create Free Cluster

  • Click “Build a Database”
  • Select M0 (Free) tier
  • Choose a cloud provider and region
  • Name your cluster: Cluster0
3

Create Database User

  • Go to Database Access → Add New Database User
  • Choose Password authentication
  • Username: fitaiid_admin
  • Generate strong password
  • Database User Privileges: Atlas Admin
4

Whitelist IPs

  • Go to Network Access → Add IP Address
  • For Railway/production: 0.0.0.0/0 (all IPs)
  • For local dev: Click “Add Current IP Address”
5

Get Connection String

  • Go to Databases → Click “Connect”
  • Choose “Connect your application”
  • Driver: Node.js, Version: 4.1 or later
  • Copy the connection string:
mongodb+srv://fitaiid_admin:<password>@cluster0.xxxxx.mongodb.net/?retryWrites=true&w=majority
  • Replace <password> with your actual password
  • Add /FitAiid before the ? to specify database name:
mongodb+srv://fitaiid_admin:[email protected]/FitAiid?retryWrites=true&w=majority
If your password contains special characters (@, :, /, etc.), you must URL-encode them:
  • @%40
  • :%3A
  • /%2F

Authentication & Security

Description: Secret key for signing JSON Web TokensRequirements:
  • Minimum 32 characters
  • Use random, unpredictable string
  • Never share or commit to Git
Generate:
# Option 1: OpenSSL
openssl rand -base64 32

# Option 2: Node.js
node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"

# Example output:
# TechStore_Super_Secret_Key_2025_abcdef123456
Usage:
const token = jwt.sign({ userId: user._id }, process.env.JWT_SECRET, {
  expiresIn: process.env.JWT_EXPIRE
});
Description: Token expiration timeFormat: String with units (7d, 24h, 60m, 3600s)Recommended:
  • Development: 7d (7 days)
  • Production: 24h (24 hours)
  • High-security: 15m (15 minutes with refresh tokens)
Example:
JWT_EXPIRE=24h

Firebase Admin SDK

Description: Firebase Admin SDK credentials for server-side authenticationHow to Obtain:
1

Create Firebase Project

  1. Go to Firebase Console
  2. Click “Add Project”
  3. Name: FitAiid
  4. Enable Google Analytics (optional)
2

Generate Service Account Key

  1. Go to Project Settings (gear icon) → Service Accounts
  2. Click “Generate New Private Key”
  3. Confirm and download the JSON file
  4. IMPORTANT: Never commit this file to Git
3

Extract Credentials

Open the downloaded JSON file and extract these values:
{
  "type": "service_account",
  "project_id": "fitaiid-12345",
  "private_key_id": "abc123...",
  "private_key": "-----BEGIN PRIVATE KEY-----\nMIIE...\n-----END PRIVATE KEY-----\n",
  "client_email": "[email protected]",
  "client_id": "123456789",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/..."
}
4

Configure Environment Variables

Option 1: Individual Variables (Local Dev)
FIREBASE_PROJECT_ID=fitaiid-12345
FIREBASE_PRIVATE_KEY=-----BEGIN PRIVATE KEY-----\nMIIE...\n-----END PRIVATE KEY-----
FIREBASE_CLIENT_EMAIL=[email protected]
Option 2: Full JSON (Railway/Production)
FIREBASE_ADMIN_SDK={"type":"service_account","project_id":"fitaiid-12345",...}
5

Initialize in Code

const admin = require('firebase-admin');

// Option 1: From individual env vars
admin.initializeApp({
  credential: admin.credential.cert({
    projectId: process.env.FIREBASE_PROJECT_ID,
    privateKey: process.env.FIREBASE_PRIVATE_KEY.replace(/\\n/g, '\n'),
    clientEmail: process.env.FIREBASE_CLIENT_EMAIL
  })
});

// Option 2: From JSON string
const serviceAccount = JSON.parse(process.env.FIREBASE_ADMIN_SDK);
admin.initializeApp({
  credential: admin.credential.cert(serviceAccount)
});
The private key contains newline characters (\n). In Railway/Vercel, paste the entire JSON as one line. In local .env, escape newlines properly.

External APIs

Description: OpenAI API key for generating personalized workout routinesHow to Obtain:
1

Create OpenAI Account

2

Add Payment Method

Go to Billing → Add payment method (required for API access)
3

Create API Key

  1. Go to API Keys
  2. Click “Create new secret key”
  3. Name: FitAiid Production
  4. Copy the key immediately (you won’t see it again)
Format:
OPENAI_API_KEY=sk-proj-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Usage in Code:
const { OpenAI } = require('openai');

const openai = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY
});

const completion = await openai.chat.completions.create({
  model: "gpt-4",
  messages: [{ role: "user", content: "Generate a workout plan..." }]
});
Pricing:
  • GPT-3.5 Turbo: ~$0.002 per 1K tokens
  • GPT-4: ~$0.03 per 1K tokens
Start with GPT-3.5 Turbo for cost-effective testing, upgrade to GPT-4 for better workout generation quality.
Description: Stripe API keys for handling subscriptions and paymentsHow to Obtain:
1

Create Stripe Account

Sign up at stripe.com
2

Get API Keys

  1. Go to API Keys
  2. Note your Publishable key (starts with pk_)
  3. Click “Reveal test key” to see Secret key (starts with sk_)
3

Create Webhook

  1. Go to Webhooks
  2. Click “Add endpoint”
  3. Endpoint URL: https://your-api.railway.app/api/webhooks/stripe
  4. Events to listen: checkout.session.completed, payment_intent.succeeded
  5. Copy the Signing secret (starts with whsec_)
Environment Variables:
STRIPE_PUBLIC_KEY=pk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
STRIPE_SECRET_KEY=sk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
STRIPE_WEBHOOK_SECRET=whsec_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
Usage:
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);

const session = await stripe.checkout.sessions.create({
  payment_method_types: ['card'],
  line_items: [{
    price_data: {
      currency: 'usd',
      product_data: { name: 'Premium Subscription' },
      unit_amount: 2999 // $29.99
    },
    quantity: 1
  }],
  mode: 'subscription',
  success_url: 'https://fitaiid.com/success',
  cancel_url: 'https://fitaiid.com/cancel'
});
Test vs Production Keys:
  • Development: Use pk_test_ and sk_test_ keys
  • Production: Switch to pk_live_ and sk_live_ keys
  • Never commit live keys to Git
Description: Gmail SMTP credentials for sending emails (password resets, notifications)How to Obtain App Password:
1

Enable 2-Factor Authentication

  1. Go to Google Account Security
  2. Enable 2-Step Verification (required for app passwords)
2

Generate App Password

  1. Go to App Passwords
  2. Select app: Mail
  3. Select device: Other (Custom name)
  4. Enter name: FitAiid Backend
  5. Click Generate
  6. Copy the 16-character password (spaces will be removed)
Environment Variables:
EMAIL_SERVICE=gmail
EMAIL_USER=[email protected]
EMAIL_PASSWORD=abcdefghijklmnop  # 16-char app password
EMAIL_FROM=[email protected]
Usage:
const nodemailer = require('nodemailer');

const transporter = nodemailer.createTransport({
  service: process.env.EMAIL_SERVICE,
  auth: {
    user: process.env.EMAIL_USER,
    pass: process.env.EMAIL_PASSWORD
  }
});

await transporter.sendMail({
  from: process.env.EMAIL_FROM,
  to: user.email,
  subject: 'Welcome to FitAiid!',
  html: '<h1>Welcome!</h1>'
});
For production, consider using a dedicated email service like SendGrid or AWS SES for better deliverability and analytics.
Description: VAPID (Voluntary Application Server Identification) keys for sending push notificationsGenerate VAPID Keys:
# Install web-push globally
npm install -g web-push

# Generate VAPID keys
web-push generate-vapid-keys
Output:
=======================================
Public Key:
BH5NRoA1tucvywFDHTef...

Private Key:
iYatNX1EcokCuw3ZNs4dg...
=======================================
Environment Variables:
VAPID_PUBLIC_KEY=BH5NRoA1tucvywFDHTef...
VAPID_PRIVATE_KEY=iYatNX1EcokCuw3ZNs4dg...
VAPID_EMAIL=mailto:[email protected]
Usage (Backend):
const webpush = require('web-push');

webpush.setVapidDetails(
  process.env.VAPID_EMAIL,
  process.env.VAPID_PUBLIC_KEY,
  process.env.VAPID_PRIVATE_KEY
);

await webpush.sendNotification(subscription, JSON.stringify({
  title: 'Workout Reminder',
  body: 'Time for your leg day workout!',
  icon: '/img/icon-192.png'
}));
Usage (Frontend):
// Subscribe to push notifications
const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.subscribe({
  userVisibleOnly: true,
  applicationServerKey: 'BH5NRoA1tucvywFDHTef...' // VAPID_PUBLIC_KEY
});
VAPID keys are unique to your application. Generate once and use the same keys across all environments.

Optional Services

Description: Sentry DSN for error monitoring and trackingHow to Obtain:
1

Create Sentry Account

Sign up at sentry.io
2

Create Project

  1. Click “Create Project”
  2. Platform: Node.js
  3. Name: FitAiid Backend
3

Get DSN

Copy the DSN from the setup page:
https://[email protected]/7890123
Environment Variable:
SENTRY_DSN=https://[email protected]/7890123
Usage:
const Sentry = require('@sentry/node');

Sentry.init({ dsn: process.env.SENTRY_DSN });

// Capture exceptions
try {
  // your code
} catch (error) {
  Sentry.captureException(error);
}
Sentry’s free tier includes 5K errors/month, perfect for staging environments.

Railway Configuration

Add all environment variables in Railway Dashboard:
1

Open Railway Project

Navigate to your deployed backend project
2

Variables Tab

Click on the Variables tab
3

Add Each Variable

Click “New Variable” and add:
  • Variable name (e.g., MONGODB_URI)
  • Variable value
  • Click “Add”
Repeat for all 20+ variables
4

Redeploy

Railway automatically redeploys when variables are added/changed
For FIREBASE_ADMIN_SDK, paste the entire JSON object as a single-line string (remove all newlines within the JSON).

Vercel Configuration

Vercel only needs the backend API URL:
VITE_API_URL=https://fitaiid-api.railway.app
1

Project Settings

Go to Vercel project → Settings → Environment Variables
2

Add Variable

  • Key: VITE_API_URL
  • Value: Your Railway backend URL
  • Environment: Production, Preview, Development
3

Redeploy

Trigger a new deployment to apply changes

Security Best Practices

Never Commit Secrets

Add .env to .gitignore to prevent accidental commits of sensitive data.

Use Strong Secrets

Generate cryptographically random secrets with minimum 32 characters.

Rotate Keys Regularly

Change API keys and secrets every 90 days, especially after team member changes.

Use Environment-Specific Keys

Use test keys for development, production keys only in production.

Validation Checklist

Before deploying, verify all variables are set:
1

Local Development

# Test locally first
npm run dev

# Verify logs show:
# ✅ MongoDB Atlas connected
# ✅ Server running on port 5000
2

Railway Production

Check Railway deployment logs for:
  • ✅ All variables loaded
  • ✅ No “undefined” errors
  • ✅ MongoDB connected
  • ✅ Server started successfully
3

Test API Endpoints

# Test authentication
curl https://fitaiid-api.railway.app/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"[email protected]","password":"Admin1234"}'

# Should return JWT token

Troubleshooting

Symptom: process.env.VARIABLE_NAME is undefinedCauses:
  1. Variable not added to Railway
  2. Typo in variable name
  3. Railway not redeployed after adding variable
Solution:
  1. Double-check variable exists in Railway Variables tab
  2. Verify exact spelling (case-sensitive)
  3. Click “Redeploy” in Railway
Symptom: MongoNetworkError: connection timed outCauses:
  1. IP not whitelisted in MongoDB Atlas
  2. Incorrect connection string
  3. Special characters not URL-encoded
Solution:
  1. Add 0.0.0.0/0 to MongoDB Atlas Network Access
  2. Verify connection string format
  3. URL-encode special characters in password
Symptom: Error: Firebase credential errorCauses:
  1. Invalid JSON format in FIREBASE_ADMIN_SDK
  2. Newlines not properly escaped
  3. Missing quotes in JSON
Solution:
  1. Copy entire JSON from Firebase console
  2. Remove all newlines and extra spaces
  3. Ensure valid JSON syntax (use JSONLint to validate)

Environment Variables Summary

VariableRequiredServiceNotes
PORTYesServerDefault: 5000
NODE_ENVYesServerproduction/development
MONGODB_URIYesDatabaseMongoDB Atlas connection
JWT_SECRETYesAuthMin 32 chars
JWT_EXPIREYesAuthe.g., 24h, 7d
FIREBASE_ADMIN_SDKYesAuthFull JSON or individual vars
OPENAI_API_KEYYesAIStarts with sk-proj-
STRIPE_SECRET_KEYYesPaymentsStarts with sk_
STRIPE_WEBHOOK_SECRETYesPaymentsStarts with whsec_
EMAIL_USERYesEmailGmail address
EMAIL_PASSWORDYesEmailGmail app password
VAPID_PUBLIC_KEYYesPushWeb Push public key
VAPID_PRIVATE_KEYYesPushWeb Push private key
VAPID_EMAILYesPushmailto:email@domain
CORS_ORIGINSYesSecurityComma-separated URLs
SENTRY_DSNNoMonitoringOptional error tracking

Next Steps

With all environment variables configured, your deployment is complete!

Back to Deployment Overview

Review the complete deployment architecture and verify your setup.

Build docs developers (and LLMs) love