RSTRust-First Site ToolkitA Rust-first static site generator with typed collections, explicit routes, and a format-agnostic asset pipeline.

Solve one concrete task

Generate non-HTML routes

Emit XML, JSON, and plain-text outputs without treating them as special cases.

Generate XML, JSON, and text outputs

Non-HTML outputs are first-class routes. Use them for things like:

  • /sitemap.xml

  • /robots.txt

  • /_headers

  • JSON indexes and feeds

Choose the right route API

Use page(...) when the route path is already known:

.page("/sitemap.xml", |ctx| {
    let mut xml = String::from(r#"<?xml version="1.0" encoding="UTF-8"?><sitemapindex>"#);

    for route in ctx.routes() {
        if route.has_attribute("family", "sitemap") {
            xml.push_str("<sitemap><loc>");
            xml.push_str(&route.path);
            xml.push_str("</loc></sitemap>");
        }
    }

    xml.push_str("</sitemapindex>");
    Ok(Artifact::Xml(xml))
})

Use file(...) when the output should be a literal flat file rather than a page-like route:

.file("/robots.txt", |_| {
    Ok(Artifact::Text(
        "User-agent: *\nAllow: /\nSitemap: /sitemap.xml\n".to_string(),
    ))
})

Use generated_routes(...) when content decides how many non-HTML outputs should exist:

.generated_routes(
    |_ctx| {
        Ok(vec![
            GeneratedRoute::file(
                "/_headers",
                "/*\n  X-Frame-Options: DENY\n".to_string(),
            )
            .with_attribute("kind", "hosting-config"),
        ])
    },
    |_ctx, text| Ok(Artifact::Text(text.clone())),
)

Pick the matching artifact

Use the artifact that matches the semantics of the bytes you are generating:

  • Artifact::Html

  • Artifact::Xml

  • Artifact::Json

  • Artifact::Text

Artifact kind and filename are intentionally independent. A text artifact can be written to events.log, and a JSON artifact can be written to an extensionless API file if you register it through file(...).

Decide the page output policy separately

Page-like routes can emit either:

  • /slug/index.html

  • /slug.html

That policy belongs to the site configuration, not to the artifact type. Explicit flat files always keep the literal output path you registered.