Person Detail: 404 Handling & Server-Side Rendering
Person Detail: 404 Handling & Server-Side Rendering
As of v0.1.103, the /dashboard/people/[id] route is a fully server-rendered page with robust validation. Invalid, missing, and unauthorised person IDs all return a proper HTTP 404 response rather than a blank or broken UI.
Validation Sequence
When a request hits /dashboard/people/[id], the server performs the following checks in order before any HTML is rendered:
- Non-numeric ID check — if the
idsegment cannot be parsed as an integer (e.g./people/not-a-number),notFound()is called immediately with no database round-trip. - Session check —
auth()is called server-side. If no authenticated session exists,notFound()is returned (belt-and-braces over the existing middleware guard). - Ownership-scoped DB query — the person record is fetched with
WHERE id = ? AND userId = ?. Records belonging to other users are treated identically to missing records. - Empty result check — if the query returns no rows,
notFound()is called.
All four failure paths trigger Next.js's built-in 404 flow, which renders the existing branded not-found.tsx page and returns an HTTP 404 status code.
ID Enumeration Protection
Because the ownership-scoped query (WHERE id = ? AND userId = ?) returns an empty result for both non-existent IDs and IDs belonging to other users, an authenticated user cannot determine whether a given ID exists. Both cases produce an identical 404 response.
Server-Side Data Pre-fetching
On a successful lookup, person and matches data are fetched server-side and passed as props to the client component (initialPerson, initialMatches, personId). This eliminates the extra client-side fetch that previously occurred on first load — the page is fully populated on the initial HTML response.
After a re-screen action, the client component calls refreshPerson() (a lightweight fetch to /api/people/[id]) to update the displayed state with fresh screening results. This is the only client-side fetch that remains.
Static Prerender Prevention
The page exports:
export const dynamic = "force-dynamic";
This prevents Next.js from attempting to statically prerender the route at build time, which would fail because the page reads from the database and requires an authenticated session.
Error States
| URL | Condition | Response |
|---|---|---|
/dashboard/people/not-a-number | Non-numeric segment | HTTP 404 + branded not-found page |
/dashboard/people/99999 | Record does not exist | HTTP 404 + branded not-found page |
/dashboard/people/123 | Record belongs to another user | HTTP 404 + branded not-found page |
/dashboard/people/123 | No active session | HTTP 404 + branded not-found page |
/dashboard/people/123 | Valid, owned record | 200 + server-rendered detail page |