axum-admin 0.1.1

A modern admin dashboard framework for Axum
Documentation

axum-admin

A modern admin dashboard framework for Axum. Register your entities and get a full CRUD dashboard — search, filtering, pagination, bulk actions, custom actions, and built-in authentication — with zero frontend build step.

Inspired by Django Admin and Laravel Nova.

Features

  • CRUD out of the box — list, create, edit, delete for any entity
  • Server-side rendering via MiniJinja, no JS framework required
  • HTMX + Alpine.js embedded, no CDN or build step
  • Session-based auth with argon2; swap in your own backend
  • RBAC via Casbin — per-entity permissions tied to user roles (SeaORM feature)
  • Sidebar groups with collapsible sections and custom icons
  • Filters, search, column sorting, pagination
  • Bulk actions (delete, CSV export) and per-record custom actions
  • Lifecycle hooks: before_save, after_delete
  • Template override support
  • ORM-agnostic via DataAdapter trait
  • First-party SeaORM adapter behind the seaorm feature flag

Quick start

1. Add the dependency

cargo add axum-admin --features seaorm
cargo add axum tokio --features tokio/full

2. Set the database URL

export DATABASE_URL=postgres://user:password@localhost:5432/myapp

3. Run migrations

axum-admin ships its own migration set (users, sessions, RBAC rules). Apply them by calling Migrator::up at startup — the example below shows how. Your app's own migrations can run in the same migrator or separately.

4. Create the admin user

Use ensure_user during app initialization to create a default admin account if it doesn't exist yet:

let auth = SeaOrmAdminAuth::new(db.clone()).await?;
auth.ensure_user("admin", "secret").await?;

ensure_user is idempotent — safe to call on every startup. Change the password via the Users UI after first login.

5. Register entities and start the server

use axum_admin::{AdminApp, EntityAdmin, EntityGroupAdmin, Field};
use axum_admin::adapters::seaorm::{SeaOrmAdapter};
use axum_admin::adapters::seaorm_auth::SeaOrmAdminAuth;

#[tokio::main]
async fn main() {
    let db = sea_orm::Database::connect(std::env::var("DATABASE_URL").unwrap()).await.unwrap();

    // run migrations
    migration::Migrator::up(&db, None).await.unwrap();

    // create default admin user
    let auth = SeaOrmAdminAuth::new(db.clone()).await.unwrap();
    auth.ensure_user("admin", "admin").await.unwrap();

    let router = AdminApp::new()
        .title("My App")
        .prefix("/admin")
        .seaorm_auth(auth)
        .register(
            EntityGroupAdmin::new("Content")
                .register(
                    EntityAdmin::from_entity::<post::Entity>("posts")
                        .label("Posts")
                        .search_fields(vec!["title".to_string()])
                        .adapter(Box::new(SeaOrmAdapter::<post::Entity>::new(db.clone()))),
                ),
        )
        .into_router()
        .await;

    let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
    println!("Admin running at http://localhost:3000/admin");
    axum::serve(listener, router).await.unwrap();
}

6. Access the dashboard

cargo run
# open http://localhost:3000/admin

Change the default password under Users after first login.


See examples/blog for a full working example with categories, posts, tags, foreign keys, many-to-many relations, filters, and RBAC roles.

Full documentation coming soon.

License

MIT