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

Blog

Probe Authored Images Without Decoding Them

New image-probing helpers let route handlers and markdown components inspect authored image format and dimensions before deciding which outputs to generate.

Probe first, transform second

The asset pipeline now exposes a small image-probing API for the cases where site code really does need to branch on the authored source image.

If you want the task-oriented version first, start with Work with content images and Override markdown components. For the exact public API, see Site-building API.

The key constraint is that this should not require decoding the full image into pixels just to learn basic facts such as:

  • what format the authored image uses

  • how large it is

  • whether it is vector-based

That is useful when the site wants to choose output widths, skip unnecessary downscales, or decide whether a vector-specific path makes more sense than a raster path.

The public API surface

The main entry points are:

  • RenderContext::probe_image(...)

  • ComponentProps::probe_image(...)

  • ImageProbe

  • ImageProbeFormat

The lower-level asset crate also exposes:

  • probe_image_bytes(...)

  • probe_image_path(...)

The site-facing API stays small

From a route handler, the entry point is:

let probe = ctx.probe_image(entry, reference)?;

The result carries three fields:

pub struct ImageProbe {
    pub format: ImageProbeFormat,
    pub width: u32,
    pub height: u32,
}

The format enum is intentionally about the authored source:

pub enum ImageProbeFormat {
    Avif,
    Jpeg,
    Png,
    Svg,
    Webp,
}

Both ImageProbe and ImageProbeFormat also expose is_vector() for the common SVG case.

One use case: choose responsive widths from the source image

If the authored image is already smaller than the largest width you would normally emit, you can branch on the probe result before asking the asset pipeline for responsive outputs:

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

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

That keeps the route code explicit:

  • probe the authored asset

  • decide what outputs are worth generating

  • then ask for the outputs you actually want

Markdown components can use the same idea

The same capability is available in markdown components:

let probe = props.probe_image("src")?;

That matters because markdown-authored images are often where the site has the least a priori knowledge about source dimensions.

For example, a custom img component can decide whether it should:

  • keep an SVG on a vector-first path

  • emit a width-based srcset

  • skip large responsive variants for a small authored raster image

The lower-level helpers stay path-based

The public site code normally reaches this through site-core.

The lower-level probing helpers live in ultrashiny, which matches the rest of the repository:

  • site-core keeps the site-facing API small and readable

  • site-core resolves authored references relative to the source document

  • ultrashiny owns the heavier probing and transform implementation once it has a resolved path

Dependency tracking still works

RenderContext::probe_image(...) records the authored source image as a route dependency.

That means a route that only probes an image still rebuilds correctly if that source image changes later. Probing is lightweight, but it is still part of the build graph.

What this does not do

This API is intentionally narrow.

It does not replace the format-agnostic output API, and it does not expose pixel data, color metadata, or any transform controls. It only gives site code enough information to make higher-level decisions before requesting actual outputs.

That keeps the common path simple:

  • ask for the output you want when source details do not matter

  • probe first only when the authored source really changes the decision

Prototype diagramThe checked-in SVG still works as an ordinary markdown image

Where to go next