███╗ ██╗███████╗███████╗████████╗███████╗ ██████╗ ██████╗ ██████╗ ███████╗
████╗ ██║██╔════╝██╔════╝╚══██╔══╝██╔════╝██╔═══██╗██╔══██╗██╔════╝ ██╔════╝
██╔██╗ ██║█████╗ ███████╗ ██║ █████╗ ██║ ██║██████╔╝██║ ███╗█████╗
██║╚██╗██║██╔══╝ ╚════██║ ██║ ██╔══╝ ██║ ██║██╔══██╗██║ ██║██╔══╝
██║ ╚████║███████╗███████║ ██║ ██║ ╚██████╔╝██║ ██║╚██████╔╝███████╗
╚═╝ ╚═══╝╚══════╝╚══════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝
NestForge is a high-performance backend framework designed for developers who crave the modularity and Dependency Injection (DI) of NestJS but want the memory safety and blazing speed of the Rust ecosystem.
Important
Stable Release NestForge 1.6.0 is now published on crates.io.
- Module system with
importsandexports - Dependency Injection with simple provider registration
- Managed singleton services with
#[injectable] - Controller macros (
#[controller],#[routes],#[get],#[post],#[put],#[delete]) - Request extractors (
Inject<T>,Param<T>,Body<T>,ValidatedBody<T>) - Extended request extractors (
Query<T>,Headers,Cookies,RequestId) - Built-in HTTP error type (
HttpException) - Guard and interceptor pipeline (global + route-level)
- Route-targeted middleware consumer API on the HTTP factory
- Auth primitives (
AuthUser,OptionalAuthUser,BearerToken, auth resolvers, auth guards) - Route versioning (
#[nestforge::version("1")]) - Global prefix support (
.with_global_prefix("api")) - Generated OpenAPI docs from controller metadata with runtime mounting helpers
- Swagger UI and Redoc hosting for generated OpenAPI docs
- DTO-driven OpenAPI schema generation for request and response bodies
- Optional GraphQL support through a dedicated
nestforge-graphqlcrate and factory helpers - Optional gRPC transport support through a dedicated
nestforge-grpccrate - Optional WebSocket gateway support through a dedicated
nestforge-websocketscrate - Optional scheduler support through a dedicated
nestforge-schedulecrate - Config module with env loading and schema validation
- Data layer crates (
nestforge-db,nestforge-orm,nestforge-data) - Testing helpers with module overrides plus HTTP and GraphQL test routers
- CLI for scaffolding, generators, flat or nested feature layouts, DB migrations, docs skeleton, formatting
crates/nestforge: public crate users importcrates/nestforge-core: DI, module graph, route builder, validation, resource servicecrates/nestforge-http: app bootstrap factorycrates/nestforge-macros: framework macroscrates/nestforge-cli:nestforgeCLI binarycrates/nestforge-config: env/config loading and validationcrates/nestforge-db: DB wrapper and migrations supportcrates/nestforge-orm: relational ORM abstraction layercrates/nestforge-data: non-relational data abstractionsexamples/hello-nestforge: full example appexamples/hello-nestforge-graphql: GraphQL-first example appexamples/hello-nestforge-grpc: gRPC-first example appexamples/hello-nestforge-microservices: microservice registry + in-process client example appexamples/hello-nestforge-websockets: WebSocket-first example app
git clone https://github.com/vernonthedev/nestforge.git
cd nestforge
cargo check --workspace
cargo run -p hello-nestforgeGraphQL-first example:
cargo run -p hello-nestforge-graphqlgRPC-first example:
cargo run -p hello-nestforge-grpcWebSocket-first example:
cargo run -p hello-nestforge-websocketsMicroservices-first example:
cargo run -p hello-nestforge-microservicesServer runs on:
http://127.0.0.1:3000
NestForge now uses a Rust-native direct release flow driven by the repository release script.
- Pushes to
mainrun the repository release script directly. - Conventional commits since the last version tag determine the next semver bump automatically.
- Changed crates are versioned, tagged, released on GitHub, and published to crates.io in dependency order.
- The primary published changelog is updated at
crates/nestforge/CHANGELOG.md, so conventional commits remain the source for changelog entries.
Repository setup required for publishing:
- Add
CARGO_REGISTRY_TOKENto GitHub Actions secrets. - Keep using Conventional Commits for changes you want included in the release notes.
- Expect first-time publishes for brand new crates to require a manual bootstrap publish before full automation can take over.
Install locally from this workspace:
cargo install --path crates/nestforge-cliCreate an app:
nestforge new demo-api
cd demo-api
cargo runScaffold a new HTTP app with OpenAPI docs wired in from day one:
nestforge new demo-api --openapiThe default app scaffold now creates a root src/lib.rs barrel so the binary can import app
symbols directly from the package crate:
src/
lib.rs
main.rs
app_config.rs
app_controller.rs
app_module.rs
health_controller.rs
That means generated bootstrap code looks more like:
use demo_api::AppModule;
use nestforge::prelude::*;instead of a long list of mod app_config;, mod app_module;, and similar declarations in
main.rs.
Nested controllers/ and services/ folders are only created later when you generate root-level resources into them.
Create a GraphQL-first app:
nestforge new demo-graphql --transport graphqlCreate a gRPC-first app:
nestforge new demo-grpc --transport grpcCreate a microservices-first app:
nestforge new demo-bus --transport microservicesCreate a WebSocket-first app:
nestforge new demo-events --transport websocketsGenerate code:
nestforge g module users
nestforge g resource users --module users
nestforge g resource users --module users --flat
nestforge g guard auth
nestforge g filter rewrite_bad_request
nestforge g middleware audit
nestforge g interceptor logging
nestforge g graphql users
nestforge g grpc billing
nestforge g gateway eventsFlat feature layout:
nestforge g module users --flat
nestforge g resource users --module users --flatThis keeps generated files together in the feature root:
src/users/
mod.rs
user_dto.rs
create_user_dto.rs
update_user_dto.rs
users_controller.rs
users_service.rs
Without --flat, the CLI keeps the older nested layout:
src/users/
mod.rs
controllers/
users_controller.rs
services/
users_service.rs
dto/
user_dto.rs
create_user_dto.rs
update_user_dto.rs
When you generate a resource from a real terminal, the CLI can now prompt for DTO fields so the scaffolded Create*Dto, Update*Dto, and entity DTO match your domain instead of defaulting to a single name field. For non-interactive runs, pass --no-prompt or let the CLI fall back to the default field set.
nestforge g resource users --module users --flat
nestforge g resource users --module users --flat --no-promptDB commands:
nestforge db init
nestforge db generate create_users_table
nestforge db migrate
nestforge db statusUtilities:
nestforge docs
nestforge fmtNestForge also ships with an official VS Code extension for driving the nestforge CLI directly from the editor.
- Marketplace: vernonthedev.nestforge
- Repository:
vernonthedev/nestforge-extension - Best for guided scaffolding, generator workflows, DB commands, OpenAPI docs access, Rust utilities, onboarding, and module-aware Explorer actions
The extension currently provides:
- New application and generator wizards
- Explorer context menus for module-aware generation
- DB dashboard commands and status polling
.envvalidation with quick fixes- OpenAPI docs shortcuts, format commands, run config generation, Git setup, logs, and module graph views
- Rust snippets for common NestForge patterns
use my_app::AppModule;
use nestforge::prelude::*;
NestForgeFactory::<AppModule>::create()?
.with_global_prefix("api")
.with_openapi_docs("My API", "1.0.0")?
.use_guard::<AllowAllGuard>()
.use_interceptor::<LoggingInterceptor>()
.listen(3000)
.await?;NestForge includes a lightweight nestforge::prelude for the framework items you reach for most
often in app code and generated scaffolds:
use nestforge::prelude::*;The prelude is meant to reduce repetitive framework import noise. It groups together the common factories, route/module macros, and helper types used in everyday NestForge code.
Examples of what it gives you:
NestForgeFactoryNestForgeGrpcFactoryNestForgeFactoryGraphQlExtNestForgeFactoryWebSocketExtInjectHttpException- common route and module macros such as
#[module],#[controller], and#[get]
On top of that, generated apps now include a root src/lib.rs barrel that re-exports top-level app
symbols like AppModule and AppConfig. That lets you write:
use demo_api::AppModule;
use demo_api::AppConfig;instead of pushing those imports through mod ...; declarations or deeper nested paths in
main.rs.
Use #[injectable] when you want NestForge to treat a struct as a managed provider without a
manual #[derive(Clone)].
use nestforge::{injectable, module, Inject};
#[injectable]
pub struct UsersService;
#[module(
providers = [UsersService],
exports = [UsersService]
)]
pub struct UsersModule;
#[nestforge::controller("/users")]
pub struct UsersController;
#[nestforge::routes]
impl UsersController {
#[nestforge::get("/count")]
async fn count(_users: Inject<UsersService>) -> Result<&'static str, nestforge::HttpException> {
Ok("ok")
}
}If a service needs custom setup, point the macro at a zero-arg factory:
#[injectable(factory = build_users_service)]
pub struct UsersService {
pub label: &'static str,
}
fn build_users_service() -> anyhow::Result<UsersService> {
Ok(UsersService { label: "users" })
}The same pattern works nicely for framework-managed config objects in the examples:
use nestforge::{injectable, ConfigModule, ConfigOptions};
#[injectable(factory = load_app_config)]
pub struct AppConfig {
pub app_name: String,
}
fn load_app_config() -> anyhow::Result<AppConfig> {
Ok(ConfigModule::for_root::<AppConfig>(
ConfigOptions::new().env_file(".env"),
)?)
}
#[nestforge::module(
providers = [AppConfig],
exports = [AppConfig]
)]
pub struct AppModule;Keep explicit value or factory providers for external runtime resources like database connections, clients, or other values you do not own as plain structs.
examples/hello-nestforge demonstrates:
- Root controllers (
AppController,HealthController) at app root - Feature modules (
users,settings,versioning) in Nest-style folders - CLI generators also support flat feature folders with
--flatwhen you want controllers, services, and DTOs side-by-side in the module root - CRUD controllers + services with
ResourceService<T> - Validation via
ValidatedBody<T> - Guard/interceptor usage at route level
- Generated
/docsand/openapi.jsonroutes from controller metadata - Generated OpenAPI schemas for DTOs used in
ValidatedBody<T>,Body<T>, andApiResult<T>
Export a static spec for CI/CD or frontend handoff:
nestforge export-docs
nestforge export-docs --format yaml --output docs/openapi.yaml- Config loading with
ConfigModule::for_rootand#[injectable(factory = ...)] - Versioned routes (
v1,v2)
Enable the graphql feature and merge a GraphQL schema directly into the app:
use nestforge::{async_graphql::{EmptyMutation, EmptySubscription, Object, Schema}, prelude::*};
struct QueryRoot;
#[Object]
impl QueryRoot {
async fn health(&self) -> &str {
"ok"
}
}
let schema = Schema::build(QueryRoot, EmptyMutation, EmptySubscription).finish();
NestForgeFactory::<AppModule>::create()?
.with_graphql(schema)
.listen(3000)
.await?;Enable the grpc feature and bootstrap a gRPC transport with the dedicated factory:
use nestforge::prelude::*;
NestForgeGrpcFactory::<AppModule>::create()?
.with_addr("127.0.0.1:50051")
.listen_with(|ctx, addr| async move {
tonic::transport::Server::builder()
// .add_service(MyGeneratedServer::new(MyGrpcService::new(ctx)))
.serve(addr)
.await
})
.await?;See examples/hello-nestforge-grpc for a full tonic-based setup with proto/greeter.proto,
build.rs, generated bindings, and provider resolution through GrpcContext.
Enable the websockets feature and mount a gateway directly into the HTTP app:
use nestforge::{prelude::*, Message, WebSocket, WebSocketContext, WebSocketGateway};
struct EventsGateway;
impl WebSocketGateway for EventsGateway {
fn on_connect(
&self,
_ctx: WebSocketContext,
mut socket: WebSocket,
) -> core::pin::Pin<Box<dyn core::future::Future<Output = ()> + Send>> {
Box::pin(async move {
let _ = socket.send(Message::Text("connected".into())).await;
})
}
}
NestForgeFactory::<AppModule>::create()?
.with_websocket_gateway(EventsGateway)
.listen(3000)
.await?;- Main Documentation: https://nestforge.suredoc.net
- Wiki: https://github.com/vernonthedev/nestforge/wiki
See CONTRIBUTING.md.
Apache-2.0 (LICENSE).