Wire in Baseline
This is the page where Baseline arrives. Two files, and both the kind you write once and rarely open again.
Add the plugin
The config file is short, and its last line is the strangest thing in the whole tutorial. Create eleventy.config.js in the project root:
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));
}
export const config = baselineConfig;
baseline() takes two arguments: settings, which is what your site is, and options, which is how Baseline behaves. Passing settings only leaves every option at its default, which is the set this tutorial wants.
Now that last line. Eleventy has already chosen its directories by the time a plugin loads, so Baseline ships them as a separate export and asks you to forward it. That is what makes src/ the input and dist/ the output. Leave it off and Baseline still runs, badly, in a project it cannot see.
Why there are two surfaces rather than one is on how Baseline works; the contract that last line forwards is the config export reference's.
Give the site its identity
Next, the file eleventy.config.js just imported. This one is your site's identity, the things that would still be true if you rewrote every template tomorrow.
It lives in src/_data/, so every template can read settings.title without importing anything. Why the location matters is on project structure.
Create src/_data/settings.js:
export default {
title: 'Simple Baseline Site',
tagline: 'Hello, Eleventy + Baseline',
url: process.env.BASELINE_URL,
defaultLanguage: 'en',
noindex: false,
head: {
link: [{ rel: 'stylesheet', href: '/assets/css/index.css' }],
script: [{ src: '/assets/js/index.js', defer: true }],
meta: [{ name: 'color-scheme', content: 'light dark' }]
}
};
url is the only value not written here: it reads process.env.BASELINE_URL, set by the start script and passed in by a production build. title and tagline feed the <title> tag, defaultLanguage sets the lang attribute, and noindex keeps a staging build out of search results. The settings reference has the others.
A plain string works here too. url: 'https://www.example.com/' is an ordinary setting, and if your site only ever builds in one place it is the simpler answer. The variable earns its place when the address changes with the build: localhost while you work, a preview URL on a branch, the real domain when it ships. That one value is the origin for every canonical link, sitemap entry, hreflang tag and JSON-LD node Baseline writes, so whatever you set here shows up in all of them.
The head block is how tags reach every page. link, script and meta are arrays whose keys become the rendered tag's attributes, and they arrive alongside what Baseline emits anyway, which the head module lists in full. The two files those paths point at get written two pages from now.
Baseline compiles your CSS and JS, but it does not link them for you. A bundle that is not listed here gets built and then never loaded, which looks exactly like the stylesheet not working.
Baseline is now wired in, we can move on to content.