[][src]Crate render

🔏 A safe and simple template engine with the ergonomics of JSX

render itself is a combination of traits, structs and macros that together unify and boost the experience of composing tree-shaped data structures. This works best with HTML and XML rendering, but can work with other usages as well, like ReasonML's Pastel library for terminal colors.


A renderable component is a struct that implements the Render trait. There are multiple macros that provide a better experience implementing Renderable:

  • #[component] for defining components using a function
  • rsx! for composing elements with JSX ergonomics
  • html! for composing elements and render them to a string

Why is this different from...


Handlebars is an awesome spec that lets us devs define templates and work seemlessly between languages and frameworks. Unfortunately, it does not guarantee any of Rust's type-safety, due to its spec. This forces you to write tests for validating types for your views, like you would in a dynamically typed language. These tests weren't necessary in a type-safe language like Rust — but Handlebars is JSON-oriented, which doesn't comply Rust's type system.

render provides the same level of type-safety Rust provides, with no compromises of ergonomics or speed.


typed-html is a wonderful library. Unfortunately, it focused its power in strictness of the HTML spec itself, and doesn't allow arbitrary compositions of custom elements.

render takes a different approach. For now, HTML is not typed at all. It can get any key and get any string value. The main focus is custom components, so you can create a composable and declarative template with no runtime errors.


Note: render needs the nightly Rust compiler, for now, so it will have hygienic macros.

This means you will need to add the following feature flag in the root of your lib.rs/main.rs:


Simple HTML rendering

In order to render a simple HTML fragment into a String, use the rsx! macro to generate a component tree, and call render on it:


use render::{rsx, Render};

let tree = rsx! {
    <p>{"Hello world!"}</p>

assert_eq!(tree.render(), "<div><h1>Hello!</h1><p>Hello world!</p></div>");

Because this is so common, there's another macro called html! that calls rsx! to generate a component tree, and then calls render on it. Most of the time, you'll find yourself using the rsx! macro to compose arbitrary components, and only calling html! when you need a String output, when sending a response or generating a Markdown file.

In Render, attributes and plain strings are escaped using the render::html_escaping module. In order to use un-escaped values so you can dangerously insert raw HTML, use the raw! macro around your string:


use render::{html, raw};

let tree = html! {
    <p>{"<Hello />"}</p>
    <p>{raw!("<Hello />")}</p>

assert_eq!(tree, "<div><p>&lt;Hello /&gt;</p><p><Hello /></p></div>");

Custom components

Render's greatest ability is to provide type-safety along with custom renderable components. Introducing new components is as easy as defining a function that returns a Render value.

In order to build up components from other components or HTML nodes, you can use the rsx! macro, which generates a Render component tree:


use render::{component, rsx, html};

fn Heading<'title>(title: &'title str) {
  rsx! { <h1 class={"title"}>{title}</h1> }

let rendered_html = html! {
  <Heading title={"Hello world!"} />

assert_eq!(rendered_html, r#"<h1 class="title">Hello world!</h1>"#);

If you pay close attention, you see that the function Heading is:

  • declared with an uppercase. Underneath, it generates a struct with the same name, and implements the Render trait on it.
  • does not have a return type. This is because everything is written to a writer, for performance reasons.

Full example


// A simple HTML 5 doctype declaration
use render::html::HTML5Doctype;
use render::{
    // A macro to create components
    // A macro to compose components in JSX fashion
    // A macro to render components in JSX fashion
    // A trait for custom components

// This can be any layout we want
fn Page<'a, Children: Render>(title: &'a str, children: Children) {
   rsx! {
       <HTML5Doctype />

// This can be a route in Rocket, the web framework,
// for instance.
pub fn some_page(user_name: &str) -> String {
    html! {
      <Page title={"Home"}>
        {format!("Welcome, {}", user_name)}


pub use fragment::Fragment;



The fragment component


HTML utilities




Render a component tree to an HTML string, using XML-like tags.


Creates a raw (unencoded) html string


Generate a renderable component tree, before rendering it



A raw (unencoded) html string


Simple HTML element tag



Render a component

Attribute Macros


A syntactic sugar for implementing Render conveniently using functions.