src/ ~8,000 lines
All application source code. Organized into four layers that depend only downward: UI consumes Context, Context calls Core and Data, Core and Data have no internal dependencies.
Children
layer
context/
PlannerContext (all state) + ThemeContext (CSS vars). The bridge between UI and logic.
layer
core/
Pure domain logic: graduation checking, prereq evaluation, course normalization, semester grid.
layer
data/
I/O adapters: fetch courses, load majors, read/write localStorage.
layer
ui/
12 React components. All consume PlannerContext via usePlanner(). No prop drilling.
Layer dependency rules
graph LR
UI["ui/ (12 components)"]
CTX["context/ (2 contexts)"]
CORE["core/ (7 modules — pure)"]
DATA["data/ (4 adapters — I/O only)"]
UI -->|"usePlanner()\nuseTheme()"| CTX
CTX -->|"pure fn calls"| CORE
CTX -->|"async I/O"| DATA
style UI fill:#ddf4ff,stroke:#0969da
style CTX fill:#fbefff,stroke:#8250df
style CORE fill:#dafbe1,stroke:#1a7f37
style DATA fill:#fff8c5,stroke:#9a6700
Import direction. Core never imports React; Data never imports Core.
Entry points: main.jsx + App.jsx
main.jsx is 4 lines — it mounts React in StrictMode and renders App.
App.jsx wraps the app in providers and computes the uiScale factor:
App() → JSX
Wraps everything in
<ThemeProvider> then <PlannerProvider>.
Inside those, PlannerApp renders the fixed-size shell and uses a
ResizeObserver to compute uiScale = containerWidth / BASE_WIDTH.
The entire app div receives transform: scale(uiScale) so all pixel values
in components can be written at one canonical desktop size.
File inventory
| File | Layer | Lines | Purpose |
|---|---|---|---|
main.jsx | — | 4 | React root mount |
App.jsx | — | ~60 | Provider wrapper + uiScale |
context/PlannerContext.jsx | Context | ~1,600 | All application state |
context/ThemeContext.jsx | Context | ~65 | CSS variable injection |
core/gradRequirements.js | Core | ~500 | Graduation requirement checking |
core/prereqEval.js | Core | ~80 | Prerequisite satisfaction |
core/courseModel.js | Core | ~120 | Course normalization + edges |
core/semGrid.js | Core | ~80 | Semester grid generation |
core/planModel.js | Core | ~200 | Plan helpers + PDF export |
core/themes.js | Core | ~160 | CSS variable token sets |
core/constants.js | Core | ~100 | Global compile-time constants |
data/courseLoader.js | Data | ~30 | Fetch course catalog |
data/majorLoader.js | Data | ~50 | Fetch major/minor requirements |
data/minorLoader.js | Data | ~40 | Fetch minor requirements |
data/persistence.js | Data | ~30 | localStorage read/write |
ui/Header.jsx | UI | ~780 | Top bar: controls, plan management, settings |
ui/BankPanel.jsx | UI | ~850 | Course bank + grad panel sidebar |
ui/GradPanel.jsx | UI | ~1,000 | Graduation requirement tree UI |
ui/SemRow.jsx | UI | ~850 | Semester row (fall/spring/special) |
ui/SummerRow.jsx | UI | ~850 | Paired summer semester columns |
ui/CourseCard.jsx | UI | ~500 | Draggable course tile |
ui/InfoPanel.jsx | UI | ~400 | Bottom drawer for selected course |
ui/RelationLines.jsx | UI | ~100 | SVG overlay for prereq/coreq lines |