Getting started
In a dev container (recommended)
Section titled “In a dev container (recommended)”The repository ships a dev container that provisions Rust, Postgres, Redis and the dev tooling in one step. It is the fastest path to a working setup.
-
Install Docker and the VS Code Dev Containers extension.
-
Clone the repository.
Terminal window git clone https://github.com/NestRS/NestRS.git nestrscd nestrs -
Open the folder in VS Code and accept Reopen in Container when prompted.
-
Run the baseline app.
Terminal window just dev# → http://localhost:3001 returns "Hello World"
just dev runs under bacon — every save triggers an incremental rebuild and
a restart. Edit a handler, save, hit the endpoint again.
On your own machine
Section titled “On your own machine”If you prefer a local toolchain:
# Rust 1.75 or newercurl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Dev toolingcargo install --locked just bacon cargo-nextestrustup component add llvm-tools-preview
# Clone and rungit clone https://github.com/NestRS/NestRS.git nestrscd nestrsjust devApps that need Postgres (api) or Redis (worker) read their connection
string from NESTRS_DATABASE__URL / NESTRS_QUEUE__URL. The bare app,
auth, mcp and chat examples need neither.
Run the examples
Section titled “Run the examples”The workspace ships several example apps. Each is a separate runnable binary; they share the same workspace and the same building blocks.
just dev # bare app baseline :3001just dev auth # OAuth2 / JWT issuer :3002just dev api # REST + GraphQL + DB :3003 (requires `just db up` once)just dev mcp # MCP server :3004just dev chat # WebSocket gateway :3005just dev worker # background jobs (headless)Your first endpoint
Section titled “Your first endpoint”A complete service with a provider, a controller and a module:
Directorysrc/
- main.rs
- app.rs
Directoryhello/
- module.rs
- service.rs
- controller.rs
use nestrs_core::injectable;
#[injectable]#[derive(Default)]pub struct HelloService;
impl HelloService { pub fn greeting(&self) -> String { "Hello World".to_string() }}use std::sync::Arc;use nestrs_http::{controller, routes};use super::service::HelloService;
#[controller(path = "/")]pub struct HelloController { #[inject] svc: Arc<HelloService>,}
#[routes]impl HelloController { #[get("/")] async fn hello(&self) -> String { self.svc.greeting() }}use nestrs_core::module;use super::{controller::HelloController, service::HelloService};
#[module(providers = [HelloService, HelloController])]pub struct HelloModule;use nestrs_core::module;use crate::hello::module::HelloModule;
#[module(imports = [HelloModule])]pub struct AppModule;use nestrs_core::App;use nestrs_http::HttpTransport;mod hello;mod app;use app::AppModule;
#[tokio::main]async fn main() -> anyhow::Result<()> { App::new::<AppModule>()? .transport(HttpTransport::new().bind("0.0.0.0:3001")) .run() .await}[dependencies]anyhow = "1"tokio = { version = "1", features = ["macros", "rt-multi-thread"] }nestrs-core = { git = "https://github.com/NestRS/NestRS" }nestrs-http = { git = "https://github.com/NestRS/NestRS" }cargo run# → GET http://localhost:3001 returns "Hello World"What just happened
Section titled “What just happened”#[injectable]markedHelloServiceas a provider;App::build()constructs it once and shares it asArc<HelloService>.#[controller]+#[routes]generated a poemEndpointthat mounts the verb methods on the controller’s path.#[module]registered both with the DI container;imports = [...]onAppModuleopened access from the root.App::newverified the access graph — every#[inject]resolves to something the importing module can reach — and returnedResult: a bad wiring fails here with a clear error.
Next steps
Section titled “Next steps”- Tutorial — build a complete feature with persistence and authz.
- Core concepts — the module model, the DI graph, the data context.
- HTTP — controllers, pipes, guards, filters, interceptors in depth.