nook: defer the SSR stream until the appcast resolves on /changelog

Every cold origin render of /changelog died with ERR_HTTP_HEADERS_SENT:
the pending createAsync at the top of NookChangelogPage suspended the
whole component before <EdgeCacheHeaders> rendered, the shell flushed
while the S3 appcast fetch was in flight, and the boundary re-render
then called setResponseHeader on an already-sent response. Warm renders
hid it because the appcast's 5-minute module cache resolved in a
microtask; fresh Vercel isolates and cache expiry hit the crash, which
is why refreshes and direct navigation failed while in-app Links worked.

deferStream holds the stream until the releases resolve, so HttpHeader
always runs pre-flush. The S3 latency lands on origin renders only,
which the page's CDN-Cache-Control s-maxage=300 already keeps rare.

Tests: local prod-build cold-start loop (build + curl /nook/changelog),
red 3/3 before, green 5/5 after; stack identical to the prod trace.

Fixes FRE-112
This commit is contained in:
2026-10-05 12:40:12 -04:00
parent 92af52dfc9
commit 687df016a6

View File

@@ -34,7 +34,7 @@ const getReleases = query(async () => {
}, "nook-changelog-releases");
export default function NookChangelogPage() {
const releases = createAsync(() => getReleases());
const releases = createAsync(() => getReleases(), { deferStream: true });
// Newest release starts open; every other row starts collapsed. `null`
// means "the user hasn't touched the accordion yet"; after any click the
// signal holds a version or the NONE sentinel — collapsing the open row