Repository navigation
Conversation
…ent with the HTML A signed-in page waited for JS, then asked /api/auth/session (twice), then sent a tRPC batch for the portal context and registrations before it could draw. The layout now reads the session and those two queries on the server and passes them to SessionProvider and a HydrationBoundary, so the session and sidebar reads need no client round trips. Visitors without a session cookie skip it. Dashboard content visible (cold, 5 runs, 1440px): median 592 ms to 391 ms, range 506..740 to 269..471.
…n the server Dashboard, club, checkin, settings and judge each drew only after hydration plus one tRPC batch. A server page now runs those reads and hands them to the unchanged client page through a HydrationBoundary, so the batch request is gone. Cold load to h1 visible (5 runs, 1440px, base vs perf, median): dashboard 446 to 266 ms, club 490 to 304, checkin 354 to 237, settings 366 to 306, judge 521 to 459. Text, redirects and theme match the base on all five at 402 and 1440 wide.
The event page showed its loading screen until hydration plus a getById round trip. The server page now resolves the edition and hands it to the client page. Cold load to h1 visible (5 runs, 1440px, signed-in hacker, base vs perf, median): 1054 ms to 399 ms (range 452..1201 to 367..440).
All seven tabs shipped with the page although one shows at a time. Six now load through next/dynamic and are fetched once the browser is idle, so a tab click still finds them ready. Route JS for /hackathons/[id] drops from 228.5 to 205.2 KB gzip (746.9 to 669.4 KB raw). The tab switch also uses history.replaceState instead of router.replace, which made the server render the page again, and now with its reads, on every click.
The site is a static page with a handful of interactive spots, but the Next export shipped about 150 KB of gzipped JavaScript (React, the App Router runtime, an inlined RSC payload) to run them. Astro renders every section to HTML at build time and sends script only where a visitor can use it. What runs where: - Sections, sprites and the FAQ render at build time with no JS. - Navbar, theme toggle, countdown, bloom-on-scroll and the service worker registrar are small plain scripts. The theme icon follows the theme in CSS, so it is right on first paint, and the no-flash theme script stays an inline script in <head>. - The four flower beds are the only React: hero (client:idle), footer and 404 (client:visible), and the mobile menu (client:media below 1024px). Markup, copy, CSS, head tags, URLs, 404 page, sw.js and public files are unchanged. Astro writes to out/, so CI and Firebase need no change except the immutable-cache rule, which now matches /_astro/ instead of /_next/static/ (sw.js caches the same path cache-first). Astro 6 and @astrojs/react 5 rather than 7: the root package.json overrides vite to 7 for the whole repo and Astro 7 needs vite 8. typecheck is tsc --noEmit because astro check needs the TypeScript JS API, which TypeScript 7 does not ship.
Update the site reference and README for the new commands, folder layout and the per-piece hydration choices, and the repo-level docs that named the old framework.
The portal layout and the prefetched pages now look the session up on the server. If that lookup throws (the database unreachable, say) it took every portal page down with a server error, where before the page rendered and the browser asked for the session itself. Both now treat a failed lookup like no session: the page renders as it did before this branch and fetches for itself. Checked with a production build pointed at a closed port and a session cookie: /dashboard, /club and /hackathons/[id] answer 200.
astro below 7.2.8 allows remote code execution through AVIF image optimization, and 6.x has no patch. Move to astro 7.4.2 and @astrojs/react 7.1.1. Astro 7 needs vite 8, but the root override pins vite to ^7.3.7 to patch Dependabot alerts for every other workspace. Rather than lift that, two scoped overrides (astro>vite and @astrojs/react>vite, both 8.3.5) give vite 8 to the Astro site only. mainweb, packages and tooling still resolve vite 7.3.7.
…browser agree The portal pages now render on the server, which runs in UTC on Cloud Run. They formatted dates and picked "today" in the runtime's own zone, so the server HTML showed a different day or time than the browser for any visitor outside UTC, and React logged hydration error #418 on every one of those pages. Dates are now formatted in en-US on America/New_York, the venue's zone and the repo's policy for event times, through one small helper (lib/venue-time.ts) that builds each Intl.DateTimeFormat on first use. Start-of-day tests (is the event on today, has it started, is it over) compare venue calendar days instead of local midnight. Output for a visitor in New York is unchanged. No TZ is set on the server, so unrelated server date math is untouched.
mainweb sets reactCompiler: true, and Next resolves the compiler plugin from mainweb's own dependencies. mainweb never declared it; it resolved only because hacklytics2027 listed babel-plugin-react-compiler@1.0.0 and pnpm used it to satisfy next's optional peer for the whole workspace. Moving hacklytics2027 to Astro dropped that entry, and CI's clean install of web then failed: "Failed to resolve package babel-plugin-react-compiler while attempting to resolve React Compiler". Same version as before, so the compiled output is unchanged.
Activation deletes only cache names other than CACHE_VERSION, and it was still hacklytics-v4. A returning visitor kept the Next.js pages and /_next/static chunks cached under it, so an offline visit could render a cached shell that requests scripts the Astro build no longer has. v5 makes activation drop them.
perf(mainweb): ship the signed-in portal's first data with the HTML
feat(hacklytics2027): move the site from Next.js to Astro
Dependency ReviewThe following issues were found:
|
|
Visit the preview URL for this PR (updated for commit 17c9062): https://hacklytics2027--pr-581-whaddi1v.web.app (expires Fri, 13 Nov 2026 16:15:53 GMT) 🔥 via Firebase Hosting GitHub Action 🌎 Sign: c48ba34db61581e25fe2978355160b5eefe0e83f |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 17c9062. Configure here.
| <script> | ||
| import "../scripts/theme-toggle"; | ||
| </script> | ||
| {import.meta.env.PROD && <script>import "../scripts/service-worker";</script>} |
There was a problem hiding this comment.
Service worker script not bundled
High Severity
The production service worker is included via a render-time conditional around a <script>import ... tag, so Astro does not hoist or bundle it. Built HTML emits a classic script with a source-tree import, which browsers reject, so /sw.js never registers after the Astro cutover. Returning visitors keep the old Next.js worker, whose offline fallback still points at /_next/static assets that no longer exist.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 17c9062. Configure here.


Automated PR tracking changes from
devintomain.Note
Medium Risk
Replaces the entire Hacklytics marketing stack and hosting cache assumptions, so any misalignment between Astro output, Firebase headers, or CI scripts could break deploy previews despite no backend changes.
Overview
Refactors the Hacklytics marketing workspace from a Next.js static export to Astro 7 with a new
astro.config.mjs,src/page/layout structure, React islands for the interactive beds, and plain scripts for navigation/theme/service-worker hooks; the oldapp/tree, Next config, and React-only registrars are deleted in favor of Astro/Vite tooling while keeping Tailwind 4 via@tailwindcss/vite.Supporting work threads the change through docs (
README,docs/architecture.md,docs/getting-started.md,docs/sites/hacklytics2027.md,sites/hacklytics2027/README.md) so contributors understand Astro workflows, preview/typecheck commands, and whyastro checkis skipped, and updates Firebase hosting headers so hashed assets under/_astro/**get long-lived caching while HTML is revalidated, matching the new build output.Tooling updates add pnpm overrides pinning
astro>vite/@astrojs/react>viteto 8.3.5 (leaving other workspaces on Vite 7), refresh.gitignore/Oxlint extends for Astro, and regeneratepnpm-lock.yamlwith the new dependency graph plus relocatedbabel-plugin-react-compilerlinkage forsites/mainweb.Reviewed by Cursor Bugbot for commit 17c9062. Bugbot is set up for automated code reviews on this repo. Configure here.