Skip to main content
Courser is fully open source. You can self-host both the Express backend and the Next.js frontend on any infrastructure you control. This guide walks through everything you need to get a working deployment.

Architecture overview

A Courser deployment consists of two applications and several external services:
ComponentTechnologyRole
BackendNode.js + ExpressAPI server, business logic, vector ingestion
FrontendNext.js 13 + Tailwind CSSProfessor dashboard, student chat interface
DatabaseMongoDBUser accounts, course metadata, chatbot config
Vector databasePineconeStores lecture embeddings for semantic search
AI / LLMOpenAIEmbeddings (text-embedding-ada-002) and chat (gpt-3.5-turbo-16k)
AuthFirebase + JWTGoogle OAuth and email/password sign-in
File storageCloudinaryBackground image uploads for chatbot customization

Prerequisites

Before you start, make sure you have the following:
The backend and frontend both require Node.js. Download it from nodejs.org or use a version manager like nvm.
node --version   # should print v18.x.x or higher
npm --version
You need a running MongoDB database. The easiest option is a free MongoDB Atlas cluster, which gives you a hosted connection string. You can also run MongoDB locally.Have your connection string (the MONGO_URI) ready before proceeding.
Courser stores lecture embeddings in Pinecone. You need a free or paid Pinecone account.The index name is hardcoded in the source as courser. You must create an index with that exact name in your Pinecone project. Use the following settings when creating it:
  • Index name: courser
  • Dimensions: 1536 (matches OpenAI text-embedding-ada-002)
  • Metric: cosine
Copy your Pinecone API key from the Pinecone console.
Courser uses OpenAI for both embeddings and chat completions. You need an OpenAI API key with access to:
  • text-embedding-ada-002
  • gpt-3.5-turbo-16k
This key is used as the platform default. Professors can optionally supply their own key per course.
Courser uses Firebase Authentication for Google OAuth and email/password sign-in.
  1. Create a new project in the Firebase console.
  2. Enable Authentication and turn on the Google and Email/Password providers.
  3. Copy your Firebase project configuration object (found in Project Settings → Your apps → Web app).
  4. Replace the firebaseConfig object in endpoints/auth.js with your own config.
Courser uses Cloudinary to store chatbot background images uploaded by professors.Create a free Cloudinary account and copy your CLOUDINARY_URL from the dashboard. It has the format cloudinary://API_KEY:API_SECRET@CLOUD_NAME.

Setup

1

Clone the repository

git clone https://github.com/GautamSharda/courser.git
cd courser
2

Install backend dependencies

From the repository root:
npm install
3

Install frontend dependencies

npm install --prefix client
Or navigate into the client directory and run npm install there.
4

Configure environment variables

Create a .env file in the repository root with all required backend variables:
MONGO_URI=mongodb+srv://user:[email protected]/courser
OPENAI_API_KEY=sk-...
PINECONE_API_KEY=pcsk_...
JWT_PRIVATE_KEY=your-long-random-secret
CLOUDINARY_URL=cloudinary://api_key:api_secret@cloud_name
PORT=8000
For the full variable reference, see Environment variables.For the frontend, create a .env.local file in the client directory:
NEXT_PUBLIC_API_URL=http://localhost:8000
5

Set up your Pinecone index

In the Pinecone console, create a new index with these settings:
  • Name: courser
  • Dimensions: 1536
  • Metric: cosine
The index name courser is hardcoded in classes/CourserAIAssistant.js. If you use a different name, you must update the INDEX constant in that file.
6

Update the Firebase config

Open endpoints/auth.js and replace the firebaseConfig object with the configuration from your own Firebase project:
const firebaseConfig = {
    apiKey: "YOUR_API_KEY",
    authDomain: "YOUR_PROJECT.firebaseapp.com",
    projectId: "YOUR_PROJECT_ID",
    storageBucket: "YOUR_PROJECT.appspot.com",
    messagingSenderId: "YOUR_SENDER_ID",
    appId: "YOUR_APP_ID",
};
You can find this object in the Firebase console under Project Settings → Your apps → Web app → SDK setup and configuration.
7

Update CORS origins

The backend currently allows requests only from these origins:
// app.js
app.use(cors({
  credentials: true,
  origin: [
    "http://localhost:3000",
    "https://courser-beta.vercel.app",
    "https://chatcourser.com"
  ]
}));
If you deploy the frontend to a custom domain, add it to this array in app.js. Requests from unlisted origins will be blocked by the browser.
8

Start the backend

From the repository root:
npm start
This runs node app.js. The server listens on the port defined by the PORT environment variable, or 8000 if PORT is not set.
🚀 Running the server on 8000
9

Start the frontend

In a separate terminal, from the client directory:
npm run dev
The frontend runs on http://localhost:3000.
npm run dev starts a development server with hot reload. For production, run npm run build followed by npm start inside the client directory.

CORS configuration

The CORS allowlist in app.js is hardcoded. For a self-hosted deployment on a custom domain, you must update it before going to production:
// app.js — update this list to include your frontend domain
app.use(cors({
  credentials: true,
  origin: [
    "http://localhost:3000",       // keep for local development
    "https://your-frontend.com",  // add your production domain
  ]
}));
If you do not update this list, browsers will block API requests from your frontend domain due to the CORS policy.

Production deployment

Do not set NODE_ENV=production until you have verified that all environment variables are set in the host environment. When NODE_ENV is production, the backend skips loading .env via dotenv and expects variables to be injected directly by the host.
Any Node.js host works: Railway, Render, Fly.io, a VPS, or your own server. Recommended steps:
  1. Set all environment variables in your host’s dashboard or secret manager.
  2. Set NODE_ENV=production.
  3. Run npm start as the start command.
  4. Expose the port defined by PORT (or 8000).
  5. Update the CORS allowlist in app.js to include your frontend domain.
The Next.js frontend can be deployed to Vercel, Netlify, or any Node-capable host.
  1. Set NEXT_PUBLIC_API_URL to your production backend URL.
  2. Run npm run build as the build command.
  3. Run npm start as the start command.
For Vercel deployments, the build and start commands are detected automatically.
Use MongoDB Atlas for a managed production database. Make sure your backend host’s IP is in the Atlas network access allowlist, or set it to allow all IPs (0.0.0.0/0) for simplicity.
For VPS deployments, use a process manager like pm2 to keep the backend running and restart it on crashes:
npm install -g pm2
pm2 start app.js --name courser-backend
pm2 save
pm2 startup

What’s next

Environment variables

Full reference for every backend and frontend environment variable

API reference

Explore the REST API exposed by the backend

Build docs developers (and LLMs) love