NUSMods and the timetable problem it solves for one university
🏫 Official course planning platform for National University of Singapore.
At a glance
- What is it?
- NUSMods is a student-run course catalogue, module search and timetable builder for the National University of Singapore, with a public v2 API and a separate export service behind the site. It is a well-targeted tool with a narrow remit and a thin release history.
- Who is it for?
- NUSMods is worth adopting for NUS students and for developers who want a ready-made course dataset for that one university, because the catalogue, the v2 API and the export service already cover the hard part of the problem. It is the wrong choice for any other institution and for teams that need a documented API contract, a release history to pin against, or a native mobile app.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 3 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Course planning at NUS is a scheduling problem, not a browsing problem
NUSMods exists because choosing modules at the National University of Singapore is a constraint problem wearing the clothes of a catalogue. Module information is spread across university systems, and the question a student actually needs answered is whether a particular set of courses can be fitted into a weekly timetable without clashing. The project presents itself as the open source college course catalogue, module search and timetable builder for NUS, and it states that the team assists over 30,000 students every semester with timetable planning and module selection. That figure comes from the project's own description rather than an independent count, but it indicates the scale a student-run team is aiming at. The audience is narrow and easy to name: NUS undergraduates and alumni who need course data and a workable schedule, plus developers who want that data in their own tools.
Two separate services carry the data side of the product
Programmatic access comes in two shapes. For anyone who needs the underlying information, the project runs a public API whose documentation lives at https://api.nusmods.com/v2/, and the README points there for retrieving course details. Getting a finished timetable out of the site is handled by a different service entirely, the timetable export service at https://export.nusmods.com/. Keeping those apart is a deliberate split: the catalogue is meant to be queried and scripted against, while the export path is a purpose-built companion rather than a mode flag on the main endpoint. One detail is worth noting for anyone automating against it. The documentation asks users to be considerate and use these services responsibly, which reads as a request to limit request volume rather than a statement of an enforced quota. No API key, rate limit number or authentication requirement appears anywhere in the project's own guidance, so a programmatic consumer is building on an undocumented contract.
Local setup lives in website/README.md, not in the root package.json
The root of the repository does not contain the setup steps. Contributors are sent to website/README.md to run the website locally, and to ARCHITECTURE.md for a description of how the various projects in the repository fit together. What the root package.json does contain is the shape of a workspace coordinator: it is marked private, it wires up Husky on install, it defines the formatter, and it pins the package manager.
{
"name": "nusmods-root",
"private": true,
"scripts": {
"prepare": "husky",
"format": "oxfmt",
"format:check": "oxfmt --check"
},
"engines": {
"node": ">=22"
},
"packageManager": "[email protected]"
}Two facts follow from those few lines. Node 22 or newer is required, and pnpm 10.30.3 is the declared package manager, which is consistent with the pnpm-lock.yaml and pnpm-workspace.yaml files sitting at the top of the tree. There is no dev or start script here, so the commands that actually launch the site live in the per-package manifests instead. A reader who expects one start command at the top of the project will not find it, and that is the main adjustment the layout asks of newcomers.
scrapers/, export/ and website/ explain the shape of the deployment
The top-level entry list makes the structure legible. A pnpm workspace holds the packages/ directory, and three sibling directories carry most of the weight: scrapers/, export/ and website/, with infra/ for deployment configuration and misc/ for assets such as the light and dark mode timetable screenshots the README displays. The name of the scrapers/ directory indicates that course data is gathered from upstream university sources rather than typed in by hand, and the presence of a standalone export/ package lines up with the export service running at export.nusmods.com. Ingestion, export and presentation are therefore separate deployables that happen to share one repository, which is the clearest architectural signal available to a reader. The root also holds MAINTENANCE.md, DEPLOYMENT.md, CONTRIBUTING.md and ARCHITECTURE.md, so operational and contributor guidance lives in the tree itself rather than only on an external wiki. AGENTS.md and CODE_OF_CONDUCT.md sit alongside them.
Branch deploys on Vercel turn pull requests into testable previews
The site runs on Vercel, which the project credits with hosting the website and automatically deploying branches so incoming pull requests can be tested in the browser without a reviewer installing anything. That preview capability is the main reason the repository can accept contributions from people who have never set the stack up locally. Around it sit the usual quality gates: a .circleci/ directory for continuous integration, codecov.yml for coverage reporting, and a .husky/ directory paired with lint-staged configuration so that oxfmt rewrites staged JavaScript, TypeScript, JSON and Markdown before a commit lands. renovate.json indicates that dependency updates arrive as automated pull requests. The README also lists BrowserStack as a sponsor for testing on real devices including older iPhone Safari, and 1Password for managing shared account credentials. There is a .dockerignore at the root and an infra/ directory, so container based pieces exist, although no docker compose file or self-hosted deployment path is described in the project's documentation.
A single 2018 test release sits above a much more recent push
The version history is the weakest signal in this project, and engineers should read it carefully. The listed release history contains one tag, 20181226-242eb46, labelled Test Release and dated 2018-12-27, while the last push to the default branch was on 2026-10-19. The repository is not archived and the code is moving, but the gap between a lone 2018 test tag and recent commits suggests that tagged releases are not how this project ships changes in practice. If you plan to pin a version, there is very little to pin. Related gaps: the documentation describes no versioning policy, no changelog format and no rollback procedure, and the API section promises nothing about stability beyond the v2 path segment. There is also no mobile app. The site is described as mobile-friendly and pinnable to a home screen on Android and iOS, which is a workable phone experience but not native software with offline data or push notifications.
Compared with writing your own scraper, the trade is institutional focus against upstream control
NUSMods is not a general course catalogue service, and that shapes what an alternative has to be. A generic university data API, or a scraper you write yourself against university pages, carries one obvious advantage: it is not tied to a single institution, and you control when and how the data is refreshed. NUSMods takes the opposite position. Its scraping layer, its catalogue and its timetable logic are already tuned to one university's module codes and class times, so for an NUS student the browser interface and the v2 API cost nothing to set up, and for a developer the dataset is already shaped the way the timetable logic expects. The export service is the piece a hand-rolled equivalent rarely has, because timetable images are a social artefact in Singapore universities and get shared in chat groups as pictures. Outside NUS, the honest comparison is against assembling the same pipeline yourself, and the trade becomes licensing and upstream fragility rather than feature count.
Editorial conclusion
NUSMods is worth adopting for NUS students and for developers who want a ready-made course dataset for that one university, because the catalogue, the v2 API and the export service already cover the hard part of the problem. It is the wrong choice for any other institution and for teams that need a documented API contract, a release history to pin against, or a native mobile app. Before depending on it, check the stability of the api.nusmods.com/v2/ endpoint, confirm that your own tooling can consume the export service, and read website/README.md for the Node 22 and pnpm 10.30.3 setup.
Frequently asked questions
How do I run the NUSMods website locally?
The repository sends contributors to website/README.md for local setup and to ARCHITECTURE.md for how the projects fit together. The root package.json requires Node >=22 and pins [email protected], and it defines no start script, so the launch commands live in the individual package manifests.
Does NUSMods have a mobile app?
No. The project states there is no mobile app, and that the website is mobile-friendly and can be pinned to the home screen on Android and iOS.
Can I get NUSMods course data programmatically?
Yes. A public API is documented at https://api.nusmods.com/v2/ for retrieving course information, and a separate timetable export service runs at https://export.nusmods.com/. The project asks that both be used responsibly.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/nusmodifications-nusmods)Was this useful?