{"id":41452757,"url":"https://github.com/kent8192/reinhardt-web","last_synced_at":"2026-06-04T00:04:44.251Z","repository":{"id":320647358,"uuid":"1070756049","full_name":"kent8192/reinhardt-web","owner":"kent8192","description":"Django/DRF-inspired full-stack web framework for Rust","archived":false,"fork":false,"pushed_at":"2026-04-19T15:38:53.000Z","size":38690,"stargazers_count":9,"open_issues_count":28,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-04-19T16:33:41.150Z","etag":null,"topics":["api-framework","async","authentication","dependency-injection","django","frontend-web","full-stack","graphql","modular","orm","rest-api","rust","web-framework","websockets"],"latest_commit_sha":null,"homepage":"https://reinhardt-web.dev","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kent8192.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-06T11:54:52.000Z","updated_at":"2026-04-19T14:55:04.000Z","dependencies_parsed_at":"2026-01-01T01:07:25.380Z","dependency_job_id":"d704691c-f63e-4a67-8d8b-fc47a7b46269","html_url":"https://github.com/kent8192/reinhardt-web","commit_stats":null,"previous_names":["kent8192/reinhardt-rs","kent8192/reinhardt-web","kent8192/reinhardt"],"tags_count":1129,"template":false,"template_full_name":null,"purl":"pkg:github/kent8192/reinhardt-web","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kent8192%2Freinhardt-web","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kent8192%2Freinhardt-web/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kent8192%2Freinhardt-web/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kent8192%2Freinhardt-web/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kent8192","download_url":"https://codeload.github.com/kent8192/reinhardt-web/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kent8192%2Freinhardt-web/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32035278,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-20T00:18:06.643Z","status":"online","status_checked_at":"2026-04-20T02:00:06.527Z","response_time":94,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-framework","async","authentication","dependency-injection","django","frontend-web","full-stack","graphql","modular","orm","rest-api","rust","web-framework","websockets"],"created_at":"2026-01-23T15:30:54.533Z","updated_at":"2026-06-04T00:04:44.244Z","avatar_url":"https://github.com/kent8192.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"branding/logo.png\" alt=\"Reinhardt Logo\" width=\"200\"/\u003e\n\n  \u003ch1\u003eReinhardt\u003c/h1\u003e\n\n  \u003ch3\u003e🦀 Django's productivity, Rust's performance\u003c/h3\u003e\n\n  \u003cp\u003e\u003cstrong\u003eA composable, batteries-included web framework for Rust\u003c/strong\u003e\u003c/p\u003e\n  \u003cp\u003eBuild with the integrated experience of Django/DRF,\u003cbr/\u003e\n  or compose only the pieces you need.\u003c/p\u003e\n\n[![Crates.io](https://img.shields.io/crates/v/reinhardt-web.svg)](https://crates.io/crates/reinhardt-web)\n[![Documentation](https://docs.rs/reinhardt-web/badge.svg)](https://docs.rs/reinhardt-web)\n[![License](https://img.shields.io/badge/license-BSD--3--Clause-blue.svg)](LICENSE)\n[![codecov](https://codecov.io/gh/kent8192/reinhardt-web/graph/badge.svg)](https://codecov.io/gh/kent8192/reinhardt-web)\n[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/kent8192/reinhardt-web)\n\n\u003c/div\u003e\n\n---\n\n## Quick Navigation\n\n- [Who is Reinhardt For?](#who-is-reinhardt-for)\n- [Quick Start](#quick-start)\n- [Why Reinhardt?](#why-reinhardt)\n- [Key Features](#key-features)\n- [Installation](#installation)\n- [Getting Started Guide](#getting-started-guide)\n- [Available Components](#available-components)\n- [Ecosystem](#ecosystem)\n- [API Stability](#api-stability)\n\n## Who is Reinhardt For?\n\nReinhardt is designed for developers who:\n\n- **Know Django/DRF** and want the same productivity in Rust\n- **Use Axum/Actix** but miss Django's batteries (ORM, admin, auth, DI)\n- **Want an integrated Rust web stack** without assembling everything from scratch\n- **Want incremental adoption** -- start with just DI or ORM, grow into a full stack later\n\nIf you have written `ModelSerializer` or `Depends()` before, Reinhardt will feel like home.\n\n## Quick Start\n\n\u003c!-- reinhardt-version-sync --\u003e\n```bash\n# Currently a pre-release: --version is required. Once 0.1.3 stable ships,\n# --version becomes optional (and acts as an opt-in reproducibility pin).\ncargo install reinhardt-admin-cli --version \"0.1.0-rc.30\"\n\nreinhardt-admin startproject my-api \u0026\u0026 cd my-api\ncargo run --bin manage runserver  # Visit http://127.0.0.1:8000\n```\n\nFor a full walkthrough, see the [Getting Started Guide](#getting-started-guide).\n\nNew to Reinhardt? Start with the default setup first. You can adopt a smaller custom stack later if needed.\n\n## Why Reinhardt?\n\nRust web development is powerful, but it often starts with choosing and wiring together many separate libraries.\n\nReinhardt takes a different approach: integrated batteries when you want them, composable parts when you don't.\n\nWe call this **polylithic**: many building blocks that still feel like one coherent framework.\n\nReinhardt brings together the best of four worlds:\n\n| Inspiration        | What We Borrowed                        | What We Improved                           |\n|--------------------|-----------------------------------------|--------------------------------------------|\n| 🐍 **Django**      | Batteries-included, ORM, admin          | Composable feature flags, type safety      |\n| 🎯 **Django REST** | Serializers, ViewSets, permissions      | Compile-time validation, zero-cost         |\n| ⚡ **FastAPI**      | DI system, auto OpenAPI                 | Native performance, no runtime overhead    |\n| 🗄️ **SQLAlchemy** | QuerySet patterns, relationships        | Type-safe queries, compile-time checks     |\n\n**Result**: A framework that's familiar to Python developers, but with Rust's performance and safety guarantees.\n\n## ✨ Key Features\n\n- **Type-Safe ORM** with compile-time validation (reinhardt-query)\n- **Powerful Serializers** with automatic validation (serde + built-in validation)\n- **FastAPI-Style DI** with type-safe dependency injection and caching\n- **ViewSets** for rapid CRUD API development\n- **Multi-Auth** (JWT, Token, Session, Basic) with BaseUser/FullUser traits\n- **Admin Panel** with auto-generated model management interface\n- **Management Commands** for migrations, static files, and more\n- **GraphQL \u0026 WebSocket** support for real-time applications\n- **Pagination, Filtering, Rate Limiting** built-in\n- **Signals** for event-driven architecture\n\nSee [Available Components](#available-components) for complete list and [Getting Started](https://reinhardt-web.dev/quickstart/getting-started/) for examples.\n\n## API Stability\n\nReinhardt follows a **three-phase lifecycle** for every crate:\n\n| Phase | What to Expect |\n|-------|---------------|\n| **Alpha** (`0.x.0-alpha.N`) | APIs may change freely. Early adopters welcome. |\n| **RC** (`0.x.0-rc.N`) | API frozen. Bug fixes only. Safe to build against. |\n| **Stable** (`0.x.0`) | Full SemVer 2.0 guarantees. |\n\n\u003c!-- reinhardt-version-sync --\u003e\n**Current status:** Reinhardt is at `0.1.3`. From `0.1.0` onward, all\npublic APIs follow SemVer 2.0; breaking changes ship in a future\n`0.2.0-rc.N` series coordinated through the `develop/0.2.0` branch.\n\nFor per-release detail (changelog summary, upgrade notes, known issues),\nsee the [Release category in GitHub Discussions](https://github.com/kent8192/reinhardt-web/discussions/categories/release).\nThe full lifecycle policy lives in\n[Stability Policy](instructions/STABILITY_POLICY.md).\n\n## Installation\n\nReinhardt is a modular framework. Choose your starting point:\n\n\u003e **New here?** Start with the default standard setup. Use `full` if you need all features, or `minimal` for lightweight APIs.\n\n### Default: Standard Setup (Balanced) ⚠️ Default Preset\n\nGet a well-balanced feature set with zero configuration:\n\n\u003c!-- reinhardt-version-sync --\u003e\n```toml\n[dependencies]\n# Import as 'reinhardt', published as 'reinhardt-web'\n# Default enables the \"standard\" preset (balanced feature set)\nreinhardt = { version = \"0.1.3\", package = \"reinhardt-web\" }\n```\n\n**Includes:** Core, Database (PostgreSQL), REST API (serializers, parsers, pagination, filters, throttling, versioning, metadata, content negotiation), Auth, Middleware (sessions), Pages (WASM Frontend with SSR), Signals\n\n**Binary**: ~20-30 MB | **Compile**: Medium\n\nThen use in your code:\n```rust\nuse reinhardt::prelude::*;\nuse reinhardt::{Request, Response, StatusCode};\n```\n\n### Option 1: Full-Featured (All Batteries Included)\n\nFor projects that need every available component:\n\n\u003c!-- reinhardt-version-sync --\u003e\n```toml\n[dependencies]\nreinhardt = { version = \"0.1.3\", package = \"reinhardt-web\", default-features = false, features = [\"full\"] }\n```\n\n**Includes:** Everything in Standard, plus Admin, GraphQL, WebSockets, Cache, i18n, Mail, Static Files, Storage, and more\n\n**Binary**: ~50+ MB | **Compile**: Slower, but everything works out of the box\n\n### Option 2: Microservices (Minimal Setup)\n\nLightweight and fast, perfect for simple APIs:\n\n\u003c!-- reinhardt-version-sync --\u003e\n```toml\n[dependencies]\nreinhardt = { version = \"0.1.3\", package = \"reinhardt-web\", default-features = false, features = [\"minimal\"] }\n```\n\n**Includes:** HTTP, routing, DI, parameter extraction, server\n\n**Binary**: ~5-10 MB | **Compile**: Very fast\n\n### Option 3: Build Your Custom Stack\n\nInstall only the components you need:\n\n\u003c!-- reinhardt-version-sync:8 --\u003e\n```toml\n[dependencies]\n# Core components\nreinhardt-http = \"0.1.3\"\nreinhardt-urls = \"0.1.3\"\n\n# Optional: Database\nreinhardt-db = \"0.1.3\"\n\n# Optional: Authentication\nreinhardt-auth = \"0.1.3\"\n\n# Optional: REST API features\nreinhardt-rest = \"0.1.3\"\n\n# Optional: Admin panel\nreinhardt-admin = \"0.1.3\"\n\n# Optional: Advanced features\nreinhardt-graphql = \"0.1.3\"\nreinhardt-websockets = \"0.1.3\"\n```\n\n**Note on Crate Naming:**\nThe main Reinhardt crate is published on crates.io as `reinhardt-web`, but you import it as `reinhardt` in your code using the `package` attribute.\n\n**📖 For a complete list of available crates and feature flags, see the [Feature Flags Guide](https://reinhardt-web.dev/docs/feature-flags/).**\n\n## Getting Started Guide\n\n### 1. Install Reinhardt Admin Tool\n\nWhile Reinhardt is on a pre-release (`-rc.*` / `-alpha.*`), `cargo install`\nrequires an explicit `--version` because pre-releases are not selected by\ndefault. Once `0.1.0` stable ships, omit `--version` to pull the latest\nstable (or keep `--version` as an opt-in reproducibility pin). The literal\nbelow is auto-bumped by release-plz on each release.\n\n\u003c!-- reinhardt-version-sync --\u003e\n```bash\ncargo install reinhardt-admin-cli --version \"0.1.3\"\n```\n\n### 2. Create a New Project\n\n```bash\n# Create a RESTful API project (default)\nreinhardt-admin startproject my-api\ncd my-api\n```\n\nThis generates a complete project structure:\n\n```\nmy-api/\n├── Cargo.toml\n├── src/\n│   ├── lib.rs\n│   ├── config.rs\n│   ├── apps.rs\n│   ├── config/\n│   │   ├── settings.rs\n│   │   ├── settings/\n│   │   │   ├── base.rs\n│   │   │   ├── local.rs\n│   │   │   ├── staging.rs\n│   │   │   └── production.rs\n│   │   ├── urls.rs\n│   │   └── apps.rs\n│   └── bin/\n│       └── manage.rs\n└── README.md\n```\n\n**Alternative: Create a reinhardt-pages Project (WASM + SSR)**\n\nFor a modern WASM-based frontend with SSR:\n\n```bash\n# Create a pages project\nreinhardt-admin startproject my-app --template pages\ncd my-app\n\n# Install WASM build tools (first time only)\ncargo make install-wasm-tools\n\n# Build WASM and start development server\ncargo make dev\n# Visit http://127.0.0.1:8000/\n```\n\n### 3. Run the Development Server\n\n```bash\n# Using the manage command\ncargo run --bin manage runserver\n\n# Server will start at http://127.0.0.1:8000\n```\n\n**Auto-Reload Support:**\n\nThe development server reloads automatically on file changes:\n\n```bash\ncargo run --bin manage -- runserver --with-pages\n```\n\nEdit any Rust source file (server-side or wasm-side) and the bundle\nplus the server are rebuilt in place. Pass `--noreload` to disable\nauto-reload entirely, or `--no-wasm-rebuild` to keep server reload\nbut manage the wasm build yourself.\n\n### 4. Create Your First App\n\n```bash\n# Create a RESTful API app (default)\nreinhardt-admin startapp users\n\n# Or explicitly specify type\nreinhardt-admin startapp users --with-rest\n\n# Create a Pages app (WASM + SSR)\nreinhardt-admin startapp dashboard --with-pages\n```\n\nThis creates an app structure — the layout depends on the template:\n\n**RESTful app** (`--with-rest`, default):\n\n```\nusers/\n├── lib.rs\n├── models.rs\n├── models/\n├── views.rs\n├── views/\n├── serializers.rs\n├── serializers/\n├── admin.rs\n├── admin/\n├── urls.rs\n├── tests.rs\n└── tests/\n```\n\n**Pages app** (`--with-pages`, WASM + SSR):\n\nEach app owns its server-side and client-side code under `src/apps/\u003capp\u003e/`.\nPer Rust 2024 edition module conventions, the entry point for an app is a\nsibling `\u003capp\u003e.rs` file next to the `\u003capp\u003e/` directory — there is no inner\n`lib.rs`. The same pattern applies to nested aggregators (`client.rs` is\nthe sibling of `client/`, `urls.rs` is the sibling of `urls/`).\n\n```\nsrc/\n├── apps.rs                       # aggregator: pub mod polls; #[cfg(server)] pub use polls::PollsConfig;\n├── apps/\n│   ├── polls.rs                  # per-app entry (sibling of polls/)\n│   └── polls/\n│       ├── admin.rs              # #[cfg(server)] admin registration\n│       ├── client.rs             # #[cfg(client)] aggregator: pub mod components; pub mod pages;\n│       ├── client/\n│       │   ├── components.rs     # per-app UI (placeholder() returning Page)\n│       │   └── pages.rs          # per-app pages (placeholder_page wraps with_nav)\n│       ├── models.rs             # #[cfg(server)] models\n│       ├── models/               # (.gitkeep — user adds submodules here)\n│       ├── serializers.rs        # #[cfg(server)] serializers\n│       ├── serializers/          # (.gitkeep)\n│       ├── server_fn.rs          # bi-target #[server_fn] handlers (placeholder)\n│       ├── tests/                # (.gitkeep)\n│       ├── urls.rs               # urls aggregator (cfg-gated submodules)\n│       ├── urls/\n│       │   ├── server_urls.rs    # #[url_patterns(InstalledApp::polls, mode = server)]\n│       │   └── client_router.rs  # #[url_patterns(InstalledApp::polls, mode = client)]\n│       └── views.rs              # #[cfg(server)] views\n├── bin/\n│   └── manage.rs                 # native-only management CLI entry\n├── client.rs                     # #[cfg(client)] aggregator: pub mod lib; pub mod components;\n├── client/\n│   ├── components.rs             # cross-app shell: pub mod nav;\n│   ├── components/\n│   │   └── nav.rs                # with_nav(body: Page) -\u003e Page helper\n│   └── lib.rs                    # #[wasm_bindgen(start)] -\u003e ClientLauncher::router_client(...)\n├── config.rs                     # cfg-gated config aggregator\n├── config/\n│   ├── apps.rs                   # installed_apps! { polls: \"polls\" }\n│   ├── settings.rs               # #[cfg(server)] settings\n│   ├── urls.rs                   # #[routes(standalone)] entry\n│   └── wasm.rs                   # #[cfg(server)] wasm tooling config\n├── lib.rs                        # crate root (`pub mod apps;` is un-gated)\n├── shared.rs                     # bi-target shared module\n└── shared/\n    ├── forms.rs                  # shared form definitions\n    └── types.rs                  # DTOs exchanged between WASM and server\n```\n\n### 5. Register Routes\n\nEdit your app's `urls.rs`. **`urls.rs` plays two roles**: it **declares the URL\nsubmodules** of the app (via `pub mod ...;`) and **aggregates** them into a\nsingle `url_patterns` (or `server_url_patterns` / `unified_url_patterns`) entry\npoint that `src/config/urls.rs` mounts:\n\n```rust\n// users/urls.rs\n//\n// 1. Module declarations for sub-URL files (optional, for larger apps):\npub mod api;\npub mod views;\n\n// 2. Aggregator — the single entry point mounted from src/config/urls.rs.\nuse reinhardt::url_patterns;\nuse reinhardt::ServerRouter;\n\nuse crate::config::apps::InstalledApp;\n\n#[url_patterns(InstalledApp::users, mode = server)]\npub fn server_url_patterns() -\u003e ServerRouter {\n\tServerRouter::new()\n\t\t.endpoint(views::list_users)\n\t\t.endpoint(views::get_user)\n\t\t.endpoint(views::create_user)\n\t\t.mount(\"/api/v1/\", api::routes())\n}\n```\n\nThe `#[url_patterns]` attribute registers this router with the framework for\nautomatic discovery. For Pages apps, use `mode = unified` and return\n`UnifiedRouter` instead (see the generated `urls/{server,client,ws}_urls.rs`\nsubmodules).\n\nInclude in `src/config/urls.rs`:\n\n```rust\n// src/config/urls.rs\nuse reinhardt::prelude::*;\nuse reinhardt::routes;\n\n#[routes]\npub fn routes() -\u003e ServerRouter {\n\tServerRouter::new()\n\t\t.mount(\"/api/\", users::urls::url_patterns())\n}\n```\n\nThe `#[routes]` attribute macro automatically registers this function with the\nframework for discovery via the `inventory` crate.\n\n**Note:** The `reinhardt::prelude` includes commonly used types. Key exports include:\n\n**Always Available:**\n- Core routing and views: `Router`, `DefaultRouter`, `ServerRouter`, `View`, `ListView`, `DetailView`\n- ViewSets: `ViewSet`, `ModelViewSet`, `ReadOnlyModelViewSet`\n- HTTP: `StatusCode`\n\n**Feature-Dependent:**\n- **`core` feature**: `Request`, `Response`, `Handler`, `Middleware`, Signals (`post_save`, `pre_save`, etc.)\n- **`database` feature**: `Model`, `DatabaseConnection`, `F`, `Q`, `Transaction`, `atomic`, Database functions (`Concat`, `Upper`, `Lower`, `Now`, `CurrentDate`), Window functions (`Window`, `RowNumber`, `Rank`, `DenseRank`), Constraints (`UniqueConstraint`, `CheckConstraint`, `ForeignKeyConstraint`)\n- **`auth` feature**: `BaseUser`, `FullUser`, `PermissionsMixin`, `BaseUserManager`, `Argon2Hasher`, `GroupManager`, `CreateGroupData`, `Permission`, `ObjectPermission`, `ObjectPermissionManager`\n- **`minimal`, `standard`, or `di` features**: `Body`, `Cookie`, `Header`, `Json`, `Path`, `Query`\n- **`rest` feature**: Serializers, Parsers, Pagination, Throttling, Versioning\n- **`admin` feature**: Admin panel components\n- **`cache` feature**: `Cache`, `InMemoryCache`\n- **`sessions` feature**: `Session`, `AuthenticationMiddleware`\n\nFor a complete list, see [Feature Flags Guide](https://reinhardt-web.dev/docs/feature-flags/).\n\nFor a complete step-by-step guide, see [Getting Started](https://reinhardt-web.dev/quickstart/getting-started/).\n\n## 🎓 Learn by Example\n\n### With Database\n\nConfigure database aliases in `settings/base.toml`:\n\n```toml\n[core]\ndebug = true\nsecret_key = \"your-secret-key-for-development\"\n\n[core.databases.default]\nengine = \"postgresql\"\nname = \"mydb\"\nuser = \"postgres\"\npassword = \"postgres\"\nhost = \"localhost\"\nport = 5432\n```\n\nSettings are automatically loaded in `src/config/settings.rs`:\n\n```rust\n// src/config/settings.rs\nuse reinhardt::prelude::*;\n\n// Compose built-in settings fragments with | - field names are inferred from type names\n// (e.g., CoreSettings -\u003e core, CacheSettings -\u003e cache, EmailSettings -\u003e email)\n#[settings(CoreSettings | CacheSettings | EmailSettings)]\npub struct ProjectSettings;\n```\n\nThe `|` syntax composes settings fragments into `ProjectSettings`. Each type must be a `#[settings(fragment = true, ...)]` struct. Built-in fragments:\n- **`CoreSettings`** - `base_dir`, `secret_key`, `debug`, `allowed_hosts`, `databases`, `security`, `middleware`, `root_urlconf`, and `installed_apps`\n- **`CacheSettings`**, **`ContactSettings`**, **`CorsSettings`**, **`EmailSettings`**, **`I18nSettings`**, **`LoggingSettings`**, **`MediaSettings`**, **`SecuritySettings`**, **`SessionSettings`**, **`StaticSettings`**, and **`TemplateSettings`** - optional framework sections\n\nAdd project-specific fragments with explicit field names using `key: Type` syntax:\n\n```rust\n#[settings(CoreSettings | CacheSettings | mail: MailSettings)]\npub struct ProjectSettings;\n```\n\nSee [Settings Documentation](https://reinhardt-web.dev/docs/settings/) for more details.\n\n**Defining a User Model:**\n\nDefine your own user model with `#[user(...)]` + `#[model(...)]`. These two\nattribute macros cooperate: `#[user]` implements the auth traits (`BaseUser`,\n`PermissionsMixin`, `AuthIdentity`, and optionally `FullUser`) on top of a\nnormal Reinhardt model:\n\n```rust\n// users/models.rs\nuse reinhardt::prelude::*;\nuse reinhardt::Argon2Hasher;\n\n#[user(hasher = Argon2Hasher, username_field = \"username\", full = true)]\n#[model(app_label = \"users\", table_name = \"users\")]\npub struct User {\n\t#[field(primary_key = true)]\n\tpub id: Uuid,\n\n\t#[field(max_length = 100)]\n\tpub username: String,\n\n\t#[field(max_length = 255)]\n\tpub email: String,\n\n\tpub password_hash: Option\u003cString\u003e,\n\n\t#[field(max_length = 150)]\n\tpub first_name: String,\n\n\t#[field(max_length = 150)]\n\tpub last_name: String,\n\n\t#[field(default = true)]\n\tpub is_active: bool,\n\n\t#[field(default = false)]\n\tpub is_staff: bool,\n\n\t#[field(default = false)]\n\tpub is_superuser: bool,\n\n\tpub last_login: Option\u003cDateTime\u003cUtc\u003e\u003e,\n\n\t#[field(auto_now_add = true)]\n\tpub date_joined: DateTime\u003cUtc\u003e,\n\n\t// Add custom fields as needed:\n\t#[field(max_length = 50, null = true)]\n\tpub phone_number: Option\u003cString\u003e,\n}\n```\n\n`#[user]` arguments:\n- `hasher` (required) — password hasher type (e.g., `Argon2Hasher`)\n- `username_field` (required) — name of the field used as the username\n- `full = true` (optional) — also implement `FullUser` (email, first_name, last_name, is_staff, date_joined)\n\n**Model Attribute Macro:**\n\nThe `#[model(...)]` attribute automatically generates:\n- Implementation of the `Model` trait (includes `#[derive(Model)]` functionality)\n- Type-safe field accessors: `User::field_email()`, `User::field_username()`, etc.\n- Global model registry registration\n- Support for composite primary keys\n\n**Note:** When using `#[model(...)]`, you do NOT need to add `#[derive(Model)]` separately,\nas it is automatically applied by the `#[model(...)]` attribute.\n\n**Field Attributes:**\n- `#[field(primary_key = true)]` - Mark as primary key\n- `#[field(max_length = 255)]` - Set maximum length for string fields\n- `#[field(default = value)]` - Set default value\n- `#[field(auto_now_add = true)]` - Auto-populate timestamp on creation\n- `#[field(auto_now = true)]` - Auto-update timestamp on save\n- `#[field(null = true)]` - Allow NULL values\n- `#[field(unique = true)]` - Enforce uniqueness constraint\n\nFor a complete list of field attributes, see the [Field Attributes Guide](https://reinhardt-web.dev/docs/field-attributes/).\n\nThe generated field accessors enable type-safe field references in queries:\n\n```rust\n// Generated by #[model(...)] for the User struct above:\nimpl User {\n\tpub const fn field_id() -\u003e FieldRef\u003cUser, Uuid\u003e { FieldRef::new(\"id\") }\n\tpub const fn field_username() -\u003e FieldRef\u003cUser, String\u003e { FieldRef::new(\"username\") }\n\tpub const fn field_email() -\u003e FieldRef\u003cUser, String\u003e { FieldRef::new(\"email\") }\n\tpub const fn field_is_active() -\u003e FieldRef\u003cUser, bool\u003e { FieldRef::new(\"is_active\") }\n\tpub const fn field_is_staff() -\u003e FieldRef\u003cUser, bool\u003e { FieldRef::new(\"is_staff\") }\n\tpub const fn field_date_joined() -\u003e FieldRef\u003cUser, DateTime\u003cUtc\u003e\u003e { FieldRef::new(\"date_joined\") }\n\t// ... other fields\n}\n```\n\n**Advanced Query Examples:**\n\n```rust\nuse reinhardt::prelude::*;\nuse crate::models::User;\n\n// Django-style F/Q object queries with type-safe field references\nasync fn complex_user_query() -\u003e Result\u003cVec\u003cUser\u003e, Box\u003cdyn std::error::Error\u003e\u003e {\n\t// Q objects for building complex conditions\n\tlet active_query = Q::new(\"is_active\", \"=\", \"true\")\n\t\t.and(Q::new(\"date_joined\", \"\u003e=\", \"NOW()\"));\n\n\t// Database functions with type-safe field references\n\tlet email_lower = Lower::new(User::field_email().into());\n\tlet username_upper = Upper::new(User::field_username().into());\n\n\t// Aggregations using field accessors\n\tlet user_count = Aggregate::count(User::field_id().into());\n\tlet latest_joined = Aggregate::max(User::field_date_joined().into());\n\n\t// Window functions for ranking\n\tlet rank_by_join_date = Window::new()\n\t\t.partition_by(vec![User::field_is_active().into()])\n\t\t.order_by(vec![(User::field_date_joined().into(), \"DESC\")])\n\t\t.function(RowNumber::new());\n\n\t// Build and execute the query using QuerySet\n\tlet users = User::objects()\n\t\t.filter(active_query)\n\t\t.annotate(\"email_lower\", email_lower)\n\t\t.annotate(\"username_upper\", username_upper)\n\t\t.annotate(\"rank\", rank_by_join_date)\n\t\t.order_by(vec![(\"-date_joined\",)])\n\t\t.all()\n\t\t.await?;\n\n\tOk(users)\n}\n\n// Transaction support\nasync fn create_user_with_transaction(\n\tconn: \u0026DatabaseConnection,\n\tuser_data: CreateUserRequest\n) -\u003e Result\u003cUser, Box\u003cdyn std::error::Error\u003e\u003e {\n\t// Transaction with automatic rollback on error\n\ttransaction(conn, |_tx| async move {\n\t\tlet user = User::create(user_data).await?;\n\t\tlog_user_creation(\u0026user).await?;\n\t\tOk(user)\n\t}).await\n}\n```\n\n**Note**: Reinhardt uses reinhardt-query for SQL operations. The `#[model(...)]` attribute automatically generates Model trait implementations, type-safe field accessors, and global model registry registration.\n\nRegister in `src/config/apps.rs`:\n\n```rust\n// src/config/apps.rs\nuse reinhardt::installed_apps;\n\n// The installed_apps! macro generates:\n// - An enum InstalledApp with variants for each app\n// - Implementation of conversion traits (From, Into, Display)\n// - A registry for app configuration and discovery\n//\n// Note: Unlike Django's INSTALLED_APPS, this macro is for user apps only.\n// Built-in framework features (auth, sessions, admin, etc.) are enabled via\n// Cargo feature flags, not through installed_apps!.\n//\n// Example:\n// [dependencies]\n// reinhardt = { version = \"0.1\", features = [\"auth\", \"sessions\", \"admin\"] }\n//\n// This enables:\n// - Automatic app discovery for migrations, admin panel, etc.\n// - Type-safe app references throughout your code\n// - Centralized app configuration\ninstalled_apps! {\n\tusers: \"users\",\n}\n\npub fn get_installed_apps() -\u003e Vec\u003cString\u003e {\n\tInstalledApp::all_apps()\n}\n```\n\n### With Authentication\n\nReinhardt provides Django-style user models and permission primitives. You\nbring your own user struct (defined with `#[user(...)]` + `#[model(...)]` as\nshown in the previous section); the framework layers auth traits, a\npassword-management workflow, groups, and object-level permissions on top.\n\n**Two entry points for user data:**\n\n| Need | Use |\n|------|-----|\n| ORM queries on users (filter/annotate/aggregate) | `User::objects()` (from `#[model]`) |\n| User lifecycle: create/password-hashing/superuser | A `BaseUserManager\u003cUser\u003e` implementation |\n| Groups | `GroupManager` |\n| Object-level permissions | `ObjectPermissionManager` |\n\n\u003e `User::objects()` is *not* a shortcut to a manager — it is the `QuerySet`\n\u003e entry point from the `Model` trait. Manager types\n\u003e (`BaseUserManager\u003cUser\u003e` for the user lifecycle, `GroupManager`,\n\u003e `ObjectPermissionManager`) are constructed directly via `::new()`.\n\n**User lifecycle example:**\n\nFor a custom user, implement `BaseUserManager\u003cUser\u003e` (see\n`reinhardt_auth::BaseUserManager`). The signature required is:\n\n```rust\nuse std::collections::HashMap;\nuse async_trait::async_trait;\nuse reinhardt::prelude::*;\nuse reinhardt_auth::{Argon2Hasher, BaseUserManager, PasswordHasher};\nuse serde_json::Value;\nuse crate::models::User;\n\npub struct UserManager {\n\thasher: Argon2Hasher,\n}\n\nimpl UserManager {\n\tpub fn new() -\u003e Self {\n\t\tSelf { hasher: Argon2Hasher::new() }\n\t}\n}\n\n#[async_trait]\nimpl BaseUserManager\u003cUser\u003e for UserManager {\n\tasync fn create_user(\n\t\t\u0026mut self,\n\t\tusername: \u0026str,\n\t\tpassword: Option\u003c\u0026str\u003e,\n\t\textra: HashMap\u003cString, Value\u003e,\n\t) -\u003e Result\u003cUser, reinhardt::Error\u003e {\n\t\tlet mut user = User::new(username.to_string(), /* email */ String::new());\n\t\tif let Some(pw) = password {\n\t\t\tuser.set_password(pw)?;\n\t\t}\n\t\t// Apply extra fields (email, first_name, …) as needed …\n\t\tuser.save().await?;\n\t\tOk(user)\n\t}\n}\n```\n\nThen:\n\n```rust\nlet mut users = UserManager::new();\nlet alice = users\n\t.create_user(\n\t\t\"alice\",\n\t\tSome(\"secure_password\"),\n\t\tHashMap::from([(\"email\".into(), serde_json::json!(\"alice@example.com\"))]),\n\t)\n\t.await?;\n```\n\n**Groups and object-level permissions:**\n\n`GroupManager` and `ObjectPermissionManager` are always available and are\ninstantiated directly:\n\n```rust\nuse reinhardt::{CreateGroupData, GroupManager, ObjectPermissionManager};\n\nlet mut groups = GroupManager::new();\nlet editors = groups\n\t.create_group(CreateGroupData { name: \"editors\".to_string() })\n\t.await?;\n\nlet mut perms = ObjectPermissionManager::new();\nperms.grant_permission(\"alice\", \"article:123\", \"edit\").await;\n```\n\nUse JWT authentication in your app's `views/profile.rs`:\n\n```rust\n// users/views/profile.rs\nuse reinhardt::{AuthUser, Response, StatusCode, ViewResult, get};\nuse crate::models::User;\n\n// JwtAuthMiddleware must be registered in urls.rs to populate AuthState in request extensions\n#[get(\"/profile\", name = \"get_profile\")]\npub async fn get_profile(\n\t#[inject] AuthUser(user): AuthUser\u003cUser\u003e,\n) -\u003e ViewResult\u003cResponse\u003e {\n\t// AuthUser\u003cU\u003e loads the full user model from the database using the AuthState\n\t// set by authentication middleware. Returns an injection error if unauthenticated.\n\tif !user.is_active() {\n\t\treturn Err(\"User account is inactive\".into());\n\t}\n\n\tlet json = serde_json::to_string(\u0026user)?;\n\tOk(Response::new(StatusCode::OK).with_body(json))\n}\n```\n\n### Dependency Injection\n\nReinhardt ships a FastAPI-inspired, async-first dependency injection (DI)\nsystem in the `reinhardt-di` crate. It is type-safe, scope-aware (`singleton` /\n`request` / `transient`), composable (dependencies can depend on other\ndependencies), and registered at compile time via the\n[`inventory`](https://crates.io/crates/inventory) crate so that there is no\nruntime reflection or startup discovery cost.\n\nThree primitives drive everyday use:\n\n1. **`#[injectable]`** — turn a struct into an injectable service.\n2. **`#[injectable_factory]`** — register an async function as a factory for\n   types you *cannot* annotate yourself (foreign types, trait objects,\n   connection handles built from settings).\n3. **`#[inject]`** with **`Depends\u003cT\u003e`** — receive dependencies in a handler\n   (or another injectable) without wiring anything by hand.\n\n#### 1. `#[injectable]` — struct-level injection\n\nApply `#[injectable]` to any struct whose fields are themselves injectable.\nNon-injected fields are marked with `#[no_inject]` and must implement\n`Default` (or be supplied via the generated builder):\n\n```rust\nuse reinhardt::di::injectable;\n\n// `scope` is passed as a macro argument; accepted values are\n// \"singleton\", \"request\", or \"transient\" (one literal, not an alternation).\n// When omitted, `#[injectable]` defaults to `request` and\n// `#[injectable_factory]` defaults to `singleton`. `Config` is registered\n// as a singleton here so it matches the singleton-scoped\n// `database_connection` factory below: mixing a longer-lived dependent\n// with a shorter-lived dependency is not rejected by the registry, but it\n// captures whichever request-scoped instance was live at first resolution\n// and reuses it for the singleton's lifetime — almost never what you want.\n#[injectable(scope = \"singleton\")]\n#[derive(Clone)]\npub struct Config {\n    #[no_inject]\n    pub database_url: String,\n}\n```\n\n`#[injectable]` generates an `impl Injectable for Config` and a compile-time\nregistration entry (via `inventory::submit!`) so the type resolves from\n`InjectionContext` automatically.\n\n#### 2. `#[injectable_factory]` — the pseudo orphan rule\n\nRust's orphan rule forbids `impl Injectable for SomeForeignType`. For user-owned\nadapters around third-party handles, Reinhardt offers `#[injectable_factory]`.\nYou write an async function whose return type is the type to register; the macro\nwraps it, submits an `inventory` entry, and hands the returned value to the DI\ncontainer:\n\n```rust\nuse reinhardt::db::DatabaseConnection;\nuse reinhardt::di::{Depends, injectable_factory};\n\n#[derive(Clone)]\npub struct AppDatabase {\n    pub connection: DatabaseConnection,\n}\n\n#[injectable_factory(scope = \"singleton\")]\nasync fn app_database(\n    #[inject] config: Depends\u003cConfig\u003e,\n) -\u003e AppDatabase {\n    let connection = DatabaseConnection::connect(\u0026config.database_url)\n        .await\n        .expect(\"failed to open database connection\");\n    AppDatabase { connection }\n}\n```\n\n**Every parameter of an `#[injectable_factory]` function must be annotated\nwith `#[inject]`.** There is no way to pass runtime arguments; factories only\ncompose over other injectables.\n\n**The pseudo orphan rule.** To prevent user factories from silently shadowing\nframework-owned types (e.g., `reinhardt_di::InjectionContext`, routers,\nmiddleware bindings), Reinhardt validates every registered factory at startup.\nIf the return type's fully-qualified name begins with a\nframework-reserved crate prefix (`reinhardt::`, `reinhardt_di::`, `reinhardt_http::`,\n… 37 prefixes total), registration is rejected unless the factory itself lives\ninside that crate. This emulates the orphan rule across the DI boundary: foreign\ntypes are fair game, framework types are not. The validator lives in\n[`crates/reinhardt-di/src/validation.rs`](crates/reinhardt-di/src/validation.rs)\n(`check_framework_type_override`, lines 51–129).\n\nFramework-owned types such as `DatabaseConnection` should use the injectable\nimplementation provided by the framework, or be wrapped in a project-owned type\nlike `AppDatabase` when you need project-specific construction.\n\n#### 3. `#[inject]` + `Depends\u003cT\u003e` in handlers\n\nUse `#[inject]` on a handler parameter to have the DI container resolve it\nbefore the handler runs. Wrap the requested type in `Depends\u003cT\u003e` so that\ncaching and scope are honoured:\n\n```rust\nuse reinhardt::{get, Response, StatusCode, ViewResult};\nuse reinhardt::di::Depends;\nuse reinhardt::db::DatabaseConnection;\nuse reinhardt::extractors::Path;\nuse crate::models::User;\n\n#[get(\"/users/{id}/\", name = \"get_user\")]\npub async fn get_user(\n    Path(id): Path\u003ci64\u003e,\n    #[inject] db: Depends\u003cDatabaseConnection\u003e,\n) -\u003e ViewResult\u003cResponse\u003e {\n    let user = User::objects().filter(User::field_id().eq(id)).get().await?;\n    let body = serde_json::to_string(\u0026user)?;\n    Ok(Response::new(StatusCode::OK).with_body(body))\n}\n```\n\n**Caching.** Within a scope boundary, resolving the same `Depends\u003cT\u003e` twice\nreturns the *same* instance. Opt out per-call with `#[inject(cache = false)]`:\n\n```rust\npub async fn uncached_handler(\n    #[inject(cache = false)] db: Depends\u003cDatabaseConnection\u003e,\n) -\u003e ViewResult\u003cResponse\u003e { /* always a fresh resolution within the scope */ }\n```\n\n#### Manual `impl Injectable`\n\nWhen neither macro fits (generic bounds the macro cannot infer, hand-written\nbuilders, conditional registration), implement `Injectable` directly:\n\n```rust\nuse async_trait::async_trait;\nuse reinhardt::di::{Injectable, InjectionContext, DiResult};\n\n#[async_trait]\nimpl Injectable for MyService {\n    async fn inject(_ctx: \u0026InjectionContext) -\u003e DiResult\u003cSelf\u003e {\n        Ok(MyService::new())\n    }\n}\n```\n\nFor the full DI reference, see the [`reinhardt-di` crate\ndocumentation](https://docs.rs/reinhardt-di).\n\n### Endpoint Definition\n\nReinhardt uses HTTP method decorators to define endpoints:\n\n#### HTTP Method Decorators\n\nUse `#[get]`, `#[post]`, `#[put]`, `#[delete]` to define routes:\n\n```rust\nuse reinhardt::{get, post, Response, ViewResult};\nuse serde_json::json;\n\n#[get(\"/\")]\npub async fn hello() -\u003e ViewResult\u003cResponse\u003e {\n\tOk(Response::ok().with_body(\"Hello, World!\"))\n}\n\n#[post(\"/users\")]\npub async fn create_user() -\u003e ViewResult\u003cResponse\u003e {\n\tlet body = json!({\"status\": \"created\"});\n\tResponse::ok().with_json(\u0026body).map_err(Into::into)\n}\n```\n\n**Features:**\n- Compile-time path validation\n- Concise syntax\n- Automatic HTTP method binding\n- Support for dependency injection via `#[inject]`\n\n#### Using Dependency Injection\n\nCombine HTTP method decorators with `#[inject]` for automatic dependency injection:\n\n```rust\nuse reinhardt::{get, Response, StatusCode, ViewResult};\nuse reinhardt::extractors::Path;\nuse reinhardt::di::Depends;\nuse reinhardt::db::DatabaseConnection;\nuse crate::models::User;\n\n#[get(\"/users/{id}/\", name = \"get_user\")]\npub async fn get_user(\n\tPath(id): Path\u003ci64\u003e,\n\t#[inject] db: Depends\u003cDatabaseConnection\u003e,\n) -\u003e ViewResult\u003cResponse\u003e {\n\t// Path extractor parses and validates the {id} segment automatically\n\tlet user = User::objects()\n\t\t.filter(User::field_id().eq(id))\n\t\t.get()\n\t\t.await?;\n\n\tlet json = serde_json::to_string(\u0026user)?;\n\tOk(Response::new(StatusCode::OK).with_body(json))\n}\n```\n\n**Dependency Injection Features:**\n- Automatic dependency injection via `#[inject]` attribute\n- Cache control with `#[inject(cache = false)]`\n- FastAPI-inspired dependency injection system\n- Works seamlessly with HTTP method decorators\n\n**Result Type:**\n\nAll view functions use `ViewResult\u003cT\u003e` as the return type:\n\n```rust\nuse reinhardt::ViewResult;  // Pre-defined result type\n```\n\n### With Parameter Extraction\n\nIn your app's `views/user.rs`:\n\n```rust\n// users/views/user.rs\nuse reinhardt::{Response, StatusCode, ViewResult, get};\nuse reinhardt::extractors::{Path, Query};\nuse reinhardt::di::Depends;\nuse reinhardt::db::DatabaseConnection;\nuse crate::models::User;\nuse serde::Deserialize;\n\n#[derive(Deserialize)]\npub struct GetUserParams {\n\tpub include_inactive: Option\u003cbool\u003e,\n}\n\n#[get(\"/users/{id}/\", name = \"get_user\")]\npub async fn get_user(\n\tPath(id): Path\u003ci64\u003e,\n\tQuery(params): Query\u003cGetUserParams\u003e,\n\t#[inject] db: Depends\u003cDatabaseConnection\u003e,\n) -\u003e ViewResult\u003cResponse\u003e {\n\tlet user = User::objects()\n\t\t.filter(User::field_id().eq(id))\n\t\t.get()\n\t\t.await?;\n\n\tif !params.include_inactive.unwrap_or(false) \u0026\u0026 !user.is_active {\n\t\treturn Err(\"User is inactive\".into());\n\t}\n\n\tlet json = serde_json::to_string(\u0026user)?;\n\tOk(Response::new(StatusCode::OK).with_body(json))\n}\n```\n\nRegister route with path parameter in `urls.rs`:\n\n```rust\n// users/urls.rs\nuse reinhardt::ServerRouter;\n\nuse super::views;\n\npub fn url_patterns() -\u003e ServerRouter {\n\tServerRouter::new()\n\t\t.endpoint(views::get_user)  // Path defined in #[get(\"/users/{id}/\")]\n}\n```\n\n### With Serializers and Validation\n\nIn your app's `serializers/user.rs`:\n\n```rust\n// users/serializers/user.rs\nuse serde::{Serialize, Deserialize};\nuse reinhardt::Validate;\n\n#[derive(Serialize, Deserialize, Validate)]\npub struct CreateUserRequest {\n\t#[validate(email)]\n\tpub email: String,\n\t#[validate(length(min = 3, max = 50))]\n\tpub username: String,\n\t#[validate(length(min = 8))]\n\tpub password: String,\n}\n\n#[derive(Serialize, Deserialize)]\npub struct UserResponse {\n\tpub id: i64,\n\tpub username: String,\n\tpub email: String,\n\tpub is_active: bool,\n}\n\nimpl From\u003cUser\u003e for UserResponse {\n\tfn from(user: User) -\u003e Self {\n\t\tUserResponse {\n\t\t\tid: user.id,\n\t\t\tusername: user.username,\n\t\t\temail: user.email,\n\t\t\tis_active: user.is_active,\n\t\t}\n\t}\n}\n```\n\nIn your app's `views/user.rs`:\n\n```rust\n// users/views/user.rs\nuse reinhardt::{Response, StatusCode, ViewResult, post};\nuse reinhardt::extractors::Json;\nuse reinhardt::validation::Validated;\nuse reinhardt::di::Depends;\nuse reinhardt::db::DatabaseConnection;\nuse crate::models::User;\nuse crate::serializers::{CreateUserRequest, UserResponse};\n\n#[post(\"/users\", name = \"create_user\")]\npub async fn create_user(\n\tJson(body): Json\u003cCreateUserRequest\u003e,\n\tValidated(create_req): Validated\u003cCreateUserRequest\u003e,\n\t#[inject] db: Depends\u003cDatabaseConnection\u003e,\n) -\u003e ViewResult\u003cResponse\u003e {\n\t// Json\u003cT\u003e deserializes the body; Validated\u003cT\u003e runs #[validate] rules and yields the validated value\n\n\t// Create user using the auto-generated new() function from #[user] + #[model]\n\tlet mut user = User::new(create_req.username, create_req.email);\n\n\t// Hash and set password using BaseUser trait\n\tuser.set_password(\u0026create_req.password)?;\n\n\t// Save to database\n\tuser.save(\u0026db).await?;\n\n\tlet response_data = UserResponse::from(user);\n\tlet json = serde_json::to_string(\u0026response_data)?;\n\n\tOk(Response::new(StatusCode::CREATED).with_body(json))\n}\n```\n\n## Adoption Paths\n\n| Your Goal | Start Here |\n|-----------|-----------|\n| **Full-stack REST API** | [Getting Started Guide](#getting-started-guide) |\n| **Full-stack with Pages (WASM + SSR)** | [Twitter Demo](examples/examples-twitter/) |\n| **Lightweight DI-focused API** | [Minimal Installation](#option-2-microservices-minimal-setup) |\n\n\u003e **Standalone DI for existing Axum apps** is planned for a future release.\n\u003e See [Discussions](https://github.com/kent8192/reinhardt-web/discussions) for updates.\n\n## Available Components\n\nReinhardt offers modular components you can mix and match:\n\n| Component           | Crate Name                | Features                                    |\n|---------------------|---------------------------|---------------------------------------------|\n| **Core**            |                           |                                             |\n| Core Types          | `reinhardt-core`          | Core traits, types, macros (Model, endpoint)|\n| HTTP \u0026 Routing      | `reinhardt-http`          | Request/Response, HTTP handling             |\n| URL Routing         | `reinhardt-urls`          | Function-based and class-based routes       |\n| Server              | `reinhardt-server`        | HTTP server implementation                  |\n| Dispatch            | `reinhardt-dispatch`      | HTTP request dispatching, handler composition |\n| Configuration       | `reinhardt-conf`          | Settings management, environment loading    |\n| Commands            | `reinhardt-commands`      | Management CLI tools (startproject, etc.)   |\n| Shortcuts           | `reinhardt-shortcuts`     | Common utility functions                    |\n| **Database**        |                           |                                             |\n| ORM                 | `reinhardt-db`            | reinhardt-query integration                |\n| **Authentication**  |                           |                                             |\n| Auth                | `reinhardt-auth`          | JWT, Token, Session, Basic auth, User models|\n| **REST API**        |                           |                                             |\n| Serializers         | `reinhardt-rest`          | built-in serialization and validation, ViewSets |\n| **Forms**           |                           |                                             |\n| Forms               | `reinhardt-forms`         | Form handling and validation                |\n| **Advanced**        |                           |                                             |\n| Admin Panel         | `reinhardt-admin`         | Django-style admin interface                |\n| Plugin System       | `reinhardt-dentdelion`    | Static \u0026 WASM plugin support, CLI management|\n| Background Tasks    | `reinhardt-tasks`         | Task queues (Redis, RabbitMQ, SQLite)       |\n| GraphQL             | `reinhardt-graphql`       | Schema generation, subscriptions            |\n| WebSockets          | `reinhardt-websockets`    | Real-time communication                     |\n| i18n                | `reinhardt-i18n`          | Multi-language support                      |\n| Mail                | `reinhardt-mail`          | Email sending and templating                |\n| gRPC                | `reinhardt-grpc`          | gRPC services, protobuf types               |\n| Deep Link           | `reinhardt-deeplink`      | iOS Universal Links, Android App Links      |\n| **Middleware**       |                           |                                             |\n| Middleware          | `reinhardt-middleware`    | HTTP middleware components, CORS, security  |\n| **Testing**         |                           |                                             |\n| Test Utilities      | `reinhardt-test`          | Testing helpers, fixtures, TestContainers   |\n| Test Kit            | `reinhardt-testkit`       | Higher-level test abstractions and utilities|\n\n**For detailed feature flags within each crate, see the [Feature Flags Guide](https://reinhardt-web.dev/docs/feature-flags/).**\n\n---\n\n## Ecosystem\n\n| Project | Status | Description |\n|---------|--------|-------------|\n| [reinhardt-cloud](https://github.com/kent8192/reinhardt-cloud) | WIP | Kubernetes operator \u0026 CLI for deploying Reinhardt apps |\n\n\u003e **Dog-fooding in progress:** We are actively developing reinhardt-cloud as the deployment infrastructure for Reinhardt applications, and using it to deploy reinhardt-web itself. As a work-in-progress project, APIs and features may change significantly.\n\n---\n\n## Documentation\n\n- 📚 [Getting Started Guide](https://reinhardt-web.dev/quickstart/getting-started/) - Step-by-step tutorial for beginners\n- 🎛️ [Feature Flags Guide](https://reinhardt-web.dev/docs/feature-flags/) - Optimize your build with granular feature control\n- 📖 [API Reference](https://docs.rs/reinhardt-web) (Coming soon)\n- 📝 [Tutorials](https://reinhardt-web.dev/quickstart/tutorials/) - Learn by building real applications\n\n**For AI Assistants**: See [CLAUDE.md](CLAUDE.md) for project-specific coding standards, testing guidelines, and development conventions.\n\n## 💬 Getting Help\n\nReinhardt is a community-driven project. Here's where you can get help:\n\n- 💬 **Discord**: Join our Discord server for real-time chat (coming soon)\n- 💭 **GitHub Discussions**: [Ask questions and share ideas](https://github.com/kent8192/reinhardt-web/discussions)\n- 🐛 **Issues**: [Report bugs](https://github.com/kent8192/reinhardt-web/issues)\n- 📖 **Documentation**: [Read the guides](docs/)\n\nBefore asking, please check:\n\n- ✅ [Getting Started Guide](https://reinhardt-web.dev/quickstart/getting-started/)\n- ✅ [Examples](examples/)\n- ✅ Existing GitHub Issues and Discussions\n\n## 🤝 Contributing\n\nWe love contributions! Please read our [Contributing Guide](CONTRIBUTING.md) to get started.\n\n**Quick links**:\n\n- [Development Setup](CONTRIBUTING.md#development-setup)\n- [Testing Guidelines](CONTRIBUTING.md#testing-guidelines)\n- [Commit Guidelines](CONTRIBUTING.md#commit-guidelines)\n\n## ⭐ Star History\n\n\u003ca href=\"https://star-history.com/#kent8192/reinhardt-web\u0026Date\"\u003e\n \u003cpicture\u003e\n   \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://api.star-history.com/svg?repos=kent8192/reinhardt-web\u0026type=Date\u0026theme=dark\" /\u003e\n   \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"https://api.star-history.com/svg?repos=kent8192/reinhardt-web\u0026type=Date\" /\u003e\n   \u003cimg alt=\"Star History Chart\" src=\"https://api.star-history.com/svg?repos=kent8192/reinhardt-web\u0026type=Date\" width=\"600\" /\u003e\n \u003c/picture\u003e\n\u003c/a\u003e\n\n## Copyright\n\nCopyright © 2026 Tachyon Inc. All rights reserved.\n\nDeveloped by Tachyon Inc.\n\n## License\n\nThis project is licensed under the [BSD 3-Clause License](LICENSE).\n\n### Third-Party Attribution\n\nThis project is inspired by:\n\n- [Django](https://www.djangoproject.com/) (BSD 3-Clause License)\n- [Django REST Framework](https://www.django-rest-framework.org/) (BSD 3-Clause License)\n- [FastAPI](https://fastapi.tiangolo.com/) (MIT License)\n- [SQLAlchemy](https://www.sqlalchemy.org/) (MIT License)\n\nSee [THIRD-PARTY-NOTICES](THIRD-PARTY-NOTICES) for full attribution.\n\n**Note:** This project is not affiliated with or endorsed by the Django Software Foundation, Encode OSS Ltd., Sebastián Ramírez (FastAPI author), or Michael Bayer (SQLAlchemy author).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkent8192%2Freinhardt-web","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkent8192%2Freinhardt-web","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkent8192%2Freinhardt-web/lists"}