Skip to content

Routes & introspection

Plugin routes, path helpers, RouteValue / MetaMap, match captures.

Author guide — edit docs/.vitepress/plugin-sdk-guides/routes.md, then pnpm docs:generate.

Adding routes from a plugin

rust
app.get("/_devtools/app", handler);
app.post("/_tasks/enqueue", handler);
app.mount("/api", |r| { /* nested router */ });

Examples: static (mount + /*path), devtools, openapi, i18n prefix, tasks HTTP enqueue.

Guard sensitive surfaces (bearer token, cli_mode, localhost-only) — see tasks enqueue + DevTools release guard.

Path helpers

rust
use sova_core::extend::{normalize_path, to_brace_path, join_paths};

Static files and OpenAPI rely on consistent path normalization.

Route introspection (RouteValue / MetaMap)

Plugins attach typed metadata to routes for other systems:

ConsumerMeta
openapioperation schemas
vldvalidation rules / coverage
metaper-page OG / robots / sitemap
rust
use sova_core::extend::{MetaMap, RouteValue, Needs};
// attach via router builders / with_update patterns used in those crates

If your plugin needs OpenAPI or validation awareness, follow vld/openapi for RouteTable / RouteEntry iteration rather than inventing a parallel registry.

Match captures

After the router matches:

TypePurposeUsed by
MatchedRoute / MatchedRouteCapturepattern + capturesdevtools, observability
MatchedMeta / MatchedMetaCaptureoverlay page metameta
rust
use sova_core::{MatchedRouteCapture, Request};

let cap = MatchedRouteCapture::new();
req.set(cap.clone());
let res = next(req).await;
let pattern = cap.get(); // Option after match

Install capture before next so the router can fill it.

Needs on routes

See State & dependencies — session uses Needs::<CookieLayerPresent> so session routes refuse to build without cookies MW.