---
title: 'Customise the Assets Pipeline'
description: 'Override Baseline''s fallback PostCSS config, add esbuild entry points, and set targets and minification for the assets module.'
slug: 'customise-assets-pipeline'
type: 'article'
date: 2026-01-25T00:00:00.000Z
lang: 'en'
url: 'https://www.eleventy-baseline.dev/docs/how-to/customise-assets-pipeline/'
---

When the fallback configs in the assets module are not enough, drop your own in. PostCSS for CSS, esbuild for JS. The module picks them up.

---

## Prerequisites

- Baseline registered in `eleventy.config.js`.
- Default entries in place: `src/assets/css/index.css` and `src/assets/js/index.js`.
- `package.json` with `"type": "module"` and scripts (`start`, `build`).

---

## PostCSS config

A `postcss.config.js` at the project root replaces Baseline's fallback wholesale. Bring the plugins you want, gate cssnano on production, and check the output.

### 1) Install PostCSS and the plugins you plan to use:

```bash
npm install postcss postcss-import postcss-preset-env cssnano postcss-mixins
```

Once you ship your own `postcss.config.js`, the fallback plugins are gone. Whatever you list here has to be installed explicitly.

---

### 2) Add `postcss.config.js` at the project root:

```js
import postcssImport from 'postcss-import';
import postcssMixins from 'postcss-mixins';
import postcssPresetEnv from 'postcss-preset-env';
import cssnano from 'cssnano';

const isProd = process.env.ELEVENTY_ENV === 'production';

const plugins = [postcssImport(), postcssMixins(), postcssPresetEnv({ stage: 1 })];

if (isProd) {
	plugins.push(cssnano({ preset: 'default' }));
}

/** @type {import('postcss-load-config').Config} */
export default {
	map: isProd ? false : { inline: true },
	plugins
};
```

---

### 3) Exercise the config in your CSS (imports and mixins):

`src/assets/css/base.css`:

```css
:root {
	color-scheme: light;
}

body {
	font-family: system-ui, sans-serif;
	margin: 0;
	padding: 2rem;
	line-height: 1.5;
	color: #1f2937;
	background: #f8fafc;
}

h1 {
	margin-bottom: 0.5rem;
}

.pill {
	display: inline-block;
	padding: 0.25rem 0.75rem;
	border-radius: 999px;
	background: #e0f2fe;
	color: #0f172a;
	font-weight: 600;
}
```

`src/assets/css/mixins.css`:

```css
@define-mixin linksMixin {
	color: #0f172a;
	text-decoration: underline;
	text-decoration-color: #fc35b9;
	text-decoration-thickness: 2px;
	text-underline-offset: 3px;
	font-weight: 600;
}
```

`src/assets/css/links.css`:

```css
a {
	@mixin linksMixin;
}

a:hover {
	color: #fc35b9;
}
```

`src/assets/css/index.css`:

```css
@import './base.css';
@import './mixins.css';
@import './links.css';
```

---

### 4) Run and inspect.

- Dev: `npx rimraf dist/ && npm run dev`
- Build: `npx rimraf dist/ && npm run build`
- Check `dist/assets/css/index.css`:
  - Dev: expanded CSS with mapped imports; no minification.
  - Prod: minified (cssnano), imports flattened, custom media resolved.

### Notes

- Your `postcss.config.js` fully overrides Baseline's fallback. Keep the entry file at `src/assets/css/index.css` and add partials via imports.
- Reach for what you need (purge, RTL, lightningcss, others). Env guards are the cleanest way to keep dev output readable and production output optimised.

---

## Esbuild targets

The JS pipeline takes more nudging than the CSS one. You may want extra entry points, different targets, or a one-off inline bundle, and esbuild is the lever for all three.

---

### 1) Install and pin esbuild explicitly.

Baseline depends on esbuild already, but esbuild's own docs recommend pinning the version you build against:

```bash
npm install --save-exact --save-dev esbuild
```

---

### 2) Add additional entry points.

An entry point is the file Baseline hands to esbuild as the start of a bundle. Each `index.js` under `src/assets/js/**/` is one entry point and produces one bundle in `dist/assets/js/`:

```bash
mkdir -p src/assets/js/home src/assets/js/about
echo "console.log('home bundle');" > src/assets/js/home/index.js
echo "console.log('about bundle');" > src/assets/js/about/index.js
```

Reference them from a page's front matter:

```md
---
title: 'Hello Baseline'
description: 'A minimal Eleventy page powered by eleventy-plugin-baseline.'
permalink: '/'
layout: 'layouts/base.njk'
head:
  script:
    - src: '/assets/js/home/index.js'
      defer: true
---
```

---

### 3) Inline a small script.

For tiny helpers, inline the bundled output with Baseline's `inlineESbuild` filter. `_baseline.paths.assets` is the resolved input path to your assets directory; concatenating the relative path keeps the example portable:

{% raw %}

```nunjucks
{% set jsPath = _baseline.paths.assets ~ "js/about/index.js" %}
{{ jsPath | inlineESbuild | safe }}
```

{% endraw %}

This bundles and minifies the file with esbuild's `es2020` target, then injects a `<script>...</script>` tag.

---

### 4) Set default target and minification for all bundles.

Pass `assets.esbuild` options when you register Baseline:

```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;
```

---

### 5) Override target or minification for a specific inline script.

For one-offs, pass options directly to the filter. They merge over your defaults from `assets.esbuild`:

{% raw %}

```nunjucks
{% set jsPath = _baseline.paths.assets ~ "js/about/index.js" %}
{{ jsPath | inlineESbuild({ minify: false, target: "es2018" }) | safe }}
```

{% endraw %}

6. Verify.
   - Dev: `npm start`
   - Build: `npm run build`
   - Check `dist/assets/js/**/index.js` for bundled output and size.
   - For inlined scripts, view the page source and confirm the bundled code is present.

---

### Notes

- Baseline's default JS bundling: any `index.js` under `src/assets/js/**/` is bundled, minified, and targeted to `es2020`.
- Inline only for small helpers; keep larger bundles as external files so they cache.
- A global override is yours to maintain. Revisit it whenever your browser support changes.
- If you reach for the same inline overrides repeatedly, write your own filter that calls `inlineESbuild` with preset options and use that filter instead.

---

## See also

- [[assets | Assets module]]
- [[globals| Globals reference]]
