Table of Contents

Assets pipeline quickstart

Ship CSS and JS through Baseline's assets module. One entry point each, compiled on every build, plus a pair of filters for the times you want the bytes in the page rather than in a file.

That, taken together, is what Baseline calls the assets pipeline.

The assets module is always on. PostCSS and esbuild are its processors, the small adapters that wire each pipeline into Eleventy. Bring your own configs, or let Baseline fall back to its defaults.


What you will build

  • src/assets/css/index.css bundled through PostCSS, using your config or Baseline's fallback.
  • src/assets/js/index.js bundled and minified through esbuild.
  • Optionally, the same content inlined into a template through inlinePostCSS and inlineESbuild.

Create src/content/pages/assets-quickstart.md:

---
title: 'Assets Quickstart'
slug: 'assets-quickstart'
description: 'CSS and JS bundled by Baseline.'
layout: 'layouts/base.njk'
---

CSS should style this page, and JS should log to the console. Here is a small badge:

<span class="pill">Pending</span>

The <link rel="stylesheet"> and <script> tags come from settings.head (set up in the simple site tutorial), so the layout never needs to know they exist. Baseline injects them into every page.


Author the CSS entry

Create src/assets/css/index.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;
}

If a postcss.config.js exists at the project root, Baseline picks it up. Otherwise it falls back to its built-in config.


Author the JS entry

Create src/assets/js/index.js:

document.addEventListener('DOMContentLoaded', () => {
	console.log('Baseline assets: JS is loaded');
	const pill = document.querySelector('.pill');
	if (pill) {
		pill.textContent = 'Bundled JS is running';
	}
});

Run the site locally

npm start
  • Open the local URL (default http://localhost:8080/). Confirm the styles apply and the console log fires.
  • Dev writes to dist/ as it runs, so dist/assets/css/index.css and dist/assets/js/index.js are inspectable while the server is up.
  • Image-format changes (png, jpg, webp, gif, avif, svg) under src/assets/ also trigger a rebuild during npm start.

Eleventy never cleans dist/ for you. Clear it with npx rimraf dist/ whenever a rebuild looks stale.

Production build and inspect output

npm run build

Check dist/assets/css/index.css for the PostCSS output, and dist/assets/js/index.js for the bundled and minified JS. The difference from npm start is the CSS: ELEVENTY_ENV=production is what turns cssnano on in Baseline's fallback PostCSS config. esbuild minifies in every mode, so the JS looks the same either way. Customise the assets pipeline shows how to make that conditional too.


Next steps

  • Drop a postcss.config.js at the project root when you want to bring your own plugins.
  • Add more entry points as the site grows; section-specific index.css files under subfolders work the same way.
  • Reach for inlinePostCSS and inlineESbuild on critical snippets only. Inlining a full bundle defeats the point.

See also