Skip to main content

Overview

SkillRise uses environment variables to configure database connections, authentication, payments, AI services, and media uploads. This guide walks you through setting up all required configuration.
Never commit .env files to version control. They contain sensitive credentials. Both server/.env and client/.env are already in .gitignore.

Backend Configuration

Create Server Environment File

1

Navigate to server directory

cd server
2

Create .env file

touch .env
3

Add environment variables

Open server/.env and add the following:
server/.env
# Database
MONGODB_URI=mongodb://localhost:27017

# Currency for payments (INR, USD, EUR, etc.)
CURRENCY=INR

# Clerk Authentication
CLERK_PUBLISHABLE_KEY=pk_test_...
CLERK_SECRET_KEY=sk_test_...
CLERK_WEBHOOK_SECRET=whsec_...

# Cloudinary Media Uploads
CLOUDINARY_NAME=your_cloud_name
CLOUDINARY_API_KEY=your_api_key
CLOUDINARY_SECRET_KEY=your_api_secret

# Razorpay Payments (for India)
RAZORPAY_KEY_ID=rzp_test_...
RAZORPAY_KEY_SECRET=your_key_secret
RAZORPAY_WEBHOOK_SECRET=whsec_...

# Groq AI (for chatbot and roadmap)
GROQ_CHATBOT_API_KEY=gsk_...

# Optional: Frontend URL (for CORS in production)
FRONTEND_URL=http://localhost:5173

# Optional: Server port
PORT=3000

Backend Environment Variables

Database Configuration

MONGODB_URI
string
required
MongoDB connection string.
MONGODB_URI=mongodb://localhost:27017
The database name SkillRise is automatically appended in configs/mongodb.js:7
CURRENCY
string
default:"INR"
Three-letter ISO currency code for payments (e.g., INR, USD, EUR).Used in:
  • server/controllers/userController.js:123
  • server/services/payments/razorpay.service.js:14

Clerk Authentication

1

Create a Clerk application

  1. Go to dashboard.clerk.com
  2. Click Create Application
  3. Choose Email and OAuth providers (Google, GitHub recommended)
  4. Click Create Application
2

Get API keys

From the Clerk dashboard:
  1. Go to API Keys in the sidebar
  2. Copy Publishable keyCLERK_PUBLISHABLE_KEY
  3. Copy Secret keyCLERK_SECRET_KEY
CLERK_PUBLISHABLE_KEY=pk_test_Y2xlcmsuZXhhbXBsZS5jb20k
CLERK_SECRET_KEY=sk_test_abcdefghijklmnopqrstuvwxyz123456
3

Configure webhook (for user sync)

SkillRise syncs Clerk users to MongoDB via webhooks.
  1. In Clerk dashboard, go to WebhooksAdd Endpoint
  2. Enter endpoint URL:
    • Local dev (with ngrok): https://your-ngrok-url.ngrok.app/clerk
    • Production: https://api.yourapp.com/clerk
  3. Select events: user.created, user.updated, user.deleted
  4. Click Create
  5. Copy Signing SecretCLERK_WEBHOOK_SECRET
CLERK_WEBHOOK_SECRET=whsec_abcdefghijklmnopqrstuvwxyz123456
To test webhooks locally:
# Install ngrok
npm install -g ngrok

# Start your server
npm run server

# In another terminal, create tunnel to port 3000
ngrok http 3000

# Copy the HTTPS URL (e.g., https://abc123.ngrok.app)
# Use this URL + /clerk in Clerk webhook settings
CLERK_PUBLISHABLE_KEY
string
required
Public API key for Clerk. Starts with pk_test_ (test) or pk_live_ (production).
CLERK_SECRET_KEY
string
required
Secret API key for Clerk. Starts with sk_test_ or sk_live_.
Keep this secret. Never expose in client-side code.
CLERK_WEBHOOK_SECRET
string
required
Signing secret for verifying webhook requests from Clerk. Starts with whsec_.Used in server/controllers/webhooks.js to verify request authenticity.

Cloudinary (Media Uploads)

1

Create Cloudinary account

  1. Go to cloudinary.com/users/register_free
  2. Sign up for a free account (25 GB storage, 25 GB bandwidth/month)
2

Get credentials

From the Cloudinary dashboard:
  1. Go to Dashboard (home page)
  2. Find Account Details section
  3. Copy:
    • Cloud NameCLOUDINARY_NAME
    • API KeyCLOUDINARY_API_KEY
    • API SecretCLOUDINARY_SECRET_KEY
CLOUDINARY_NAME=dxyz123abc
CLOUDINARY_API_KEY=123456789012345
CLOUDINARY_SECRET_KEY=abcdefghijklmnopqrstuvwxyz12
CLOUDINARY_NAME
string
required
Your Cloudinary cloud name (found on dashboard).
CLOUDINARY_API_KEY
string
required
API key for Cloudinary uploads.
CLOUDINARY_SECRET_KEY
string
required
API secret for signing Cloudinary requests.Used in server/configs/cloudinary.js:6 to configure the Cloudinary SDK.

Razorpay (Payment Processing)

For international users: Replace Razorpay with Stripe. See Payment Integration Guide for Stripe setup.
1

Create Razorpay account

  1. Go to dashboard.razorpay.com/signup
  2. Sign up (requires Indian phone number and business details)
  3. Complete KYC verification
2

Get API keys

From Razorpay dashboard:
  1. Go to SettingsAPI Keys
  2. Click Generate Test Key (for development)
  3. Copy:
    • Key IDRAZORPAY_KEY_ID
    • Key SecretRAZORPAY_KEY_SECRET
RAZORPAY_KEY_ID=rzp_test_ABC123XYZ456
RAZORPAY_KEY_SECRET=your_key_secret_here
Use Test Mode keys for development. Switch to Live Mode for production only after completing KYC.
3

Configure webhook

  1. Go to SettingsWebhooks
  2. Click Add New Webhook
  3. Enter webhook URL:
    • Local: https://your-ngrok-url.ngrok.app/razorpay
    • Production: https://api.yourapp.com/razorpay
  4. Select events: payment.captured, payment.failed
  5. Copy SecretRAZORPAY_WEBHOOK_SECRET
RAZORPAY_WEBHOOK_SECRET=whsec_razorpay_secret_key
RAZORPAY_KEY_ID
string
required
Razorpay API Key ID (starts with rzp_test_ or rzp_live_).Used in:
  • server/services/payments/razorpay.service.js:11
  • server/services/payments/razorpay.service.js:33
RAZORPAY_KEY_SECRET
string
required
Razorpay API Key Secret for server-side requests.
RAZORPAY_WEBHOOK_SECRET
string
required
Signing secret to verify webhook requests from Razorpay.Used in server/controllers/webhooks.js:45 to validate payment notifications.

Groq AI (Chatbot & Roadmap)

1

Get Groq API key

  1. Go to console.groq.com
  2. Sign in with Google or GitHub
  3. Click API Keys in sidebar
  4. Click Create API Key
  5. Copy the key (starts with gsk_)
GROQ_CHATBOT_API_KEY=gsk_abcdefghijklmnopqrstuvwxyz1234567890
GROQ_CHATBOT_API_KEY
string
required
Groq API key for AI chat and roadmap generation.Used in:
  • server/services/chatbot/aiChatbotService.js:3 - AI chatbot
  • Quiz generation
  • Learning roadmap generation
SkillRise uses the openai/gpt-oss-120b model by default. Groq offers generous free tier limits.

Optional Variables

FRONTEND_URL
string
default:"http://localhost:5173"
Frontend URL for CORS configuration.
# Development
FRONTEND_URL=http://localhost:5173

# Production
FRONTEND_URL=https://skillrise.com
Used in server/server.js:29 to configure CORS policy.
Required in production. Without this, API requests from the frontend will be blocked.
PORT
number
default:"3000"
Port for the Express server.
PORT=3000
Used in server/server.js:123 to start the HTTP server.
NODE_ENV
string
default:"development"
Node environment mode.
NODE_ENV=production
  • development - Enables verbose logging
  • production - Enforces FRONTEND_URL requirement

Frontend Configuration

Create Client Environment File

1

Navigate to client directory

cd client
2

Create .env file

touch .env
3

Add environment variables

Open client/.env and add:
client/.env
# Clerk Authentication (public key)
VITE_CLERK_PUBLISHABLE_KEY=pk_test_...

# Backend API URL
VITE_BACKEND_URL=http://localhost:3000

# Razorpay public key (optional - only if using Razorpay checkout)
VITE_RAZORPAY_KEY_ID=rzp_test_...

Frontend Environment Variables

VITE_CLERK_PUBLISHABLE_KEY
string
required
Clerk publishable key (same as backend CLERK_PUBLISHABLE_KEY).
VITE_CLERK_PUBLISHABLE_KEY=pk_test_Y2xlcmsuZXhhbXBsZS5jb20k
Used in:
  • client/src/main.jsx:6 - Initialize ClerkProvider
  • client/src/context/AppContext.jsx - Auth state
The VITE_ prefix is required for Vite to expose the variable to client code.
VITE_BACKEND_URL
string
required
Base URL for API requests.
# Development
VITE_BACKEND_URL=http://localhost:3000

# Production
VITE_BACKEND_URL=https://api.skillrise.com
Used in:
  • client/src/context/AppContext.jsx:23 - Axios instance base URL
  • client/src/hooks/useTimeTracker.js:12 - Analytics tracking
VITE_RAZORPAY_KEY_ID
string
Razorpay public key ID for client-side checkout (if using Razorpay).
VITE_RAZORPAY_KEY_ID=rzp_test_ABC123XYZ456
Only required if you’re implementing Razorpay embedded checkout in the frontend.

Verify Configuration

Before running the application, verify your configuration:
cd server

# Check .env file exists
ls -la .env

# Verify environment variables are loaded
node -e "require('dotenv').config(); console.log('MONGODB_URI:', process.env.MONGODB_URI ? '✓ Set' : '✗ Missing')"

Configuration Checklist

1

Backend environment

  • MONGODB_URI - Database connection string
  • CLERK_PUBLISHABLE_KEY - Clerk public key
  • CLERK_SECRET_KEY - Clerk secret key
  • CLERK_WEBHOOK_SECRET - Clerk webhook secret
  • CLOUDINARY_NAME - Cloudinary cloud name
  • CLOUDINARY_API_KEY - Cloudinary API key
  • CLOUDINARY_SECRET_KEY - Cloudinary API secret
  • RAZORPAY_KEY_ID - Razorpay key ID
  • RAZORPAY_KEY_SECRET - Razorpay key secret
  • RAZORPAY_WEBHOOK_SECRET - Razorpay webhook secret
  • GROQ_CHATBOT_API_KEY - Groq API key
2

Frontend environment

  • VITE_CLERK_PUBLISHABLE_KEY - Clerk public key
  • VITE_BACKEND_URL - Backend API URL
3

External services configured

  • Clerk webhook endpoint created
  • Razorpay webhook endpoint created
  • MongoDB database accessible
  • Cloudinary account active
Configuration complete! Proceed to run the application or set up Docker.

Environment Variable Reference

server/.env
# ─── Database ─────────────────────────────────────────────────────────────────
MONGODB_URI=mongodb://localhost:27017
CURRENCY=INR

# ─── Authentication ───────────────────────────────────────────────────────────
CLERK_PUBLISHABLE_KEY=pk_test_...
CLERK_SECRET_KEY=sk_test_...
CLERK_WEBHOOK_SECRET=whsec_...

# ─── Media Uploads ────────────────────────────────────────────────────────────
CLOUDINARY_NAME=your_cloud_name
CLOUDINARY_API_KEY=123456789012345
CLOUDINARY_SECRET_KEY=your_api_secret

# ─── Payments ─────────────────────────────────────────────────────────────────
RAZORPAY_KEY_ID=rzp_test_...
RAZORPAY_KEY_SECRET=your_key_secret
RAZORPAY_WEBHOOK_SECRET=whsec_...

# ─── AI Services ──────────────────────────────────────────────────────────────
GROQ_CHATBOT_API_KEY=gsk_...

# ─── Optional ─────────────────────────────────────────────────────────────────
FRONTEND_URL=http://localhost:5173
PORT=3000
NODE_ENV=development
client/.env
# ─── Authentication ───────────────────────────────────────────────────────────
VITE_CLERK_PUBLISHABLE_KEY=pk_test_...

# ─── API ──────────────────────────────────────────────────────────────────────
VITE_BACKEND_URL=http://localhost:3000

# ─── Payments (optional) ──────────────────────────────────────────────────────
VITE_RAZORPAY_KEY_ID=rzp_test_...

Troubleshooting

Symptom: undefined when accessing process.env.VARIABLE_NAMESolutions:
  1. Verify .env file exists in the correct directory (server/ or client/)
  2. Restart the dev server after changing .env
  3. For Vite (client), ensure variables start with VITE_
  4. Check for typos in variable names (they’re case-sensitive)
Error: Access to XMLHttpRequest at 'http://localhost:3000/api/...' from origin 'http://localhost:5173' has been blocked by CORS policySolutions:
  1. Set FRONTEND_URL=http://localhost:5173 in server/.env
  2. Verify VITE_BACKEND_URL=http://localhost:3000 in client/.env
  3. Restart both servers
Symptom: Login redirects to 404 or fails silentlySolutions:
  1. Verify CLERK_PUBLISHABLE_KEY matches in both server/.env and client/.env (as VITE_CLERK_PUBLISHABLE_KEY)
  2. Check Clerk dashboard → API Keys → ensure you’re using keys from the correct application
  3. Clear browser cookies and localStorage, then try again
Error: MongoServerError: Authentication failedSolutions:
  1. Verify MONGODB_URI is correct
  2. For Atlas: ensure your IP is whitelisted in Network Access
  3. For Atlas: verify database user credentials are correct
  4. For local: ensure MongoDB is running (brew services list or sudo systemctl status mongod)
Error: Invalid API keySolutions:
  1. Go to Cloudinary dashboard → verify cloud name, API key, and secret
  2. Ensure no extra spaces in .env values
  3. Restart the server after updating .env

Next Steps