Loaders & actions
A route loads data with two functions. loader runs on GET, action runs on POST. Both take the args bag and return data that the page's default export renders.
A page route with a loader must export LoaderOutput — the type its loader returns and its default renders.
import type { RouteArgs } from 'camelon';
export type LoaderInput = { query: { name?: string } };
export type LoaderOutput = { greeting: string };
export function loader({ query }: RouteArgs) {
return { greeting: `Hello, ${query.name ?? 'world'}` };
}
export default function Data({ greeting }: LoaderOutput) {
return (
<div class="d-card">
<strong safe>{greeting}</strong>
<p>Try adding <code>?name=Ada</code> to the URL above.</p>
</div>
);
}export type LoaderInput = { query: { name?: string } };
export type LoaderOutput = { greeting: string };
export function loader({ query }: RouteArgs) {
return { greeting: `Hello, ${query.name ?? 'world'}` };
}
export default function Page({ greeting }: LoaderOutput) {
return <h1 safe>{greeting}</h1>;
}
The args bag
Every loader, action, and middleware gets the same object. There is no req, res, or cookies. Read through request, write through response, scratch on ctx, manage state through session.
| Key | What it is |
|---|---|
params |
path params (:id, :splat) |
query |
parsed query string |
body |
parsed request body |
signals |
Datastar state ({} if not a reactive request) |
files |
multipart uploads by field; .data is a Uint8Array |
request |
raw read: .url .headers .method .signal, .json() .text() .formData() |
response |
.status(code), .header(name, val) |
ctx |
middleware → loader scratch |
stream |
server → client SSE channel |
session |
signed cookie store; auto-commits on change |
db |
your injected client; throws if unconfigured |
logger |
request-bound; carries { requestId, method, path } |
Return values
A page route always renders HTML. A resource route returns a string for HTML, an object for JSON, or a Response for full control.
export function loader() {
return { ok: true, items: [1, 2, 3] }; // → application/json
}
Next: typed contracts.