damask

React-like components for Rust whose templates compile away.

The Damask mark — a four-petalled quatrefoil drawn in madder red inside a rounded square, on a dark ground printed with a faint woven pattern

React-like components for Rust, resolved entirely at build time. A component is a struct — its fields are its props — paired with an HTML template written in a { … } tag syntax. The Component derive finds the .dmk file sitting next to the struct and compiles it into a render method, so what runs is plain, allocation-light Rust: no template engine, no parsing, nothing to load at startup. There is no build.rs and nothing to configure; editing a template rebuilds the crate.

Most of the interest is in what the compiler is made to catch. Capitalized tags are components, and an attribute no field declares is a build failure naming it — a misspelled prop cannot quietly render into the page. Attribute values are typed rather than stringified: a bool writes a bare disabled or nothing at all, an Option writes nothing when None, because in HTML the presence of the attribute is what disables the control. {@tokens} builds one value out of many parts, {@attrs} expands into a run of data-* or aria-* pairs, and {...expr} splices attributes a component cannot name.

Slots are the web-component pair — <slot/> places, slot="…" fills — and live off the struct, so a template declares as many as it likes without the type changing; a <slot> written where a fill goes forwards it to a child. Snippets are reusable fragments with parameters, which is how render-props are spelled. And .await anywhere the template holds Rust compiles that component to an async render path — decided from the template itself, at no cost to one that does not await. The render future is Send, so a request handler can await it.

Beside the crate: a language server with diagnostics and completion, a Zed extension, and a Tree-sitter grammar the documentation site highlights with — so a snippet reads the same on the page as it does in an editor.

Rust, MIT, on crates.io: cargo add damask, with cargo install damask-lsp for the language server.