type PageError = { status: Int64, message: String }
A page-load failure. The router renders the nearest error.vyx, or a built-in error body, at status.
Type to search, or try , or .
28 exports, from std/ui.vyrn.
File-based routing as a generator: pages(dir) scans a directory of page modules at generation time and returns a router module.
import { pages } from "std/ui" import { route } from pages("./pages") fn handle(req: Request) -> Response { return route(req) }
pages/index.vyrn -> GET / pages/items/index.vyrn -> GET /items pages/items/[id].vyrn -> GET /items/:id
A page module exports what the Page contract below allows. A page with [bracket] segments exports type Params, whose field names must equal the segments; a segment that does not parse as its type is a 404 before user code runs. The router module exports route(req: Request) -> Response, type RoutePath (the regex of every route), and a typed URL helper per route. A Params mismatch, an unsupported param type or a route collision fails the load with a report at the page module.
The import graph shows the whole library.
type PageError = { status: Int64, message: String }
A page-load failure. The router renders the nearest error.vyx, or a built-in error body, at status.
fn pageError(status: Int64, message: String) -> PageError
fn notFound(message: String) -> PageError
fn badRequest(message: String) -> PageError
type PageData<T> = enum { Loading, Ready(T) }
A lazy page's view data. Loading exists only on a client soft nav; the server always renders Ready. Defined once here, because each constructor may register only once.
type Meta = { name: String, content: String }
type Head = { title: Option<String>, stylesheets: Array<String>, modules: Array<String>, scripts: Array<String>, meta: Array<Meta>, }
What a page contributes to the document head, built from noHead() and the with* combinators:
export fn head() -> Head { return withModule(noHead(), "/app.js") }
fn noHead() -> Head
fn withTitle(h: Head, title: String) -> Head
The page's title wins over its layouts'.
fn withStylesheet(h: Head, href: String) -> Head
fn withModule(h: Head, src: String) -> Head
fn withScript(h: Head, src: String) -> Head
fn withMeta(h: Head, name: String, content: String) -> Head
fn headHtml(h: Head) -> Array<Html>
Stylesheets, then modules, then scripts, then meta, each in the order added.
fn headTitleOf(h: Head) -> String
"" when the head declares no title.
type Query<T> = { run: fn() -> T }
A page's data, produced by a deferred call. The page blocks until the data lands; return a Lazy to render first and fill in later.
export fn data() -> Query<Array<Paste>> { return query(|| listPastes().pastes) }
type Lazy<T> = { run: fn() -> T }
A page's data when the page renders lazily: on a client soft nav the shell paints first and the data region fills in. A distinct type, not a flag, because laziness decides the view's type (PageData<T>), and the generator reads types, not function bodies.
type ParamQuery<P, T> = { run: fn(P) -> T }
A page's data when it depends on the route parameters. P is the page's own Params, which std/ui cannot name.
export fn data() -> ParamQuery<Params, Result<Paste, PageError>> { return paramQuery(|p: Params| fetch(p.id)) }
type ParamLazy<P, T> = { run: fn(P) -> T }
fn query<T>(run: consume fn() -> T) -> Query<T>
fn lazy<T>(q: consume Query<T>) -> Lazy<T>
The server always has the data, so SSR is unaffected.
fn paramQuery<P, T>(run: consume fn(P) -> T) -> ParamQuery<P, T>
fn paramLazy<P, T>(q: consume ParamQuery<P, T>) -> ParamLazy<P, T>
fn noQuery() -> Query<Unit>
The default data for a page that declares none.
gen fn pages(dir: String) -> String
Scans dir for .vyrn and .vyx pages and returns the router module.
gen fn pagesThemed(dir: String, theme: String) -> String
pages, with every .vyx page's classes checked against theme. theme resolves relative to the importing module.
gen fn pagesClient(dir: String) -> String
The client page bundle for dir.
gen fn pagesClientThemed(dir: String, theme: String) -> String
pagesClient with a theme; the server side is pagesThemed.
11 test blocks in std/ui.vyrn. CI runs all of them.
6 programs in examples/ import this module. Each runs as WebAssembly and as a native binary.