Modern asset processing for Jekyll with image transformations:
srcset
generationurl()
rewriting - automatic asset path updatesGemfile
:group :jekyll_plugins do
gem 'jekyll-skyhook'
end
And then run
bundle install
For ImageMagick (default):
# Ubuntu/Debian:
sudo apt-get install imagemagick
# macOS:
brew install imagemagick
For libvips (faster alternative):
# Ubuntu/Debian:
sudo apt-get install libvips
# macOS:
brew install vips
_digested
directory to .gitignore
Add to _config.yml
:
skyhook:
# Directories to process (default: ['assets'])
asset_dirs: [assets, images]
# When to digest assets (default: true)
# Can be:
# - true (always digest)
# - false (never digest)
# - string (digest in specific environment)
# - array (digest in multiple environments)
digest_assets: true
# Examples:
# digest_assets: true
# digest_assets: false
# digest_assets: production
# digest_assets: [staging, production]
# Directory for digested assets (default: '_digested')
digest_dir: '_digested'
# Image processing library (default: 'mini_magick')
# Options: 'mini_magick' or 'vips'
# vips is faster but requires libvips to be installed
image_processor: mini_magick
# Include digested files in build
include:
- _digested
Use the {% asset %}
tag for regular assets with cache-busting digests:
<link rel="stylesheet" href="{% asset assets/styles.css %}">
<script src="{% asset assets/app.js %}"></script>
Use the {% image_transform %}
tag with bracket syntax for image transformations:
<!-- Resize image -->
{% image_transform assets/hero.jpg[width="400"] %}
<!-- Convert format -->
{% image_transform assets/hero.jpg[format="webp"] %}
<!-- Multiple transformations -->
{% image_transform assets/hero.jpg[width="800"][format="avif"] %}
<!-- Use in img tag -->
<img src="{% image_transform assets/hero.jpg[width="400"][format="webp"] %}"
alt="Hero image" loading="lazy">
width="400"
- Resize to maximum width (maintains aspect ratio)height="300"
- Resize to maximum height (maintains aspect ratio)format="webp"
- Convert to WebP, AVIF, PNG, or JPEGUse the {% srcset %}
tag to generate responsive image sets:
<!-- Generate multiple sizes in original format -->
{% srcset assets/hero.jpg 400 800 1200 %}
<!-- Generate multiple sizes in specific format -->
{% srcset assets/hero.jpg[format="webp"] 400 800 1200 %}
Create modern responsive images with multiple formats:
<picture>
<!-- AVIF sources -->
<source
type="image/avif"
{% srcset assets/hero.jpg[format="avif"] 400 800 1200 %}
sizes="(max-width: 600px) 100vw, 50vw">
<!-- WebP fallback -->
<source
type="image/webp"
{% srcset assets/hero.jpg[format="webp"] 400 800 1200 %}
sizes="(max-width: 600px) 100vw, 50vw">
<!-- Original format fallback + lazy loading -->
<img
src="{% image_transform assets/hero.jpg[width="800"] %}"
{% srcset assets/hero.jpg 400 800 1200 %}
sizes="(max-width: 600px) 100vw, 50vw"
alt="Description of the image"
loading="lazy">
</picture>
You can use Liquid variables in transformations:
{% assign mobile_width = "400" %}
{% assign format = "webp" %}
<img src="{% image_transform {{ page.featured_image }}[width="{{ mobile_width }}"][format="{{ format }}"] %}">
For build scripts or advanced use cases, you can manually store processed images:
require 'image_processing/mini_magick'
# Process image
processed = ImageProcessing::MiniMagick
.source("assets/hero.jpg")
.resize_to_limit(400, 400)
.convert("webp")
.call
# Store in Skyhook manifest
skyhook = Jekyll::Skyhook.instance(site)
skyhook.store_version("assets/hero.jpg", {format: "webp", width: "400"}, processed.path)
your-site/
├── assets/
│ ├── hero.jpg # Original image
│ ├── styles.css # Original CSS
│ └── app.js # Original JS
├── _digested/ # Generated (add to .gitignore)
│ └── assets/
│ ├── hero-width400-abc123.webp
│ ├── hero-width800-def456.webp
│ ├── styles-xyz789.css
│ └── app-uvw012.js
├── _site/ # Jekyll build output
│ └── _digested/ # Digested assets maintain structure
│ └── assets/
│ ├── hero-width400-abc123.webp
│ ├── styles-xyz789.css
│ └── app-uvw012.js
└── .jekyll-cache/
└── skyhook/
└── assets-manifest.json # Tracks all transformations
assets-manifest.json
for fast lookups# Install ImageMagick
brew install imagemagick # macOS
sudo apt-get install imagemagick # Ubuntu/Debian
_config.yml
_digested
is included in Jekyll builddigest_assets: false
in development if needed--drafts
flag when working on draftsjekyll serve --drafts
and jekyll build --drafts
are supported