Skip to content
Air-Cloud docs

Routes

config/routes.toml is the product's route table: which path reaches which function or container, and which paths require an end user's session. A route's posture is read off where it is declared, never off an attribute:

aircloud routes prints the resolved table and which routes require a session.

aircloud routes

Public routes

[[route]]
prefix = "/api/health"
function = "health"
org_path = "/"

prefix is an absolute path with no trailing slash. A route names exactly one target: function or container (flow and module are reserved and refused). strip_prefix = true removes the prefix before the request reaches its target. A public route never carries roles.

A public route has no end user, so a route to a function declares the node its invocations act at, org_path: aircloud check refuses one without it (route.org_path_required). "/" acts at the root, over every customer, and counts only because it is written; the generators write it, so edit it to act lower. A route to a container runs no function and declares none (route.org_path_not_invocation). See The acting node and elevation.

Public site pages need no route

The site is the fallback: every path that no route claims is answered by the site, so a page anyone may open needs no entry in config/routes.toml. /about is served by the site's /about page with nothing declared.

A [[route]] entry therefore never carries site: aircloud check refuses it with schema.unknown_key, and the message says why. Declare a site route only for pages that require a session, as an [[authenticate.route]] with site = true (below).

Routes that require a session

[authenticate]
sign_in = "/sign-in"

[[authenticate.route]]
prefix = "/api/session"
function = "session"

[[authenticate.route]]
site = true
prefix = "/account"
roles = ["staff"]

Without a session, a site page redirects to sign_in (by default /_air/session/login), and any other request is refused with session_required. roles narrows a route to the end users holding at least one of the listed roles; a session holding none of them is refused with session_role_required. Without roles, any session passes. The roles themselves are declared once in [authenticate]: see Members, roles and registration.

The roles are those of the end user's selected membership. at = "<node>" evaluates them at that node: the route passes only when one of its roles is effective there or at a node below it, through the membership's home or a grant. A product that declares workspaces must scope with at every route admitting a role of its workspace admin profile (authenticate.route_at_required, see Workspaces).

Nested site routes

A site = true route of [authenticate] protects every path under its prefix, so one entry protects a whole area of the site. Its page is src/pages/<route>/index.jsx, named in src/routes.js with the path <prefix>/*, and its sub-routes are <Routes> inside that page. With the /account route above, /account/orders/42 requires a session too: it is a sub-route of the /account page, never a separate entry.

aircloud check validates the table against the product, and aircloud routes shows it as the platform resolves it.