nextrs 0.3.1

A Next.js-style React routing framework for Rust built on Axum.
Documentation

nextrs

A Next.js-style routing framework for Rust, built on Axum and Askama.

File-based routes with page / layout / loading / middleware / route conventions, HTTP-level streaming for the loading shell, an optional typed-client pipeline (OpenAPI → React Query hooks), and optional React page.tsx pages whose data the server can seed into the client cache. Deploys to Vercel as a single Rust function, or runs anywhere as a normal Axum app.

app/
├── layout.{rs,html}      root layout, wraps every route
├── page.{rs,html,tsx}    /              — .rs/.html server-rendered, or .tsx React
├── middleware.rs         request guard, composed root-to-leaf
├── api/ping/route.rs     /api/ping      — typed HTTP handlers (get/post/…)
└── dashboard/
    ├── loading.{rs,html} streamed shell shown while the page resolves
    └── page.{rs,html}    /dashboard

Each directory is a URL segment; each filename is a convention slot. .rs wins when both .rs and .html exist. Adding a route is just adding a file — a build-time codegen step (the build feature, called from your build.rs) discovers the tree and wires the router, with no hand-written mod declarations or registry constructors.

Quick start

[dependencies]
nextrs = "0.3"
axum = "0.8"
tokio = { version = "1", features = ["full"] }
askama = "0.15"

[build-dependencies]
nextrs = { version = "0.3", features = ["build"] }
// build.rs
fn main() {
    nextrs::build::emit_registry("app", "src/main.rs", "nextrs_routes.rs").unwrap();
}
// src/main.rs
include!(concat!(env!("OUT_DIR"), "/nextrs_routes.rs"));

#[tokio::main]
async fn main() {
    let app = nextrs::router::build_router(generated_registry());
    let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
    axum::serve(listener, app).await.unwrap();
}

Features

  • build — the build-script codegen (nextrs::build, nextrs::docs): route discovery, the generated registry, and a markdown→docs+llms.txt pipeline. Depend on it under [build-dependencies] only.
  • tsx — build-time bundling of React page.tsx entries via rolldown. Heavy build-dependency tree; enable only if you use .tsx pages.
  • vercelnextrs::vercel::StreamingVercelLayer, a drop-in replacement for the upstream Vercel layer that preserves text/html streaming.

Streaming

A route with a loading slot streams the shell first and swaps in the page when its handler resolves — one HTTP response, no client framework:

[layout-open]
<div id="__nx_slot__"> …loading… </div>      ← arrives at TTFB
<template id="__nx_page__"> …page… </template> ← arrives when the handler resolves
<script> /* ~200 bytes: swap slot ← template */ </script>
[layout-close]

Status

Pre-1.0 — the API will change. See the repository for the full docs, examples (including a React + server-seeded-cache todo app), and design notes.

License

Apache-2.0