A modern, self-hosted Content Management System built entirely in Rust β fast, type-safe, and batteries included.
Avored Rust CMS is an open-source headless CMS and admin platform built with Rust, Leptos, Axum, and SurrealDB. It combines a reactive server-side-rendered admin UI with a clean REST API, giving you full control over your content without sacrificing developer experience.
Most CMS platforms are either too heavy (monolithic PHP stacks), too limiting (SaaS-only), or require a patchwork of services to get started. Avored Rust CMS aims to be a single, self-contained binary that you can drop on a server and have a production-grade content management system running in minutes β with no external database server, no container orchestration, and no JavaScript runtime required on the server.
Built in Rust from the ground up, it targets:
- Performance β near-zero overhead, handling thousands of requests with minimal memory footprint.
- Safety β the Rust type system and Leptos's reactive model eliminate entire classes of runtime errors.
- Developer productivity β a single codebase for both the admin UI (Leptos/WASM) and the backend API (Axum), with shared types across the boundary.
- True self-hosting β embedded SurrealDB means no external dependencies. Clone, configure, run.
- Entities β define custom content types (e.g. Blog Post, Product, FAQ) with flexible attribute schemas.
- Attributes β attach typed fields (text, number, date, boolean, relation) to any entity.
- Collections β group and organise content records across entities.
- Entity Identifier Management β rename and re-slug entity identifiers without losing data.
- Custom Workflows β create multi-step publishing workflows (e.g. Draft β Review β Published).
- Workflow Executions β track the full execution history of every workflow run.
- Activate / Deactivate β toggle workflows on or off at any time via the API.
- Managed Templates β create, update, and delete reusable email templates from the admin or API.
- Paginated Listing β browse all templates with server-side pagination.
- JWT-based Authentication β stateless, secure token authentication for every API request.
- Argon2 Password Hashing β industry-standard password hashing with configurable salt.
- Role-based Access Control β user model with granular permission support.
- CORS Configuration β restrict API access to trusted origins via environment variable.
- Multi-environment Secrets β separate
.envfiles per environment (local,dev,test,stag,prod).
- Full CRUD for Entities, Collections, Email Templates, and Workflows.
- Versioned API (
/api/v1/) for stable, public-facing content access. - Auth endpoint β
/api/auth/login - Setup endpoint β
/api/misc/setupfor first-run administrator bootstrapping. - OpenAPI-friendly route structure (GET / POST / PUT / PATCH / DELETE per resource).
- Server-Side Rendered admin panel powered by Leptos with client-side hydration.
- Reactive components β real-time UI updates without full page reloads.
- i18n / Internationalisation β built-in multi-language support via
rust-i18n. - Local browser storage β preferences and session data persisted via
gloo-storage.
- Embedded SurrealDB β no external database required; data lives in
rocksdb://data/avored.db. - Schema migrations β applied automatically on startup.
- In-memory mode β available for testing (
kv-memfeature).
- Single binary β compile once, run anywhere.
- Vite frontend pipeline β fast asset bundling with hot-module replacement in development.
- WASM-optimised release profile β size-optimised (
opt-level = 'z', LTO) WASM bundle for production. - Static asset serving β built-in file serving for
/publicand/assetsroutes.
The full improvement, tech-debt, and product roadmap is maintained in the roadmap document.
The roadmap's proposed next product phase focuses on content modeling, asset management, testing, and delivery:
| Workstream | GitHub issues |
|---|---|
| Field schema and asset storage foundation | #398, #399 |
| Admin asset browser and richer field types | #400, #401 |
| Playwright coverage, Tailwind patterns, and quality checks | #402, #403, #404 |
| Documentation and deployment automation | #405, #406 |
Tailwind CSS is already used by the project; the planned work standardizes its use across admin forms rather than introducing a new styling framework.
| Layer | Technology |
|---|---|
| Language | Rust (2021 edition) |
| Web Framework | Axum 0.8 |
| Frontend UI | Leptos 0.8 (SSR + WASM hydration) |
| Database | SurrealDB 3 (embedded RocksDB) |
| Auth | JWT (jsonwebtoken) + Argon2 |
| Asset Bundling | Vite + cargo-leptos |
| i18n | rust-i18n |
| Async Runtime | Tokio |
- Rust and Cargo
- The
wasm32-unknown-unknownRust target - Node.js and npm
- The
cargo-leptoscommand-line tool
Install the Rust target and cargo-leptos if you don't already have them:
rustup target add wasm32-unknown-unknown
cargo install cargo-leptos --lockedNew contributors should start here:
- Architecture overview
- API route/versioning reference
- Improvement, tech-debt, and product roadmap
- Contributing guide
-
Clone the repository and enter the project directory:
git clone https://github.com/avored/avored-rust-cms.git cd avored-rust-cms -
Install the JavaScript dependencies:
npm install
-
Create a
.envfile in the project root with the following local-development settings:APP_ENV=local AVORED_DATABASE_NAMESPACE=avored AVORED_DATABASE_NAME=avored_cms AVORED_DATABASE_FOLDER_NAME=rocksdb://data/avored.db AVORED_PASSWORD_SALT=replace-with-a-random-secret AVORED_JWT_SECRET=replace-with-another-random-secret AVORED_CORS_ALLOWED_APP_URL=http://localhost:3000
Generate a separate random value for each secret, then replace the placeholders:
openssl rand -hex 32
Running the command twice produces independent values. Keep
.envprivate and do not commit it. For other environments, the application loads.env.dev,.env.test,.env.stag, or.env.prodwhenAPP_ENVis set todev,test,stag, orprod, respectively. -
Build the frontend assets:
npm run build
-
Start the development servers:
npm run dev
This runs Vite and
cargo leptos watch. The CMS server listens on port 3000. -
Open http://localhost:3000/setup and create your administrator account. After setup, sign in at http://localhost:3000/auth/login.
The application uses embedded SurrealDB storage, so no separate database server is needed. It creates the database and applies schema migrations on startup. With the settings above, the database is stored at data/avored.db.
| Command | Description |
|---|---|
npm run build |
Build the Vite frontend assets |
npm run vite |
Start the Vite development server |
npm run leptos |
Start the Leptos development watcher |
npm run dev |
Run Vite and the Leptos watcher together |
cargo test |
Run the Rust test suite |
The Rust code is a Cargo workspace with three packages:
avored-corecontains domain models, application use cases, and shared error types.avored-webcontains the Leptos UI and hydration library.avored-apicontains the Axum server, API handlers, persistence, and server binary.
The workspace Cargo-Leptos project pairs the avored-api binary with the avored-web library. Cargo features are additive, so use --no-default-features on direct package builds to ensure only the requested feature is active.
| Build | Command |
|---|---|
| SSR server | cargo build -p avored-api --no-default-features --features ssr --bin avored-api |
| Hydration WASM library | cargo build -p avored-web --target wasm32-unknown-unknown --no-default-features --features hydrate --lib |
| Full Leptos application | cargo leptos build --project avored-rust-cms --release |
Cargo-Leptos builds the server with ssr and the library with hydrate, disabling defaults for each target. The hydrate-only dependency graph should not contain Axum or SurrealDB.
avored-api depends on avored-core and avored-web; the web package remains independent of the database-backed core so its WASM build cannot pull in server persistence dependencies. The workspace split establishes package and feature boundaries; it is not yet a claim of measured compile-time improvement. See the workspace decision for the rationale and remaining measurement work.
Do not use development secrets in production. Set APP_ENV=prod in .env and provide the required production settings in a protected .env.prod file. Use strong, unique values for AVORED_PASSWORD_SALT and AVORED_JWT_SECRET, restrict AVORED_CORS_ALLOWED_APP_URL to trusted origins, and serve the application behind HTTPS.
Contributions are welcome. Please read the contributing guide before opening a pull request. In short: open or reference an issue, keep changes small and scoped, update docs when behaviour changes, and ensure the relevant Rust and frontend checks pass.
This repository does not currently declare a license in its root metadata or files. Before redistributing or publishing forks, confirm the intended licensing terms with the project maintainers.