modo-macros
Procedural macros for the modo web framework. Provides attribute macros for route registration, application bootstrap, and derive macros for input validation and sanitization.
All macros are re-exported from modo — import them as modo::handler,
modo::main, etc. Do not depend on modo-macros directly in application code.
Features
| Feature | What it enables |
|---|---|
static-embed |
#[main(static_assets = "...")] static file embedding via rust-embed |
Template and i18n macros (#[view], #[template_function], #[template_filter], t!)
are re-exported from modo only when the corresponding templates or i18n
feature is enabled on the modo crate.
Usage
Application entry point
async
The function must be named main, be async, and accept exactly two
parameters: an AppBuilder and a config type. The macro bootstraps a
multi-threaded Tokio runtime, configures tracing_subscriber, loads config
via environment variables, and exits with code 1 on error.
HTTP handlers
async
async
Supported methods: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS.
Path parameters written as {name} are extracted automatically. Declare a
function parameter with the matching name and the macro injects
axum::extract::Path extraction. Undeclared path params are captured but
ignored (partial extraction).
Handler-level middleware
async
// Factory middleware (called with arguments)
async
Bare middleware paths are wrapped with axum::middleware::from_fn. Paths
followed by (args) are called as layer factories.
Route modules
// With module-level middleware
All #[handler] attributes inside the module are automatically associated
with the module's prefix and middleware at compile time.
Custom error handler
The function must be sync and accept exactly (modo::Error, &modo::ErrorContext).
It is registered via inventory and invoked for every unhandled modo::Error.
Input sanitization
Available #[clean(...)] rules: trim, lowercase, uppercase,
strip_html_tags, collapse_whitespace, truncate = N, normalize_email,
custom = "path::to::fn".
Input validation
// In a handler:
async
Available #[validate(...)] rules: required, min_length = N,
max_length = N, email, min = V, max = V, custom = "path::to::fn".
Each rule accepts an optional (message = "...") override.
Templates (requires templates feature)
// With a separate HTMX partial
Localisation (requires i18n feature)
// In a handler with an I18n extractor:
let msg = t!;
let items = t!;
t! calls i18n.t_plural when a count variable is present.
Key Macros
| Macro | Kind | Purpose |
|---|---|---|
#[handler] |
attribute | Register an async fn as an HTTP route |
#[main] |
attribute | Application entry point and runtime bootstrap |
#[module] |
attribute | Group routes under a shared prefix |
#[error_handler] |
attribute | Register a custom error handler |
#[Sanitize] |
derive | Generate Sanitize::sanitize from #[clean] fields |
#[Validate] |
derive | Generate Validate::validate from #[validate] fields |
t! |
function-like | Localisation key lookup with variable substitution |
#[view] |
attribute | Link a struct to a MiniJinja template |
#[template_function] |
attribute | Register a MiniJinja global function |
#[template_filter] |
attribute | Register a MiniJinja filter |