Skip to main content
Each page can have a companion .server.tsx file. That module never ships to the browser.

Loaders

loader runs on GET. Its return value becomes the page component’s props and useLoaderData().
src/routes/projects/[id].server.tsx
src/routes/projects/[id].tsx
LoaderArgs: redirect("/login") from a loader sends the browser there. Prefer that for HTML pages. Throw HTTPException(401) from APIs — see Errors.

Actions

action handles POST, PUT, PATCH, and DELETE for the same URL. Named actions live on actions and are selected with ?action= or ?_action=.
src/routes/projects/[id].server.tsx
After an action: Use redirect(url, 303) after POST so the browser does not replay the form. redirect(url) is 302.

Forms

<Form> intercepts submit, posts multipart/urlencoded as the browser would, and follows redirects through the SPA router. Add data-enhance="false" on a submitter to do a full document post. useForm() is a small controlled helper (data, errors, pending, post(url)). It treats HTTP 422 as field errors. Island pages should use useIslandForm() — same API, but a successful action reloads the document.

File uploads

See Bindings for R2.

Cookies and headers

There is no wrapper around cookies. Use Hono’s helpers on c:

Render flags

Export these from the .server.tsx file:
prerender is reserved and not implemented. Do not export it expecting a static snapshot.

Request-scoped helpers

Inside a loader, action, or middleware you can call:
They use AsyncLocalStorage. They throw from a scheduled / queue / email handler — pass env from defineWorker instead. See Worker entrypoint.