From edd6f8d78a32d2f94462831e975194cff7f3ccca Mon Sep 17 00:00:00 2001 From: Agustin Kassis Date: Tue, 12 May 2026 20:41:06 -0300 Subject: [PATCH] fix(hackathons): wrap HackathonProjectsList in Suspense to unblock prerender MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On prod (Vercel), the `/hackathons/[id]` page is served with the entire HackathonProjectsList section truncated from the RSC stream: the parent row references $L32, but row 32's data is never sent. The page ends at the "Participación" rules card and the projects list (with the project links users want to click) simply doesn't render. Local dev SSR includes the section fine (~102KB vs 55KB on prod). The truncation is specific to the prerender path that combines a `"use cache"` directive on the page with a complex client component (useEffect + useMemo + useHackathonResults + lots of imports) as the last child. Earlier client components on the page render fine (HackathonInscripcionButton, HackathonResultsClient) — only the tail gets dropped. Wrapping `` in `` marks the slot as a deferred streaming boundary so the cached prerender stops trying to resolve it inline. The fallback is null (the component already renders its own loading skeleton when nostrSubmissions === []), and client hydration takes over normally. Verified locally: SSR HTML still contains "PROYECTOS INSCRIPTOS" / "Rescanear Nostr" / "Inscribite gratis" after the change, and the client component mounts correctly. The Vercel-side fix needs a preview deploy to confirm row 32 actually arrives in the prod RSC stream now. --- app/hackathons/[id]/page.tsx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/app/hackathons/[id]/page.tsx b/app/hackathons/[id]/page.tsx index f943468..b50659f 100644 --- a/app/hackathons/[id]/page.tsx +++ b/app/hackathons/[id]/page.tsx @@ -1,4 +1,5 @@ import type { Metadata } from "next"; +import { Suspense } from "react"; import { notFound } from "next/navigation"; import Link from "next/link"; import { @@ -533,8 +534,17 @@ export default async function HackathonPage({ - {/* Projects / leaderboard (curated + Nostr submissions) */} - + {/* Projects / leaderboard (curated + Nostr submissions). + * + * Wrapped in so the parent `"use cache"` prerender doesn't + * try to resolve this client component inline. On Vercel, omitting the + * boundary truncates the RSC stream right at this slot — the page + * comes back missing the entire projects section. The fallback renders + * the SSR skeleton; client takes over on hydration. + */} + + + ); }