Declare a model once — get the database table, the migration, a type-safe form and a full admin panel. Runique is a batteries-included web framework that brings Django's productivity to Rust, without giving up Rust's safety and performance. Built on Axum, SeaORM and Tera.
Status — honest: active development. The framework crate (
runique) is the source of truth;demo-appis a real validation app exercised against it. The admin is in beta. Nothing below is overstated — see Project status.
🌍 Languages: English | Français
model! {
Article,
table: "articles",
pk: id => Pk,
enums: { Status: [Draft="Draft", Published="Published"], },
{
title: text [required],
slug: text [unique],
body: richtext [required],
status: choice [enum(Status), default: "Draft"],
views: int [default: 0],
}
}model! generates the SeaORM entity (article::Model) and its SQL migration (runique makemigrations). A matching type-safe form is declared with #[form] (server-side validated, derivable from the schema). Register the resource and you get a full CRUD admin — list display, search, filters, permissions:
admin! {
article: article::Model => ArticleForm {
title: "Articles",
list_display: [["title", "Title"], ["status", "Status"], ["views", "Views"]],
search_fields: ["title", "body"],
list_filter: [["status", "Status", 5]],
}
}Rust has fast, low-level web building blocks — but no batteries-included framework with Django's productivity. Wiring an ORM, a template engine, a form layer and an admin together by hand is a project in itself. Runique integrates them, convention-driven, so you ship features instead of plumbing — while keeping type safety and performance.
| Django (Python) | Runique (Rust) |
|---|---|
models.py |
model! → SeaORM entity + migration |
forms.py |
#[form] type-safe forms |
admin.py |
admin! generated admin panel |
urls.py |
urlpatterns! routing macro |
| Django templates | Tera (auto-escaped) |
| QuerySet | SeaORM + search! query DSL |
| middleware | ordered middleware slots |
Full side-by-side: Runique vs Django.
Security ships on by construction, not as an add-on:
- CSRF protection with constant-time token comparison (
ct_eq) - CSP with per-response nonces, configurable via the builder
- Auth: timing-safe login (no user enumeration), Argon2 password hashing
- Sessions persisted with priority protection for authenticated users
- Password reset: DB-persisted, SHA-256-hashed, single-use, IDOR-hardened tokens
- Output sanitization (ammonia) + Tera auto-escaping, allowed-host validation
runique new myapp
cd myapp
cargo run # your app is a normal Rust binary
runique startis not how you launch the app — it's the admin code generator: it watches youradmin!declarations and regenerates the CRUD code (see Admin (beta)).
A trimmed main.rs (full version in demo-app/src/main.rs):
use runique::prelude::*;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = RuniqueConfig::from_env();
let db = DatabaseConfig::from_env()?.build().connect().await?;
RuniqueApp::builder(config)
.routes(url::routes())
.with_database(db)
.statics()
.build()
.await
.map_err(|e| -> Box<dyn std::error::Error> { Box::new(e) })?
.run()
.await?;
Ok(())
}Routes are declared with the urlpatterns! macro and return an Axum Router:
pub fn routes() -> Router {
urlpatterns! {
"/" => view!{ index }, name = "index",
"/blog/{id}" => view!{ blog_detail }, name = "blog_detail",
}
.rate_limit("/login", "login", view!(login_user), 10, 60, vec![Method::POST])
}Detailed guide: Installation
runique/→ framework crate (the product, source of truth)demo-app/→ validation app exercised against the frameworkdocs/→ EN/FR documentation
Workspace version (source of truth): 2.1.21.
runique provides:
runique new <name>runique start [--main src/main.rs] [--admin src/admin.rs]— admin code generator/watcher, not the app launcher (run the app withcargo run)runique create-superuserrunique makemigrations --entities src/entities --migrations migration/src [--force false]runique migration up|down|status --migrations migration/src
⚠️ Warning — rolling back migrationsrunique makemigrationsgenerates migrations while preserving the chronological order of the migration system. When you need to roll a migration back, prefer the SeaORM CLI: it keeps the migration tracking table synchronized with the actual schema state. Mixing rollback tooling can desynchronize migration tracking.
The admin daemon, run via runique start:
- parses your
admin!declarations insrc/admin.rs - generates CRUD code under
src/admins/ - refreshes on changes in watcher mode
It checks whether .with_admin(...) exists in src/main.rs and starts the watcher only when enabled, otherwise exits with an explicit hint.
Current beta limits: mostly resource-level permissions, the generated src/admins/ folder is overwritten, and iterative hardening is ongoing.
Admin docs: Admin
Default features: orm, all-databases.
Selectable backends: sqlite, postgres, mysql, mariadb.
CleaningMemoryStore replaces the default MemoryStore with automatic expired-session cleanup, a two-tier watermark system (128 MB / 256 MB), and priority protection for authenticated sessions (purged last, survive restarts via a DB fallback).
Full reference: Sessions
- Reported tests: 2380+ passing
- Coverage snapshot (
2026-06-17, packagerunique): functions 78.17%, lines 77.26%, regions 75.46%
cargo llvm-cov --tests --package runique --ignore-filename-regex "admin" --summary-onlyFull per-file breakdown: docs/couverture_test.md
- Installation
- Architecture
- Configuration
- Routing
- Forms
- Model/Schema
- Templates
- ORM
- Middlewares
- Flash Messages
- Examples
- Admin beta
- Sessions
- Environment variables
- Project status — continuously updated state report
- Changelog
- Runique vs Django — feature comparison
- Crates.io
- Security policy
MIT — see LICENSE