Docs

Routes and layouts

Define route trees, layouts, and static paths.

Open Markdown

Proa route declarations are regular Rust values. You define a route tree with Route, then turn it into an Axum Router with router_from_spec.

Route Tree

use axum::routing::get;
use proa_framework_axum::{router_from_spec, Route, RouteMode};

let (routes, metadata) = router_from_spec(vec![
    Route::layout(
        "",
        &AppLayout,
        vec![
            Route::page("/", "Home", get(home)).with_route_mode(RouteMode::Server),
            Route::page("/about", "About", get(about)).with_route_mode(RouteMode::Static),
            Route::page("/dashboard", "Dashboard", get(dashboard))
                .with_route_mode(RouteMode::ClientBrowser),
        ],
    ),
]);

The generated router contains the Axum routes. The metadata map contains precomputed metadata for those same paths and should be passed to FrameworkBuilder::with_dynamic_routes_and_metadata.

For JSON APIs, form submissions, webhooks, health checks, and other non-page routes, use Route handlers.

Route Constructors

ConstructorUse it for
Route::endpoint(path, router)Raw endpoint without generated title metadata.
Route::page(path, title, router)Page endpoint with title-only metadata.
Route::page_with_metadata(path, router, metadata)Page endpoint with a custom metadata provider.
Route::layout(path, layout, children)Metadata layout shared by child routes.

Route Modes

RouteMode describes how a route should be treated by build and client-routing tooling.

ModeUse it when
ServerThe route is rendered by the server at request time.
StaticThe route can be pre-rendered by build tooling.
ClientBrowserThe route participates in client-side browser navigation.

The mode does not replace your Axum handler. It is metadata for Proa's route tooling and export pipeline.

Dynamic Static Paths

Static dynamic routes can provide path parameters:

use std::collections::HashMap;

use axum::routing::get;
use proa_framework_axum::{Route, RouteMode};

fn blog_paths() -> Vec<HashMap<&'static str, String>> {
    vec![
        HashMap::from([("slug", "intro".to_string())]),
        HashMap::from([("slug", "routing".to_string())]),
    ]
}

let route = Route::<()>::page("/blog/:slug", "Blog Post", get(blog_handler))
    .with_route_mode(RouteMode::Static)
    .with_static_paths(blog_paths);

The keys match the :param names in the route path.

Layouts

A route layout is a metadata boundary. It implements Metadata, so title templates and Open Graph defaults can live at the layout level.

use proa_framework_axum::{Layout, Metadata};

pub struct AppLayout;

impl Metadata for AppLayout {}
impl Layout for AppLayout {}

Compose shared HTML chrome explicitly in the render tree, normally with a reusable RootDocument component:

use proa_framework_axum::RouteResponse;

RouteResponse::ssr(RootDocument { content: ProductPage })

That composition is typed and works the same way for synchronous, buffered async, and streaming routes; route metadata continues to cascade independently.

Search

Type at least 2 characters