lariv-rs 0.1.0

Compile-time plugin web application framework built on Axum, SeaORM, Maud, and HTMX
Documentation
//! Step-by-step tutorial: build a minimal plugin that renders "Hello, World!".
//!
//! # Creating a Hello World plugin
//!
//! Follow these steps to define a plugin, register a route and page template, write a
//! handler, and boot the server.
//!
//! # Step 1: Create the plugin entrypoint (`mod.rs`)
//!
//! Every plugin needs a zero-sized tag struct and an `install` function generated by
//! [`define_plugin_install!`](crate::plugin_install::define_plugin_install):
//!
//! ```ignore
//! // src/plugins/hello/mod.rs
//! pub mod handlers;
//! pub mod routes;
//! pub mod templates;
//!
//! use lariv_rs::plugin_install::define_plugin_install;
//!
//! /// Plugin identity tag.
//! pub struct HelloTag;
//!
//! define_plugin_install! {
//!     plugin: HelloTag;
//!     /// Register hello templates and HTTP routes.
//!     steps: [
//!         templates(templates::Hook),
//!         http(routes::Hook),
//!     ]
//! }
//! ```
//!
//! # Step 2: Add HTTP routing (`routes.rs`)
//!
//! Routes are declared with [`define_plugin_routes!`](crate::define_plugin_routes).
//! Each line maps a path pattern to an async handler function:
//!
//! ```ignore
//! // src/plugins/hello/routes.rs
//! use lariv_rs::define_plugin_routes;
//! use super::handlers;
//!
//! define_plugin_routes! {
//!     plugin: HelloTag;
//!     routes: [
//!         get HelloRouteTag, "/hello", handlers::hello;
//!     ]
//! }
//! ```
//!
//! The macro generates a typed route tag (`HelloRouteTag`) with `.url()` and `.path()`
//! helpers for use in templates and redirects.
//!
//! # Step 3: Create the page template (`templates.rs`)
//!
//! Pages are plain structs that implement [`RenderTemplate`](crate::template::RenderTemplate)
//! and render Maud markup. Register them with [`define_register_items!`](crate::capability::define_register_items):
//!
//! ```ignore
//! // src/plugins/hello/templates.rs
//! use maud::{Markup, html};
//! use lariv_rs::{
//!     capability::define_register_items,
//!     components::ShellChrome,
//!     template::{RenderTemplate, TemplateCapability, TemplateOf, TemplateRegistrar},
//! };
//! use super::HelloTag;
//!
//! pub struct HelloPageTag;
//! pub struct HelloPage;
//!
//! impl RenderTemplate for HelloPage {
//!     fn render(&self, _chrome: &ShellChrome) -> Markup {
//!         html! {
//!             div class="container mx-auto p-8" {
//!                 h1 class="text-2xl font-bold" { "Hello, World!" }
//!             }
//!         }
//!     }
//! }
//!
//! define_register_items! {
//!     plugin: HelloTag;
//!     capability: TemplateCapability;
//!     trait: TemplateRegistrar;
//!     method: register_templates;
//!     wrapper: TemplateOf;
//!     bounds: [Clone];
//!     hook: Hook;
//!     items: [
//!         HelloIdx: HelloPageTag => HelloPage,
//!     ]
//! }
//! ```
//!
//! # Step 4: Write the handler (`handlers.rs`)
//!
//! Handlers are async Axum functions. For a simple page, build the template struct and
//! return HTML via [`html_built_page_or_app_layout`](crate::web::html_built_page_or_app_layout):
//!
//! ```ignore
//! // src/plugins/hello/handlers.rs
//! use lariv_rs::{
//!     components::{SharedChromeFolder, SlotCtx},
//!     http::Cap,
//!     web::{Htmx, html_built_page_or_app_layout},
//! };
//! use super::templates::HelloPage;
//!
//! pub async fn hello(
//!     Cap(chrome): Cap<SharedChromeFolder>,
//!     htmx: Htmx,
//! ) -> maud::Markup {
//!     let page = HelloPage;
//!     let slot_ctx = SlotCtx::default();
//!     html_built_page_or_app_layout(&page, &htmx, &chrome, &slot_ctx)
//! }
//! ```
//!
//! # Step 5: Bootstrap the server (`main.rs`)
//!
//! Install your plugin on a web app, load config, mount, and run:
//!
//! ```ignore
//! // src/main.rs
//! use lariv_rs::app::App;
//!
//! mod plugins {
//!     pub mod hello;
//! }
//!
//! #[tokio::main]
//! async fn main() -> anyhow::Result<()> {
//!     let app = App::new_web_app();
//!     let app = plugins::hello::install(app);
//!     let app = app.load_config("config.toml").await?;
//!     let mounted = app.mount();
//!     mounted.run().await
//! }
//! ```
//!
//! Create a minimal `config.toml` at the project root (or rely on defaults):
//!
//! ```toml
//! database_url = "sqlite://data/lariv.db?mode=rwc"
//! bind = "127.0.0.1:3000"
//! ```
//!
//! Run the server:
//!
//! ```text
//! cargo run
//! ```
//!
//! Open [http://127.0.0.1:3000/hello](http://127.0.0.1:3000/hello) in your browser.
//!
//! # Next steps
//!
//! - Add a dashboard tile: see [`super::app`] and [`define_register_apps!`](crate::apps::define_register_apps)
//! - Share a capability across plugins: see [`super::app`] (`cap_attach` / `cap_hook`)
//! - Load database records: see [`super::layers`] and [`super::entities`]
//! - Add plugin configuration: see [`super::config`]
//! - Full project layout: see [`super`] module documentation