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

Solve one concrete task

Work with content images

Request the output image you want and let the pipeline stay agnostic to the source format.

Keep site code agnostic to the authored format

Images can come from either:

  • markdown body references such as ![hero](hero.svg)

  • frontmatter fields such as hero: hero-card.svg

The site code should describe the output it wants, not branch on whether the source was SVG, PNG, JPEG, WebP, or AVIF.

Generate an OpenGraph JPEG from any authored image

For a frontmatter-authored hero image:

let open_graph_image = entry
    .frontmatter
    .hero
    .as_deref()
    .map(|reference| {
        ctx.image_url(
            entry,
            reference,
            &ImageOutput::raster(ImageFormat::Jpeg, 1200, 630)
                .with_fit(ImageFit::Cover)
                .with_quality(82)
                .with_background(BackgroundColor::rgb(248, 244, 234))
                .rasterize_vector_inputs(),
        )
    })
    .transpose()?;

The route code does not need to care whether the source asset was vector or raster.

Probe an authored image before choosing outputs

When the authored source does matter, probe it first instead of decoding the full image:

let hero = ctx.probe_image(entry, reference)?;
let widths = if hero.width >= 1600 {
    [800, 1200, 1600]
} else {
    [hero.width]
};

The probe result reports:

  • the authored source format

  • width and height in pixels

  • whether the source is vector-based

Markdown components can do the same through ComponentProps::probe_image("src").

Generate responsive AVIF page imagery

For page content, ask for width-based responsive outputs:

let hero = ctx.responsive_image(
    entry,
    reference,
    &ResponsiveImageOutput::widths(ImageFormat::Avif, [768, 1200, 1600])
        .with_sizes("(min-width: 54rem) 54rem, calc(100vw - 2rem)"),
)?;

The returned value already contains src, and when relevant also srcset and sizes.

Keep SVG as SVG unless you explicitly opt out

Vector inputs stay vector by default.

That means:

  • ordinary page imagery keeps SVG output as SVG

  • width-based responsive requests collapse to a single src when the source stays vector

  • rasterization is explicit

Opt into rasterization only when the destination format requires it, such as OpenGraph JPEG output.

Override markdown image rendering

When images originate in markdown, override the generated img tag through a markdown component:

.markdown_component("img", components::responsive_image)

That keeps image policy in one place instead of scattering repeated srcset logic through route handlers.

For a more general walkthrough of markdown-generated tag overrides, see Override markdown components.