state management
Three layers: React Context at runtime, localStorage across sessions, nuqs in the URL.
Related: Data model, Python pipeline.
Layers#
flowchart TB
subgraph runtime [Session]
Ctx[UserContext]
RQ[TanStack Query]
end
subgraph persist [Disk]
LS[(localStorage)]
end
subgraph share [URL]
nuqs[year batch campus selectedSubjects]
end
Form --> Ctx
Form --> nuqs
Ctx --> LS
LS --> Ctx
Home --> RQ
RQ --> API["/api/*"]UserContext#
website/context/userContext.ts and userContextProvider.tsx:
flowchart LR schedule[schedule Python output] edited[editedSchedule overlay] schedule --> Display edited --> Display
| Field | Role |
|---|---|
| schedule | Last generated timetable |
| editedSchedule | Edits and custom events |
| setters | setSchedule, setEditedSchedule |
Display components use editedSchedule || schedule. A new generate call sets editedSchedule to null.
The provider loads editedSchedule from localStorage on mount and writes it back whenever it changes. Null clears the key.
localStorage#
flowchart TB CS[cachedSchedule] CSP[cachedScheduleParams] CC[classConfigs] ES[editedSchedule]
| Key | Shape |
|---|---|
cachedSchedule |
YourTietable |
cachedScheduleParams |
{ year, batch, campus, selectedSubjects } |
classConfigs |
{ [name]: { year, batch, campus, selectedSubjects, electiveCount? } } |
editedSchedule |
edited YourTietable |
timelineWelcomeDismissed |
"1" |
HomeContent hydrates schedule from cachedSchedule and writes it whenever the object is non-empty. After generate it also writes cachedScheduleParams for URL conflict checks.
Named configs live in classConfigs. The form can save, load, delete, and share them.
nuqs#
On home:
year, batch, campus parseAsString
electiveCount parseAsInteger
selectedSubjects parseAsArrayOf(parseAsString)
flowchart TD
Mount[HomeContent mount]
Mount --> HasParams{year+batch+campus?}
HasParams -->|no cache| Auto[pendingAutoGeneration]
HasParams -->|cache same params| Keep
HasParams -->|cache different| Dialog[UrlParamsDialog]
Dialog --> Override
Dialog --> Prefill
Dialog --> ViewExistingOverride queues the same auto-generate path. Prefill only fills the form.
Query cache#
| Hook | Endpoint | staleTime |
|---|---|---|
| useTimeTables | /api/time-table |
24h |
| useBatchMappings | /api/time-table/{sem}/{batch} |
5 min |
| useAcademicYears / Calendar | /api/academic-calendar |
24h |
| useExamSemesters / Schedule | /api/exam-schedule |
24h |
| useMessMenu | /api/mess-menu |
1h |
Default semester is ODD26 when present (lib/constants.ts + getSmartSemester). Default academic year is 2627.