Exp 09 — nested routes

Three routes under one node.

This heading is rendered by a Layout two levels down from the document. The root Layout wrote the <html> around it; this one wraps every route under /builds, and the component below is whichever one matched.

Layout sees
/builds/new
Params, from getContext()
{}

Live specimen — builds/new.server.tsx

This is the static route. Its sibling :id matches this URL too, and is declared above it in the Route file — so if you are reading this sentence rather than a build called new, specificity decided it and declaration order did not.

Live specimen — builds/mutations.server.ts

Submit that form with JavaScript switched off and it still works. There is no client code on this page to switch off: the api.POST is the submission, not an enhancement over it, and a form that works natively never waits on a runtime.

Success and failure take the same shape — a 303 back to this URL with the reason in the query string. An API route cannot render a page: it is not in the Walk, so it has no way to re-render the component beside it. The accepted cost is a failure you can see in the address bar.

Only an API route can do this. A page component handling its own POST must await request.formData(), which is its first Suspension and therefore its Commit, and a Response returned after Commit aborts the stream. So a page-route POST can render UI at 200 and can never redirect or choose a status.

A node carrying no api at all renders its component for every method, POST included: POST /builds redraws the index page at 200. That is the fourth row of the doctrine's table — a form posting to a node with no handler for it — and it is documented rather than detected, because a Client component renders under many Routes and the build cannot know which node a given form sits on.