fix: repair the timetable download and the calendar download's month - #140
Open
Pranjal-SB wants to merge 3 commits into
Open
fix: repair the timetable download and the calendar download's month#140Pranjal-SB wants to merge 3 commits into
Pranjal-SB wants to merge 3 commits into
Conversation
/api/timetable read the timetable straight from the goscrape table while
every other surface (the academia page, /view) reads it from the Go
backend. That second source of truth needed NEXT_PUBLIC_SUPABASE_URL and
NEXT_PUBLIC_SERVICE_KEY, and without them createClient("", "") throws
"supabaseUrl is required" at module evaluation: the route 500s and
`next build` fails outright while collecting page data.
Read from fetchUserData() instead, which is where the rest of the app
already gets the same data, and return the ImageResponse directly rather
than rebuffering it through a second Response.
Supabase still backs optional-hour saving, so keep the client but let it
be null when unconfigured instead of throwing at import. /api/ophours
answers 503 in that case, which the editor already surfaces as a failed
save.
Also give the download link a filename with an extension, and guard the
timetable lookups so a missing timetable renders empty instead of
throwing.
The downloaded image was titled with the wrong month. Both the API route
and the grid picked a name with
month.includes("Jul") ? months[index + 6] : months[index]
which only holds when the calendar starts in January or July. The route
tested the selected month's own string, so October in a July-start
calendar fell to the else branch and produced an image titled "April"
over October's days. The grid tested calendar[0] instead, so it survived
July starts but not others - a semester can start in any month, as
CalendarHelper_test.go's "Aug '26" fixture shows, and there it rendered
January.
Months arrive as "Aug '26", so derive the name from that string in one
shared helper. The result no longer depends on the array index at all.
The same helper feeds the download filename.
next.config.ts and vercel.json both stamped Cache-Control: public, max-age=300, stale-while-revalidate=600 on /api/(.*). Headers configured this way override what a route handler sets, so /api/timetable - a PNG of one student's timetable, built from their session cookie - was advertised to shared caches as reusable, and /api/calendar lost the CDN headers it sets for itself. Exclude /api from the blanket rule in both configs and let each route declare its own caching. Note that authenticated pages are still covered by the catch-all public, max-age=3600 rule. That is the same class of problem and wants a deliberate decision about page caching, so it is left alone here.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Both download buttons on the academia page were broken. Fixing them turned up
two neighbouring problems with the same root, so they are here too, each in its
own commit.
Timetable download returned an error
/api/timetableread the timetable straight from thegoscrapetable, whileevery other surface that shows the same data — the academia page and
/view—reads it from the Go backend through
fetchUserData().That second source of truth needs
NEXT_PUBLIC_SUPABASE_URLandNEXT_PUBLIC_SERVICE_KEY. Without themcreateClient("", "")throwssupabaseUrl is requiredat module evaluation, so the route 500s — andnext buildfails outright while collecting page data:The route now reads from
fetchUserData()and returns theImageResponsedirectly instead of rebuffering it through a second
Response.Supabase still backs optional-hour saving, so the client stays — but it is
nullwhen unconfigured rather than throwing at import, and/api/ophoursanswers 503 in that case, which the editor already surfaces as a failed save.
A deployment without Supabase now builds and runs, losing only that one
feature.
Calendar download had the wrong month on it
Both the API route and the grid named the month with:
which only holds when the calendar starts in January or July.
The route tested the selected month's own string. Pick October in a
July-start calendar and
"Oct '25"fails theincludes("Jul")test, so itfalls through to
months[3]— an image titled April over October's days.The grid tested
calendar[0]instead, so it survived July starts but notothers. A semester can begin in any month;
CalendarHelper_test.gouses an"Aug '26"fixture, and for that calendar the grid rendered January inboth the header and the download filename.
Months arrive as
"Aug '26", so the name is now derived from that string in asingle shared helper and no longer depends on the array index at all.
Per-user API responses were marked publicly cacheable
next.config.tsandvercel.jsonboth stampedCache-Control: public, max-age=300, stale-while-revalidate=600on/api/(.*). Headers configured this way override what a route handler sets, so/api/timetable— a PNG of one student's timetable, built from their sessioncookie — was advertised to shared caches as reusable, and
/api/calendarlostthe CDN headers it sets for itself.
/apiis now excluded from the blanket rule in both configs, and each routedeclares its own caching.
Authenticated pages are still covered by the catch-all
public, max-age=3600rule. That is the same class of problem, but it wants a deliberate decision
about page caching rather than a drive-by change, so it is left alone here and
called out in the commit message.
Also
Timetable-ClassPro.png./viewand the calendar grid threw on missing timetable/calendar datainstead of rendering empty.
Testing
utils/Times.test.tsis a plainnode:assertscript — no test runner isconfigured in this repo, and it covers the month-naming case that regressed.
What is not covered: I have no live backend or Supabase project to point
this at, so neither download has been exercised end to end. The month-naming
bug is demonstrated by the index arithmetic above and the build failure is
reproduced verbatim, but clicking both buttons against a real deployment before
merging would be worth it.
Note for reviewers
frontend/utils/Database/index.tsis dead code — nothing in the repo importsit. I guarded it rather than deleting it to keep this PR to the reported bugs;
it can go in a follow-up, or here if you would rather.