Image Optimization
Kiln automatically optimizes images at build time, generating responsive variants in modern formats. Every .png, .jpg, and .jpeg in your vault is resized at multiple breakpoints and encoded into AVIF and WebP alongside the original format. The result is a <picture> element that lets browsers pick the smallest file they support — no configuration required.
How it works
During a build, Kiln processes each optimizable image through a simple pipeline:
- Decode the source image
- Resize to each breakpoint that is smaller than the original width (1200px, 800px, 400px)
- Encode every resized version into three formats — AVIF (best compression), WebP (good compression), and the original format (fallback)
- Generate HTML using a
<picture>element with<source>tags for each format
Each image can produce up to 9 variants (3 breakpoints times 3 formats). All encoding uses a fixed quality of 80. If the original image is narrower than a given breakpoint, that breakpoint is skipped.
Format priority in the generated HTML follows the order AVIF > WebP > original, so browsers that support AVIF will download the smallest file first.
Supported formats
| Input format | Optimized? | Output formats produced |
|---|---|---|
.png | Yes | AVIF, WebP, PNG |
.jpg / .jpeg | Yes | AVIF, WebP, JPEG |
.gif | No | Copied as-is |
.svg | No | Copied as-is |
.webp | No | Copied as-is |
Images that are not optimized are still copied to the output directory — they just skip the resize-and-encode pipeline.
Requirements
Kiln shells out to two external CLI tools for modern format encoding:
cwebp(from the libwebp package) — converts images to WebPavifenc(from the libavif project) — converts images to AVIF
Install them on common systems:
# Debian / Ubuntu
sudo apt install webp libavif-bin
# macOS (Homebrew)
brew install webp libavif
# Nix
nix-shell -p libwebp libavif
If either tool is missing, Kiln silently skips that format and falls back to copying the original image. Your build will not fail — you simply won't get the optimized variants for the missing encoder.
The generated HTML
For each optimized image, Kiln emits a <picture> element wrapping multiple <source> tags and a fallback <img>. Here is a representative example for a PNG with all three breakpoints:
<figure class="img-figure">
<picture>
<source type="image/avif"
srcset="/img/photo-400w.avif 400w, /img/photo-800w.avif 800w, /img/photo-1200w.avif 1200w"
sizes="min(65ch, 100vw)">
<source type="image/webp"
srcset="/img/photo-400w.webp 400w, /img/photo-800w.webp 800w, /img/photo-1200w.webp 1200w"
sizes="min(65ch, 100vw)">
<source type="image/png"
srcset="/img/photo-400w.png 400w, /img/photo-800w.png 800w, /img/photo-1200w.png 1200w"
sizes="min(65ch, 100vw)">
<img src="/img/photo.png" alt="A photo" sizes="min(65ch, 100vw)" loading="lazy">
</picture>
<button class="img-expand-btn" aria-label="View full size" type="button">...</button>
</figure>
Key details:
srcsetlists each variant with its width descriptor (e.g.,400w)sizesis set tomin(65ch, 100vw), matching the content column widthloading="lazy"on the fallback<img>defers off-screen images- An expand button (lightbox) is added to every image, allowing readers to view the full-size version
Images that have no optimized variants (unsupported format, or encoders missing) receive a plain <img loading="lazy"> tag with the expand button.
Usage
No configuration is needed. Reference images in your markdown the way you normally would:

Or with Wikilinks syntax:
![[photo.jpg]]
![[photo.jpg|Alt text goes here]]
Kiln detects supported formats and produces the optimized <picture> output automatically.
Limitations
- External tools required — WebP and AVIF encoding depend on
cwebpandavifencbeing available on your PATH - Fixed breakpoints — the resize widths (1200, 800, 400) are hard-coded and not configurable
- Fixed quality — encoding quality is set to 80 and cannot be changed
- GIF and SVG are not optimized — these formats are copied as-is
- Increased output size — each optimizable image can produce up to 9 variant files, increasing total disk usage
- Longer builds — image encoding adds build time proportional to the number and size of images in your vault