Table of Contents
assets
INTERNAL_KEY: '_assets'
What it does
The assets module is the bridge between Eleventy's template system and the asset processors. It registers js and css as template formats, gates them with compile guards (filters that decide which files get processed), watches the assets directory for changes, and exposes two inline filters for embedding bundles directly in a template.
esbuild handles JS, PostCSS handles CSS. Both ship with Baseline.
Active when
Always. The assets module is always loaded.
Lifecycle
Build-time only. The module registers template formats, compile guards, a watch target, and the inline filters. It does no cascade-time or transform-time work.
How it works
- Resolve the assets directory. The composition root registers a virtual directory keyed
assetsand exposes the resolved path through_baseline.paths.assets. - Register
jsandcsstemplate formats. Each gets an extension handler withread: falseso the driver owns its own I/O. - Apply compile guards. A compile guard is a small filter inside the extension handler. JS guards: only
index.jsfiles underassets/js/are processed;11tydata.jsfiles are also explicitly excluded from the template graph. CSS guard: onlyindex.cssfiles underassets/css/. Anything else returns undefined and is skipped without error. - Watch the assets directory. The watch glob covers JS, CSS, and common image formats so an asset edit triggers a reload during
npm run dev. - Register inline filters. An inline filter runs the driver against a path you give it and wraps the result in
<script>or<style>tags. See the driver subsections below.
Defaults
- Assets directory. The virtual directory keyed
assetsoneleventyConfig.directories. Defaults tosrc/assets/per the directory contract. Available in templates as_baseline.paths.assets. - JS entry points. Any
index.jsunderassets/js/(including nested folders). An entry point is the front door of a bundle; everything else is reached throughimportfrom there. - CSS entry points. Any
index.cssunderassets/css/. Reach the rest through@import. - esbuild.
minify: true,target: 'es2020'. Defaults live in _baseline/modules/assets/processors/esbuild-process.js. - PostCSS. Resolves your project's
postcss.config.jsfrom the project root (cwd). If none is found, falls back to the config bundled with baseline (postcss-import,postcss-preset-env,cssnanoin production). The resolved config is cached for the lifetime of the process; restart Eleventy to pick up changes. - Watch target.
assets/**/*.{css,js,svg,png,jpeg,jpg,webp,gif,avif}. A watch target is a glob Eleventy reloads on during--serve. - Output. Compiled files land under
dist/assets/, mirroring the input layout.
Options
| Option | Type | Default | Meaning |
|---|---|---|---|
assets.esbuild |
object | {} |
Forwarded to esbuild on every entry-point build and inline call. Merged on defaults. |
PostCSS has no plugin-level options. Configure it through your own postcss.config.js. See Customise the assets pipeline for the recipe.
JS processor: esbuild
The JS processor bundles a JavaScript file and returns the compiled text. A pure function with no Eleventy knowledge: takes a path, returns a string.
At the plugin level, override esbuild defaults through options.assets.esbuild:
import baseline, { config as baselineConfig } from '@apleasantview/eleventy-plugin-baseline';
import settings from './src/_data/settings.js';
/** @param {import("@11ty/eleventy").UserConfig} eleventyConfig */
export default async function (eleventyConfig) {
eleventyConfig.addPlugin(
baseline(settings, {
assets: {
esbuild: {
minify: process.env.ELEVENTY_ENV === 'production',
target: 'es2017'
}
}
})
);
}
export const config = baselineConfig;
These apply to both compiled entry points and the inline filter, unless overridden per call.
Per call, the inlineESbuild filter accepts an options object that merges with the defaults:
{% set jsPath = _baseline.paths.assets ~ "js/inline-example.js" %}
{{ jsPath | inlineESbuild({ minify: false, target: "es2017" }) | safe }}
The filter is not limited to the assets directory: pass any absolute path. In Markdown, keep the call unindented and on its own lines so the <script> tag is treated as raw HTML, and pipe through | safe so Nunjucks does not escape it.
On error, the processor logs and returns /* Error processing JS */ so the build does not break.
CSS processor: PostCSS
The CSS processor runs a CSS file through PostCSS and returns the compiled text. Pure function, same shape as the JS processor.
It does not take plugin-level options. Configure it through postcss.config.js at your project root. See Customise the assets pipeline for the steps.
The inlinePostCSS filter wraps any CSS file in <style> tags:
{% set cssPath = _baseline.paths.assets ~ "css/critical.css" %}
{{ cssPath | inlinePostCSS | safe }}
Same Markdown caveat: keep the call unindented, pipe through | safe. Useful for critical CSS that should render before the main stylesheet loads.
On error, the processor logs and returns /* Error processing CSS */.
Tips
- Only
index.jsandindex.cssare compiled. Use them as entry points; reach everything else throughimportand@import. - The watch target covers images too, so editing an SVG or PNG triggers a reload without extra config.
- The bundled PostCSS fallback is a sensible starting point. You only need your own
postcss.config.jswhen you want to customise plugins. - Inline filters are useful for small critical-path assets. Avoid inlining anything large; the bundle ends up duplicated on every page.
Peer deps
esbuild and postcss. Both ship with Baseline.
See also
- Image shortcode reads
_baseline.paths.assetsfor default lookups. - Filters reference lists
inlineESbuildandinlinePostCSSalongside the rest. - Customise the assets pipeline
- Tutorial: assets pipeline