{greeting.data?.data.message}
; } ``` When `cargo dev` is running, changes to annotated endpoints automatically refresh the generated client. Production builds regenerate it through the configured build process as well, so client generation is not normally a step you need to think about. To refresh the client without starting the application, you can run: ```bash title="Terminal" cargo nextrs client generate # or: nextrs client generate ``` `.nextrs/client` is a genuine npm workspace dependency linked into root `node_modules`. Its package exports point to built JavaScript and `.d.ts` declarations, so a brand-new nested `.ts` or `.tsx` file resolves both imports in TypeScript and VS Code. No relative generated import, declaration shim, or `tsconfig.paths` entry is required. `nextrs new` also creates the root `.gitignore`. The whole generated `.nextrs/client` package is ignored. A small tracked template under `.nextrs/template/client` lets `cargo dev` and client generation recreate the package before TypeScript or the browser build consumes it. ## Run the dev loop The default shortcut is: ```bash title="Terminal" cargo dev ``` These direct forms run the same watcher: ```bash title="Terminal" cargo nextrs dev nextrs dev ``` `cargo dev` is a scaffolded Cargo alias. The unified dev command refreshes the generated client, builds the app, starts it, and watches relevant Rust, frontend, template, asset, and environment files. ## Why `app.rs`, `main.rs`, `api/index.rs`, and `build.rs` all exist - `src/app.rs` constructs the shared Axum `Router`. Application-wide layers and domain wiring belong here. - `src/main.rs` only starts the local/container process and calls that shared app. - `api/index.rs` is a thin Vercel adapter required by Vercel's current Rust entry convention. Do not put application logic there. - `build.rs` is normal Rust build-script infrastructure. It discovers the `app/` tree, generates the route/OpenAPI registry, and bundles React pages. If Vercel is not a deployment target, remove `api/index.rs`, its `index` Cargo target, the Vercel-only dependencies, `vercel.json` (and the `[vercel]` table in `nextrs.toml`), and the prebuilt-deploy script together. Keep `src/app.rs`, `src/main.rs`, and `build.rs`. ## Where to go next - [Routing Conventions](/docs/conventions) - [A Rust-First Tour](/docs/rust-first-tour) - [Client Generation: Step by Step](/docs/client-codegen) - [Porting an Existing App](/docs/porting) - [Deploy to Vercel](/docs/deploy-vercel) or [Deploy with Docker](/docs/deploy-docker) ### Choosing the development app Run `nextrs dev` from the application directory. It selects the current Cargo package's `default-run` binary, or its sole runnable binary. The generated `cargo dev` alias is optional shorthand for the same framework command. Use `nextrs dev --bin NAME` only to choose another binary or resolve an ambiguous workspace. The framework command is `nextrs`, not `next`. --- # Routing Conventions > Exact route filenames, free colocation, dynamic URLs, APIs, and server prefetch Directories under `app/` describe URL segments. Files only acquire framework meaning when their names match a convention exactly; every other `.ts`, `.tsx`, or Rust module is ordinary colocated application code. ## Recognized files | File | Role | |---|---| | `page.tsx` | React page for this URL | | `layout.tsx` | React layout for this segment and descendants | | `loading.tsx` | React pending UI | | `not-found.tsx` | React 404 surface for this subtree | | `middleware.rs` | Request guard or transformation | | `route.rs` | Axum handlers named for HTTP methods | | `prefetch.rs` | Server data that warms a sibling `page.tsx` query cache | New applications should use the React conventions above. `prefetch.rs` requires a `page.tsx` sibling because it feeds that React page's cache.Loading…
; } ``` A `prefetch.rs` beside `page.tsx` returns a `nextrs::QuerySeed`. On a hard load, nextrs includes those cache entries in the page shell. On link intent and soft navigation, the app shell warms the route chunk and data. See [React Pages & Server Prefetch](/docs/react-server-props). ## Middleware `middleware.rs` files compose from root to leaf and run before pages and API handlers: ```rust use axum::body::Body; use http::Request; use nextrs::conventions::MiddlewareResult; pub async fn handle(mut req: Request) -> MiddlewareResult { let Some(user) = authenticate(&req).await else { return MiddlewareResult::response(( http::StatusCode::SEE_OTHER, [("location", "/login")], )); }; req.extensions_mut().insert(user); MiddlewareResult::next(req) } ``` ## Typed API routes `route.rs` exports async functions named `get`, `post`, `put`, `patch`, `delete`, `head`, or `options`. Axum extractors define the inputs and concrete response types define the output: ```rust use axum::{extract::Path, Json}; use serde::Serialize; use utoipa::ToSchema; #[derive(Serialize, ToSchema)] pub struct User { pub id: u64 } #[nextrs::api] pub async fn get(Path(id): PathLoading…
; return (Loading todos…
; } ``` The app shell can show this component while the route bundle and data become available. Keep it small and independent of the data it is waiting for. ## Prefetch server data Add `prefetch.rs` beside the same `page.tsx` to warm its React Query cache. On a hard load, nextrs puts those entries into the page shell before React mounts. On link intent and soft navigation, the app shell preloads the target route and calls the same prefetch path automatically. The page itself continues using an ordinary generated hook: ```tsx import { useGetApiTodos } from "@mysite/client/react-query"; export default function TodosPage() { const { data, isPending } = useGetApiTodos(); if (isPending) returnLoading todos…
; returnLoading…
; if (todo.isError) { return{todo.error instanceof HttpError && todo.error.status === 404 ? "Not found" : "Could not load the todo"}
; } return{todo.data.data.title}
; } const options = getGetApiTodosByIdQueryOptions(42, { neighbors: true }); ``` Query data is inferred from the fetch function. There is no need to write a response generic or annotate callback data. ## 5. Add a typed request body and mutation Add a patch handler to the same `route.rs`: ```rust #[derive(Deserialize, ToSchema)] pub struct UpdateTodoRequest { pub done: bool, } #[nextrs::api( patch, operation_id = "updateTodo", request_body = UpdateTodoRequest, responses((status = 200, description = "Updated todo", body = Todo)), )] pub async fn patch( Path(id): Path