| Crates.io | loomx |
| lib.rs | loomx |
| version | 0.1.0-alpha.1 |
| created_at | 2025-12-18 23:17:21.026663+00 |
| updated_at | 2025-12-18 23:17:21.026663+00 |
| description | Typed headless rendering for HTMX |
| homepage | |
| repository | https://github.com/cvandeluitgaarden/loomx-rs |
| max_upload_size | |
| id | 1993804 |
| size | 24,491 |
loomx is a strongly‑typed, server‑driven UI framework for Rust. It renders HTML fragments and pages using typed components, designed for HTMX‑first applications with minimal JavaScript.
At its core, loomx lets you:
Non‑goals:
loomx/
├─ crates/
│ ├─ loomx-core # Registry, rendering, props parsing
│ ├─ loomx-macros # register_component! macro
│ ├─ loomx-axum # Axum integration (routes, handlers)
│ └─ loomx-cli # CLI (experimental)
├─ components/
│ └─ loomx-components-basic
│ └─ Example component pack
├─ examples/
│ └─ basic # Example Axum app
A component is:
#[derive(Template, Deserialize)]
#[template(path = "components/hello.html")]
pub struct Hello {
pub name: String,
}
impl Component for Hello {
const NAME: &'static str = "hello";
}
register_component!(Hello);
Components are registered at compile time using inventory.
Duplicate component names are detected at startup.
use loomx::render;
let html = render("hello", json!({ "name": "Ada" }))?;
Rendering returns HTML or a typed error.
loomx-core provides a transport‑agnostic parser:
application/jsonapplication/x-www-form-urlencodedparse_props(content_type, body_bytes)
This logic is reused by all integrations.
loomx-axum provides:
GET /fragments/:name → query paramsPOST /fragments/:name → form or JSON bodyRouter::new().merge(loomx_axum::fragment_router())
Router::new().merge(
loomx_axum::typed_fragment_routes! {
"/fragments/hello" => ("hello", HelloProps),
}
)
This generates:
GET /fragments/helloPOST /fragments/hello (form)POST /fragments/hello/json (JSON)All fully typed.
loomx is HTMX‑first:
hx-get, hx-post, hx-swapNo JS framework required.
Structured logging via tracing:
loomx is early but functional.
Current focus:
MIT
loomx now provides an ergonomic typed rendering helper:
render_with<T: Serialize>(name, &T) — preferred for application codeThis avoids manual construction of serde_json::Value while preserving the dynamic
component registry model.
The example application includes an interactive component gallery at /gallery
showing:
/typed/...See docs/gallery.md for details.