API

Everything in this page is imported from @mantou/gemkit, unless stated otherwise. All of them are auto-imported, except HttpError, formatTitle and types.

Routes

page

page(options?: string | PageOptions<P, D>): ClassDecorator

Marks the default export of a page module. A string is the page title, the same as { title: options }.

@page<{ slug: string }, Post>({ load: ({ params }) => getPost(params.slug) })
export default class PostPage extends GemElement {
  @property params!: { slug: string };
  @property data?: Post;
}

layout

layout(options?: LayoutOptions<P, D>): ClassDecorator

Marks the default export of _layout.ts. A layout applies to the pages below it and is kept while navigating between them.

PageOptions

Option Type Description
title string | (ctx: RouteContext<P, D>) => string | Promise<string> The page title.
load (ctx: LoadContext<P>) => D | Promise<D> Isomorphic data loading before rendering.
meta Meta | (ctx: RouteContext<P, D>) => Meta | Promise<Meta> <meta> tags of the page.
paths (ctx: { lang: string }) => P[] | Promise<P[]> Params of the dynamic route to prerender.

LayoutOptions has load and meta.

RouteContext

interface RouteContext<P extends Params = Params, D = unknown> {
  params: P;
  data: D;
}

params are the matched route parameters. data is the result of load; for load itself, it is the result of the sibling server module load.

Meta

type Meta = Record<string, string | undefined>;

Keys containing : become <meta property>, others <meta name>. undefined values are skipped.

Server modules

A sibling <page or layout>.server.ts exports these values. They only run on the server.

load

export function load(ctx: ServerLoadContext<P>): unknown | Promise<unknown>;

Returns JSON-serializable data. It is passed to the page or layout load as data, or used directly when there is no load option. It can redirect, error or notFound.

paths

export function paths(ctx: { lang: string }): Params[] | Promise<Params[]>;

The params of the dynamic route to prerender. It is called once per language and takes precedence over the page paths option. Only pages use it.

prerender

export const prerender = false;

Disables prerendering for the route. In a layout it applies to all pages below it.

actions

export const actions: Record<
  string,
  (ctx: ServerLoadContext) => unknown | Promise<unknown>
>;

Handlers for POST <page path>?/<name>. The form action="?/login" calls actions.login. A submit button with formaction="?/logout" calls actions.logout from the same form. Return a JSON-serializable value for submitAction, or use redirect, error and notFound.

Request

ServerLoadContext

interface ServerLoadContext<P extends Params = Params> extends RequestEvent {
  params: P;
}

RequestEvent

Field Type Description
url URL The page URL, including the language prefix.
path string The page path without the language prefix, as matched by routes.
request Request The current request. Not available when prerendering.
cookies Cookies Request cookies. Not available when prerendering.
locals Locals Per-request data shared by server code.

getRequestEvent

getRequestEvent(): RequestEvent;

Returns the request event of the current server request. It throws outside a request, for example during module evaluation or after the response has finished. It is scoped per request, so the result must not be stored in a module-level variable.

redirect

redirect(status: 301 | 302 | 303 | 307 | 308, location: string): never;

Throws a redirect. location includes the language prefix. It works in handle, load, actions and API routes.

error

error(status: number, message?: string): never;

Throws an error that renders the error page with the given status.

notFound

notFound(): never;

Same as error(404, 'Not Found').

HttpError

class HttpError extends Error {
  status: number;
  message: string;
}

The error thrown by error(), and by $gemkit/api when the response is not OK.

submitAction

submitAction(form: HTMLFormElement, submitter?: HTMLElement | null): Promise<unknown>;

Submits the form without a page reload. On success, reloads the current page data and returns the action result. On redirect, navigates on the client. On error, renders the error page. The form has aria-busy during the request. It throws when the request itself fails.

Cookies

interface Cookies {
  get(name: string): string | undefined;
  set(name: string, value: string, options?: CookieOptions): void;
  delete(name: string, options?: Pick<CookieOptions, 'path' | 'domain'>): void;
}

set and delete add a Set-Cookie header to the response. A later get in the same request sees the new value.

CookieOptions

Option Type Default
path string '/'
domain string
maxAge number, seconds
expires Date
httpOnly boolean true
secure boolean true on HTTPS
sameSite 'Strict' | 'Lax' | 'None' 'Lax'

Locals

interface Locals {}

An empty interface extended by the app. Populate it in handle and read it from load, actions, API routes and server elements.

declare module '@mantou/gemkit' {
  interface Locals {
    user?: User;
  }
}

Server elements

server

Marks a class as a server-only element, or a method or field to run during server rendering.

@server()
class ServerOnly extends GemElement {}

@server() on a member runs it during server rendering and serializes its state. The result must be JSON-serializable.

lazy

lazy(options?: { on?: 'interaction' | 'load' | 'visible' }): ClassDecorator

Keeps the server HTML until the client loads the element code and hydrates. on defaults to 'interaction'.

client

client(): ClassDecorator

Renders the element only on the client. The server outputs the tag, and the client renders without hydration. The module is replaced with an empty module in the server build.

Utilities

formatTitle

formatTitle(title: string | undefined, { title, titleTemplate }: TitleOptions): string;

Applies the site title and title template, the same way Gemkit does.

TitleOptions

interface TitleOptions {
  title?: string;
  titleTemplate?: string;
}

Generated modules

i18n from $gemkit/i18n and apis from $gemkit/api are auto-imported.

$gemkit/i18n

Export Type
i18n I18n<typeof defaultMessages>
languages string[]
defaultLanguage string
prefixDefaultLanguage boolean
localizePath (lang: string, path?: string) => string

Without a locales directory, i18n is undefined, languages is empty and defaultLanguage is ''. See Internationalization.

$gemkit/api

apis is generated from the API routes. Static segments are properties, dynamic segments are function calls and HTTP methods are the final call. The input and result are inferred from the handler. A JSON response is parsed; other responses return the Response. A non-OK response rejects with HttpError.

const likes = await apis.api.likes(slug).GET({ page: 1 });

GET and DELETE send the input as the query, other methods send JSON.

Package entry points

Import Content
@mantou/gemkit The APIs in this page.
@mantou/gemkit/plugin pluginGemkit, GemkitOptions and GemkitConfig.
@mantou/gemkit/server createRenderer for a custom integration.
@mantou/gemkit/init The project initializer used by gemkit init.
@mantou/gemkit/internal Internal runtime modules. Don't use it in application code.