Proper 404 Handling on Person Detail Pages
Proper 404 Handling on Person Detail Pages
Introduced in v0.1.104
Overview
The person detail page (/dashboard/people/[id]) now returns a real HTTP 404 and renders the platform's branded 404 UI whenever an invalid or unauthorised person ID is requested. Previously, invalid lookups silently produced a blank screen or a plain "Record not found." text string.
What triggers a 404
Three distinct conditions each result in an immediate 404:
- Non-numeric ID — e.g.
/dashboard/people/not-a-number. The server validates the route parameter as an integer before making any database call. - No authenticated session — belt-and-braces check in addition to middleware; unauthenticated requests are rejected without touching the database.
- Record not found or belongs to another user — the database query is scoped to
WHERE id = ? AND userId = ?. If no rows are returned — whether because the record doesn't exist or belongs to a different account — the page returns 404. This prevents ID enumeration.
Performance improvement
As part of this change the person detail page was converted from a client-shell that fetched data after mount into a full async server component. Person and match data are now fetched server-side and passed to the page as props, eliminating an extra round-trip on first load.
The Re-screen action still triggers a client-side refresh (refreshPerson()) to reflect updated match results after rescreening, so interactive behaviour is unchanged.
The 404 page
When notFound() is called, Next.js renders src/app/not-found.tsx — the platform's existing branded 404 component. No changes were made to that file; the improvement is purely in the server component that calls it.
URL examples
| URL | Result |
|---|---|
/dashboard/people/42 (your record) | Person detail page, server-rendered |
/dashboard/people/42 (another user's record) | 404 — branded not-found page |
/dashboard/people/99999 (non-existent ID) | 404 — branded not-found page |
/dashboard/people/abc (non-numeric) | 404 — branded not-found page |
Technical reference
| File | Role |
|---|---|
src/app/dashboard/people/[id]/page.tsx | Async server component; owns validation, auth check, and DB query |
src/app/dashboard/people/[id]/_client.tsx | Client component; receives pre-fetched data as props; handles rescreen/delete interactions |
src/app/not-found.tsx | Branded 404 UI rendered by Next.js when notFound() is called (unchanged) |