nu-map
A zero-backend, single-page React degree planner for Northeastern University. Every piece of logic runs in the browser — no server, no database, no auth. Plans live in localStorage and export as JSON.
src/main.jsx → src/App.jsxArchitecture overview
The app uses a strict 4-layer hexagonal architecture. Data flows upward only — core never imports UI, and data adapters never import context. PlannerContext is the hub: it calls core logic and data adapters, then exposes state to all UI components via usePlanner().
Source tree
Navigate any node below to read its full documentation — methods, state, connections to siblings and parents.
Key design decisions
No backend, ever
Zero hosting cost, no migrations, no auth. Plans persist in localStorage and export as JSON files. Course data is scraped and bundled at build time.
React Context over Redux
All state in PlannerContext (~1,600 lines). No action/reducer boilerplate. Any component reads or mutates any state with one usePlanner() call.
CSS variables for theming
ThemeContext injects ~100 CSS custom properties onto <html>. All components use var(--token) inline. No CSS-in-JS library.
Fixed layout + CSS scale
Components are written at desktop scale. On small screens, App.jsx applies transform: scale(uiScale) — one layout for all viewports.
Data sources
| Source | Format | When loaded | Size |
|---|---|---|---|
public/all-courses.json | JSON array | App startup (primary) | 6.5 MB, 4,800+ courses |
husker.vercel.app/courses/all | JSON array | App startup fallback (if local JSON fails) | Same data via SearchNEU API |
tableau.northeastern.edu | Playwright DOM scrape | NUPath Update tool (manual) | ~4,800 course NUPath records |
graduatenu/ fork | Major2 JSON | On major selection | 1,471 files |
localStorage | JSON strings | App startup + every mutation | ~50 KB per plan |
Quick start
git clone https://github.com/nayugu/nu-map
cd nu-map
npm install
npm run dev # Vite on :5173 + catalog-check-server on :3333
npm run data:scrape:write # update course catalog from catalog.northeastern.edu
npm run data:patch:write # apply YAML corrections from data/patches/
npm run build # production bundle → dist/