---
title: 'assets'
description: 'Baseline''s single assets module. Wires JS (esbuild) and CSS (PostCSS) entry points into Eleventy, with compile guards, watch targets, and inline filters for critical-path assets.'
slug: 'assets'
type: 'article'
date: 2026-04-13T00:00:00.000Z
lang: 'en'
url: 'https://www.eleventy-baseline.dev/docs/module/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

{% stepsBlock "compact" %}

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.

{% endstepsBlock %}

---

## Defaults

{% stepsBlock "compact" %}

- **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](_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.

{% endstepsBlock %}

---

### Options

{% tableBlock true %}

| Option           | Type   | Default | Meaning                                                                              |
| ---------------- | ------ | ------- | ------------------------------------------------------------------------------------ |
| `assets.esbuild` | object | `{}`    | Forwarded to esbuild on every entry-point build and inline call. Merged on defaults. |

{% endtableBlock %}

PostCSS has no plugin-level options. Configure it through your own `postcss.config.js`. See [[customise-assets-pipeline | 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`:

```js
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) {
	await 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:

{% raw %}

```nunjucks
{% set jsPath = _baseline.paths.assets ~ "js/inline-example.js" %}
{{ jsPath | inlineESbuild({ minify: false, target: "es2017" }) | safe }}
```

{% endraw %}

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-assets-pipeline | Customise the assets pipeline]] for the steps.

The `inlinePostCSS` filter wraps any CSS file in `<style>` tags:

{% raw %}

```nunjucks
{% set cssPath = _baseline.paths.assets ~ "css/critical.css" %}
{{ cssPath | inlinePostCSS | safe }}
```

{% endraw %}

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

- [[image-shortcode | Image shortcode]] reads `_baseline.paths.assets` for default lookups.
- [[filters | Filters reference]] lists `inlineESbuild` and `inlinePostCSS` alongside the rest.
- [[customise-assets-pipeline | Customise the assets pipeline]]
- [[assets-pipeline | Tutorial: assets pipeline]]
