Skip to content

Dev - #583

Merged
aamoghS merged 10 commits into
mainfrom
dev
Nov 6, 2026
Merged

Dev#583
aamoghS merged 10 commits into
mainfrom
dev

Conversation

@aamoghS

@aamoghS aamoghS commented Nov 6, 2026 •

Copy link
Copy Markdown
Member

Rest of the signed-in portal ships its first data with the HTML; admin roster search fixed (#582).


Note

Medium Risk
Touches many high-traffic portal routes and prefetch wiring; wrong cache keys or async prefetch branches could cause stale or missing client data, though failures fall back to client fetch.

Overview
Ships initial tRPC data with the HTML by moving many portal page.tsx files to thin server wrappers around PrefetchedPage, with the interactive UI extracted into *Page.tsx client components (admin club, bootcamp, hackathons, judging, dashboard-related routes, club bootcamp, etc.). Dashboard prefetch is now async and conditional: it mirrors the client’s “next step” logic to warm hackathon.myRegistrations, portal context, and submission/judging/results queries when applicable.

Hackathon admin roster search fixes the Drizzle EXISTS subquery to alias users explicitly so user_id compares against the real user primary key instead of a mis-resolved participant column (stopping 500s on search). Attendees tab polish defers RegistrationControls until client hydration for timezone-correct deadlines and formats attendee timestamps with venueFormat for venue-consistent display. Club hub prefetch also pulls member.myPass.

Smaller UX tweaks alongside the moves: e.g. bootcamp admin session rows use venue time formatting; hackathons list page is extracted similarly for prefetch.

Reviewed by Cursor Bugbot for commit 7cd2942. Bugbot is set up for automated code reviews on this repo. Configure here.

aamoghS and others added 10 commits November 6, 2026 12:39
The list drew only after hydration plus a tRPC batch. A server page now reads
the list, the visitor's registrations and projects and hands them to the
unchanged client page; its dates print on the venue calendar so the server
(UTC) and the browser agree. Cold load to the first card, 5 runs, 1440px,
median: 436 to 334 ms (warm 190 to 158).
The page waited on the registrations, then on the submission, the event and
the submission window for the event it picked. The server page reads the
registrations, picks the same event (the URL's, else the first still open),
and reads the other three with it. PrefetchedPage accepts an async reads
function for this. Cold load to the submission notice, median of 5:
878 to 488 ms (warm 412 to 232).
…mber pass

The dashboard's next step waited on the registrations and then up to four more
queries; the server page works out which the client will ask for (the same
checks as the page) and reads them. The club page also read member.myPass
after load; it is prefetched now. Cold load median of 5: dashboard checked-in
hacker 1247 to 530 ms (warm 420 to 279), club pass QR 514 to 290 (warm 203 to
150).
… list

Each drew its list only after hydration plus a tRPC batch. Server pages read
events.listAll, hackathon.listAll and the bans list for the unchanged client
pages, and the dates they print move to the venue calendar. Cold load median
of 5: /admin 493 to 308 ms, /admin/attendees 452 to 393, /admin/hackathons
1113 to 359.
…cations

The dashboard waited on the edition, then on the applications page and the
stats. The server page reads the edition, the first page of applications and
the analytics. The dates in the applications table move to the venue calendar,
and the registration controls (a deadline and inputs in the organiser's own
time zone, which the server cannot know) are drawn after hydration so both
renders agree; without that gate React threw #418. Cold load median of 5:
672 to 480 ms (warm 315 to 189).
The edition console waited on the overview and then the checklist. Server
pages read the edition list, the overview and the checklist. shortTime moves
to the venue clock so server and browser print the same times. Cold load
median of 5: /admin/judging 560 to 365 ms, an edition 963 to 495.
Attendance and the workshop table drew after hydration plus a tRPC batch.
A server page reads both for the current term and the session dates print on
the venue calendar. Cold load median of 5: 858 to 613 ms (warm 321 to 251).
… sign-up

Each page held a loading screen until its first tRPC batch returned. Server
pages read the first reads of lead, lead/[id], initiatives, subteams,
club/bootcamp and judge/register for the unchanged client pages. Cold load
median of 5: lead 582 to 369 ms, a project 695 to 432, initiatives 437 to 301,
subteams 643 to 475, club/bootcamp 621 to 392, judge/register 699 to 419.
Every search on the admin roster answered 500: "operator does not exist:
uuid = text". The filter is shared by the paged roster, which runs as a
relational query (db.query.hackathonParticipants.findMany), and inside that
Drizzle renders every column in a raw sql template against the participants
alias. The user-name and email subquery therefore compared
"hackathonParticipants"."id" (uuid) with its own user_id (text), and read
name and email off the participants alias too.

The user table now has a hand-written alias in that subquery. Checked on a
production build against the local Docker database: "example.test" matches
the 8 seeded attendees through their user email, "casey" 1, "zzzz" 0.
perf(mainweb): ship the rest of the portal's first data with the HTML
@github-actions

github-actions Bot commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

@greptileai

@github-actions

github-actions Bot commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@github-actions

github-actions Bot commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

Visit the preview URL for this PR (updated for commit 7cd2942):

https://hacklytics2027--pr-583-e9h0x2jg.web.app

(expires Fri, 13 Nov 2026 17:54:50 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

Sign: c48ba34db61581e25fe2978355160b5eefe0e83f

@greptile-apps

greptile-apps Bot commented Nov 6, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 4/5

[Medium impact] The broadest reach is faster first data across signed-in portal workflows.

Fix the dashboard’s late rejection handler before merging.

Findings

  1. P1 Profile errors escape the fallback ▶

Summary

Moves the remaining signed-in pages behind server reads so their first data can arrive with the HTML.

  • Signed-in portal pages show their first data without waiting for browser queries.
  • Admin attendee search matches names and email addresses to participants.
  • Admin hackathon dates use the venue’s time zone and local clock controls.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Portal page request] --> B{Signed-in caller available?}
  B -->|No| C[Render existing client page]
  B -->|Yes| D[Run page reads]
  D --> E[Wait for dependent reads]
  E --> F[Keep successful results]
  F --> G[Fill browser query cache]
  G --> H[Render page with first data]
Loading

Reviews (1) · Last reviewed commit: "Merge pull request #582 from DataScience..." · Reviewed by Greptile

["user.me", undefined, c.user.me()],
]}
reads={async (c) => {
const me = c.user.me();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Profile errors escape the fallback

If user.me fails while registrations or portal context are still loading, its promise has no rejection handler. dehydratePrefetched attaches its catch only after this callback returns, so the failure reaches the server as an unhandled rejection instead of staying inside the intended fallback. Attach a catch when starting me, before the first await.

@aamoghS
aamoghS merged commit 3fd78ba into main Nov 6, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant