Getting started
Install the toolchain, scaffold a project, and start it.
Prerequisites
Section titled “Prerequisites”NestRS needs Rust 1.97+ (edition 2024). Install rustup if you don’t have it:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | shThen the CLI:
cargo install --locked nest-rs-cliThat’s the only thing you install by hand. The first time you run a task with
nestrs run, the CLI installs the dev toolchain it drives —
just for the recipes, bacon for watch mode,
cargo-nextest for tests — once, then never again. Set NESTRS_NO_BOOTSTRAP=1
(or pass --no-bootstrap) on CI to opt out and install them yourself.
As with any Rust dependency, cargo install nest-rs-cli and your first
nestrs run compile the crate graph once — a few minutes, cached from then on.
Every build after that is an incremental, sub-second rebuild.
Scaffold and start
Section titled “Scaffold and start”One layout, no flag to weigh: a monorepo with your domain in a shared
crates/features/ and one binary per app under apps/.
-
Scaffold.
Terminal window nestrs new hellocd hello -
Start the default app.
Terminal window nestrs run dev helloOpen http://localhost:3000/ —
Hello World, served fromcrates/features/src/hello/.apps/hello/only wires modules.
A second workload is another nestrs new inside the same tree, sharing the
same features — which is what the tutorial does next.
Hello World needs nothing else — no database, no containers, no config.
Verify it, then look at what you got (bare nestrs run lists every recipe):
$ curl http://localhost:3000/Hello WorldWhat you just generated
Section titled “What you just generated”One thin controller over one service — the shape every feature follows. Every
path out of nestrs new writes it, so a fresh project always proves itself
with a browser hit instead of a 404:
use std::sync::Arc;
use nest_rs::http::{controller, routes};
use crate::hello::HelloService;
#[controller(path = "/")]pub struct HelloController { #[inject] svc: Arc<HelloService>,}
#[routes]impl HelloController { // Every route declares a posture, and an unguarded one is flagged at boot. // This greeting is deliberately open, so it says so. #[get("/")] #[public] async fn hello(&self) -> String { self.svc.greeting() }}The #[public] is not decoration: a route with no posture is flagged at boot
(unguarded routes detected), and this one is open on purpose.
The scaffold depends on nest-rs and enables the features it needs — one
entry, whatever the app grows into. Each module page adds a feature, not a
crate; see Packages for the full menu.
Make your first change
Section titled “Make your first change”Edit the greeting in crates/features/src/hello/service.rs, save, and
nestrs run dev hot-reloads. Then curl again:
fn greeting(&self) -> String { "Hello, NestRS".to_string() // was "Hello World"}$ curl http://localhost:3000/Hello, NestRSThat’s the loop — edit, save, curl. Every reference section builds on it.
Going further
Section titled “Going further”- Tutorial — add
apps/blog/withnestrs new blogand build posts over HTTP. - The demo apps (Publish) — the multi-tenant publishing platform all the reference apps build.
- CLI — scaffold apps, features, and transport adapters.
- Fundamentals — modules, providers, guards, pipes, interceptors, filters.