Building 64 UI Components in Rust Without a Framework
How maud-ui delivers shadcn-quality components with zero JavaScript framework, 22 KB gzipped, using maud templating and htmx.
I shipped maud-ui this week: 64 accessible, headless UI components for Rust web applications. No React, no virtual DOM, no build step for consumers. Just pure Rust functions that return HTML.
The bet was simple: maud for templating, htmx for interactivity, and shadcn/ui as the visual reference. The result is 22 KB gzipped (JS + CSS combined) and works with any Rust web framework.
Why Rust for UI components?
The Rust web ecosystem has excellent server frameworks (Axum, Actix) but the component story is thin. If you want styled, interactive UI, your options are: write raw HTML strings, use a heavyweight WASM framework like Leptos, or reach for JavaScript.
maud-ui fills the gap. Components are pure functions: Props -> Markup. No state management, no lifecycle hooks, no hydration. The server renders HTML, htmx handles interactivity, and CSS custom properties handle theming.
The three tiers
The 64 components are organized into three capability tiers:
- Static (pure HTML/CSS): buttons, badges, cards, typography
- Interactive (HTML/CSS + htmx attributes): accordions, tabs, dialogs, command palette
- Rich (HTML/CSS + htmx + a small JS widget): code editor (Monaco), charts, data grids
Each tier adds a dependency layer but the consumer only pays for what they use.
What I learned
Building a component library in a systems language forces different design decisions. No useState, no useEffect, no reactivity model. Every interaction is an HTTP round-trip or a CSS transition. This constraint is liberating: the components are fast, accessible by default, and trivially cacheable.
The live demo is at maudui.herman.engineer.