What to build
Implement the definePage function — the primary API for declaring page routes. Uses a curried pattern for full TypeScript inference:
export default definePage("/blog/[slug]")({
template: "marketing",
loader: async ({ request, ctx }) => {
return { post: await getPost(ctx.params.slug) };
},
defineSlots: ({ loaderData }) => ({
main: <BlogPost post={loaderData.post} />,
}),
meta: ({ loaderData }) => ({
title: loaderData.post.title,
}),
});
The first call accepts the route path string and returns a function. The second call accepts the page config. This pattern allows TypeScript to:
- Infer params from the route path (via
RouteMap)
- Infer
loaderData type from the loader return
- Validate
template against TemplateRegistry
At runtime, definePage is an identity function — it returns the config unchanged.
Acceptance criteria
Blocked by
What to build
Implement the
definePagefunction — the primary API for declaring page routes. Uses a curried pattern for full TypeScript inference:The first call accepts the route path string and returns a function. The second call accepts the page config. This pattern allows TypeScript to:
RouteMap)loaderDatatype from theloaderreturntemplateagainstTemplateRegistryAt runtime,
definePageis an identity function — it returns the config unchanged.Acceptance criteria
definePage("/path")({...})signaturetemplatefield constrained tokeyof TemplateRegistryloaderreceives{ request: Request, ctx: Context }with typed paramsdefineSlotsreceives{ loaderData }typed from loader returnmetaaccepts static object or function of{ loaderData }loaderis optional (defineSlots receives{ loaderData: undefined }when omitted)Blocked by