EnglishNederlandsFrançais Toggle theme

Eleventy Baseline

Start building your site, skip the recurring setup work.
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

  1. Resolve the assets directory. The composition root registers a virtual directory keyed assets and exposes the resolved path through _baseline.paths.assets.
  2. Register js and css template formats. Each gets an extension handler with read: false so the driver owns its own I/O.
  3. Apply compile guards. A compile guard is a small filter inside the extension handler. JS guards: only index.js files under assets/js/ are processed; 11tydata.js files are also explicitly excluded from the template graph. CSS guard: only index.css files under assets/css/. Anything else returns undefined and is skipped without error.
  4. 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.
  5. 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 assets on eleventyConfig.directories. Defaults to src/assets/ per the directory contract. Available in templates as _baseline.paths.assets.
  • JS entry points. Any index.js under assets/js/ (including nested folders). An entry point is the front door of a bundle; everything else is reached through import from there.
  • CSS entry points. Any index.css under assets/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.js from the project root (cwd). If none is found, falls back to the config bundled with baseline (postcss-import, postcss-preset-env, cssnano in 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.js and index.css are compiled. Use them as entry points; reach everything else through import and @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.js when 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

Previous: Modules

Next: head