Problem
The production model is pre-rendered dist/ + API, and the entire value of a judge-review platform is people Googling a judge's name and landing on that judge's page. But the build emits no per-judge and no per-article HTML, so every core URL — including the ones we put in the sitemap and in transactional emails — serves a hard 404. At launch, the product's main pages do not exist.
Findings
- No per-judge or per-article static output.
dist/judges/contains onlyreview.htmlandsubmit.html(the static-named siblings); there is nodist/article/at all. The dynamic views —resources/views/judges/[id]/profile/index.stx(plusreviews/,cases/,rulings/siblings),resources/views/article/[id].stx,resources/views/court-houses/[id].stx,resources/views/judges/[id].stx— are pure client-side shells with no<script server>; a grep acrossresources/views/finds zerogetStaticPathsusages. - Static serving falls through to a real 404.
preview.ts:34-39returnsdist/404.htmlwith status 404 for any unmatched path, andnetlify.tomlhas no[[redirects]]/SPA fallback, so/judges/123/profileserves nothing. - The framework already supports the fix — and warns about it today.
pantry/@stacksjs/stx/dist/build.js(~line 10811) extractsgetStaticPathsfrom<script server>blocks and logsWarning: Dynamic route ... has no getStaticPaths or returned empty paths, emitting zero files for such routes. No view uses it. - The dead URLs are actively advertised.
app/Actions/SitemapAction.ts:92emits/judges/{id}/profilefor every judge and:110emits/article/{id}for every approved review./article/{id}is also baked into transactional emails:app/Actions/Reviews/SubmitReviewAction.ts:159,app/Actions/Admin/Reviews/UpdateReviewStatusAction.ts:109, andapp/Helpers/notifyModerators.ts:55— users click an email link straight into a 404.
Acceptance criteria
resources/views/judges/[id]/profile/index.stx(and thereviews/cases/rulingssiblings) definegetStaticPathsin a<script server>block enumerating judge ids from the database at build time.resources/views/article/[id].stxdefinesgetStaticPathsenumerating approved/published review ids.- Build output contains an HTML file for every
/judges/{id}/profileand/article/{id}URL the sitemap emits; a smoke test asserts everySitemapActionURL resolves to 200 againstdist/. - Judge name and published review content are server-rendered into the page (crawlable without JS), not fetched client-side only.
- Build log shows no "has no getStaticPaths or returned empty paths" warnings for sitemap-advertised routes.
- A rebuild trigger exists (scheduled cron and/or webhook on judge creation + review approval) so newly created judges/articles get static pages without a manual deploy.
- Interim only if SSG slips: a host-level rewrite serving a shell for
/judges/*and/article/*— documented as a stopgap, not the fix.
From the 2026-06-10 production-readiness audit.