This document describes the current NUSMods deployment model.
NUSMods is deployed as two parts:
- Website + export endpoints on Vercel.
- Self-managed data pipeline (scraper + static API data hosting, plus search infra).
The website (nusmods.com) and export service are deployed via Vercel.
- Website config:
website/vercel.json - Export config:
export/vercel.json
Operational flow:
- Push a branch / open a PR to get a preview deployment.
- Merge to the production branch configured in Vercel.
- Validate critical flows after deploy:
- module search
- timetable rendering
- timetable export (PNG/PDF)
- error reporting
For local production-like verification:
cd website
pnpm build
npx serve -s distUse this section if you operate scraper/data infrastructure outside Vercel.
- Ubuntu LTS
- Node 22 LTS
- pnpm
- PM2
- Nginx (for static API data serving)
sudo apt update && sudo apt upgrade -y
sudo apt install -y git nginx curl build-essentialInstall Node 22 LTS and pnpm using your standard team method (nvm, fnm, or distro policy), then verify:
node -v
pnpm -vInstall PM2 globally:
pnpm add -g pm2
pm2 -vgit clone https://github.com/nusmodifications/nusmods.git
cd nusmods
pnpm installIn scrapers/nus-v2:
cd scrapers/nus-v2
cp env.example.json env.json
# fill in env.json with required internal API credentials / endpoints
pnpm dev test | pnpm bunyan
pnpm build
pm2 start ecosystem.config.js
pm2 save
pm2 startup systemdNotes:
- Scraper production scripts are defined in
scrapers/nus-v2/package.json. - PM2 config is in
scrapers/nus-v2/ecosystem.config.js. - ElasticSearch config is optional for local development, but required for production search.
The API static JSON data directory is typically served as api.nusmods.com.
- Place generated data under your chosen path (for example,
/home/<user>/api.nusmods.com). - Configure an Nginx server block to serve that directory.
- Enable and restart Nginx:
sudo systemctl enable nginx
sudo systemctl restart nginx- Validate permissions for all parent directories and files.
- Point DNS to this host and verify public access.
cd /path/to/nusmods
git pull
pnpm install
cd scrapers/nus-v2
pnpm build
pm2 restart ecosystem.config.jsRun a scraper health check after restart:
pnpm dev test | pnpm bunyan