Options and files
The options of framework(), the files src/routes/ may hold, and what each entry of @k8ordo/server exports. How to use each is covered in the guides.
On this page
Four entries
@k8ordo/server splits its entries by where the code runs. A deployed application loads only runtime and serve, and neither loads Vite.
@k8ordo/server:framework(), the plugin forvite.config.ts. It loads Vite.@k8ordo/server/runtime: what code inside the handler imports. It uses nothing only Node.js has, so it runs wherever the handler does.@k8ordo/server/serve:serve(), which runs the build on Node.js.@k8ordo/server/vercel:vercel(), the plugin that writes Vercel’s output.
framework
Import from @k8ordo/server
The Vite plugin that makes the application run on a server. It returns an array that includes React’s plugin and the RSC pipeline; put it in plugins as it is.
framework(options?: ServerOptions): PluginOption[]Parameters
options.routesDirstring- The route directory, relative to the project root;
src/routesby default. The generated files still go to.k8ordo/.
Returns
PluginOption[] — An array of Vite plugins.
vite.config.tsimport { framework } from '@k8ordo/server';
import { defineConfig } from 'vite';
export default defineConfig({ plugins: [framework()] });Route files
The files a directory under src/routes/ may hold, what each exports and what it receives. Anything else goes under a directory whose name starts with _.
page.tsx
- Default export: the page component that answers its directory’s URL. It receives
paramsandpathname. - In this mode it also receives
request: the request’s headers and cookies. paramsSchema: a schema that validates the parameters, anything implementing Standard Schema. Optional.search: the url schema the page reads. A page that declares it receives that slot assearch.
layout.tsx
- Default export: a component that wraps what renders below it, received as
children. It also receivesparamsandpathname, withparamstyped as strings. - In this mode it also receives
request: the request’s headers and cookies. paramsSchema: runs for every page below, before the page’s own.
not-found.tsx
- Default export: a component that answers any URL below its directory that no route matched. It receives
paramsandpathname, and theparamsare unvalidated strings. - In this mode it also receives
request: the request’s headers and cookies. - In this mode it answers under a 404, and each directory may hold its own.
error.tsx
- A
'use client'file. - Default export: a component receiving
errorandreset, rendered in place of what is below it when that throws. It receives noparams.
loading.tsx
- Default export: a component with no props, rendered as the
<Suspense>fallback while the page below it loads.
redirect.ts
- Default export: the target as a string, or
{ to, permanent }.tois a pattern of the route table, filled with the matched parameters. - In this mode it answers
GETandHEADwith a307, or a308whenpermanent.
route.ts
- Exports named after methods, such as
GETandPOST: functions that receive{ request, params }and return aResponse. paramsSchema: validates the parameters, as a page’s does.- In this mode any of the seven methods may be exported. Without a
HEAD, it answers with theGETresponse, body left off.
guard.ts
- Default export: a function that receives
{ request, params }. Returning aResponseends the request there; returning nothing lets it through. It runs before anything below its directory answers.
What route files use from @k8ordo/router
The types and functions route files use come from @k8ordo/router, not from the mode package, so a page reads the same under either mode.
PageProps<pattern>: the props a page receives.LayoutProps<pattern>: the props a layout receives.ErrorProps: the props anerror.tsxreceives.RouteContext<pattern>: what aroute.tsfunction receives.notFound(): thrown from a page, it has the nearestnot-found.tsxanswer under a 404.href(): builds a URL typed against the route table.usePathname()anduseMatch(): hooks that read the current URL in the browser.usePendingPathname(): a hook that reads where a navigation under way is going.
cookies
Import from @k8ordo/server/runtime
Reads and writes the request’s cookies, from a guard.ts, a route.ts or a Server Action.
cookies(): CookiesFields
get(name: string) => string | undefined- Reads a value by name;
undefinedwhen there is none. has(name: string) => boolean- Whether a cookie of that name is there.
set(name: string, value: string, options?: CookieOptions) => void- Writes a value, with the attributes of
CookieOptionsas the third argument. delete(name: string, scope?: { path?: string; domain?: string }) => void- Deletes a cookie. Pass the
pathanddomainit was written with.
Caveats
- A read sees the cookies the request carried, with what was written earlier in the same request on top.
- Every write reaches the browser as a
Set-Cookieon the answer, whatever the answer is. - It throws when called while a page renders; a page reads
request.cookies.
cookies().get('session');
cookies().set('session', token, { maxAge: 60 * 60 * 24 });
cookies().delete('session');CookieOptions
Import from @k8ordo/server/runtime
The attributes passed to cookies().set() as its third argument. Leave them out, and they are what a session wants.
type CookieOptions = {
path?: string;
domain?: string;
maxAge?: number;
expires?: Date;
httpOnly?: boolean;
secure?: boolean;
sameSite?: 'strict' | 'lax' | 'none';
};Fields
pathstring/by default.domainstring- Not set by default.
maxAgenumber- How long it lasts, in seconds.
0expires it at once. expiresDate- When it expires, as a
Date. httpOnlybooleantrueby default: a page’s script cannot read it.securebooleantrueby default: sent over HTTPS only. For a request over plain HTTP to this machine (localhostand the like), the default isfalse.sameSite'strict' | 'lax' | 'none''lax'by default.'none'only goes withsecure.
responseHeaders
Import from @k8ordo/server/runtime
Returns the Headers the final response will carry. What is set here goes on the answer, whether a page, its payload or a Response a guard returned.
responseHeaders(): HeadersCaveats
- A header the answer already carries is replaced.
- It throws outside a
guard.ts, aroute.tsor a Server Action.
requestHeaders
Import from @k8ordo/server/runtime
Returns the headers the request arrived with — for a Server Action, which receives its arguments rather than the request.
requestHeaders(): HeadersCaveats
- It throws outside a
guard.ts, aroute.tsor a Server Action.
redirect
Import from @k8ordo/server/runtime
Ends a Server Action and sends the visitor to another URL.
redirect(to: string): neverParameters
tostring- Where to go. It is sent as written, so build it with
href().
Returns
never — It never returns; it throws.
Caveats
- It ends by throwing, so do not call it inside a
try. - A form posted before JavaScript arrived is answered with a
303; a call from the client runtime with a payload telling the router where to go.
nonce
Import from @k8ordo/server/runtime
Returns the nonce this answer’s inline scripts carry, new for every request.
nonce(): stringCaveats
- It returns the same value anywhere the request is being answered, the render included.
- It throws outside a request.
Guard
Import from @k8ordo/server/runtime
The type of what a guard.ts default-exports, given its directory’s pattern.
type Guard<P extends string = string> = (context: {
request: Request;
params: ParamsOf<P>;
}) => Response | void | Promise<Response | void>;Fields
requestRequest- The
Requestas it arrived. paramsParamsOf<P>- The parameters of its directory’s pattern, as the URL’s strings: a guard runs before any schema.
RouteRequest
Import from @k8ordo/server/runtime
The type of the request a page, a layout and a not-found.tsx receive. Both fields are read-only.
type RouteRequest = {
headers: Headers;
cookies: ReadonlyMap<string, string>;
};Fields
headersHeaders- The request’s headers.
cookiesReadonlyMap<string, string>- The
Cookieheader read by name. When a name appears twice, the first wins.
RedirectTarget
Import from @k8ordo/server/runtime
The type of what a redirect.ts default-exports. Write satisfies RedirectTarget to check the shape where it is written.
type RedirectTarget =
| string
| { to: string; permanent?: boolean };serve
Import from @k8ordo/server/serve
Runs the build on a Node.js HTTP server. Once it is listening, it returns where it listens and how to stop it.
serve(options?: ServeOptions): Promise<Server>Parameters
options.diststring- The build output directory;
distby default, resolved from the working directory. options.portnumber- The port to listen on;
3000by default.0lets the system pick a free one. options.hoststring- The host to listen on. The default,
localhost, is reachable from the same machine only; pass0.0.0.0inside a container and the like.
Returns
Promise<Server> — The server, once it is listening.
Fields
portnumber- The port it actually listens on.
urlstring- Its URL,
http://<host>:<port>. close() => Promise<void>- Stops the server, returning a promise that settles once it has stopped.
Caveats
- A
GETorHEADnaming a file indist/client/gets that file; everything else goes to the handler. - When the handler throws, it answers a
500with the bodyinternal error, and logs what was thrown.
serve.jsimport { serve } from '@k8ordo/server/serve';
const server = await serve({ port: 3000 });
console.log(server.url);vercel
Import from @k8ordo/server/vercel
A plugin that has vite build also write .vercel/output/ in the shape of Vercel’s Build Output API (v3). Put it beside framework().
vercel(): PluginReturns
Plugin — A Vite plugin.
Caveats
- The handler is bundled with every dependency, so one that ships a native binary, or reads its own files by path, does not work.
vite.config.tsimport { framework } from '@k8ordo/server';
import { vercel } from '@k8ordo/server/vercel';
import { defineConfig } from 'vite';
export default defineConfig({ plugins: [framework(), vercel()] });