Table of Contents
Page 5 of 6

Eleventy Base Blog

Swap the head, then put your stylesheet back

In base.njk, replace the entire hand-written <head> with:

<baseline-head></baseline-head>

No wrapping <head>. The placeholder is the head, and Baseline emits the opening and closing tags itself.

Your site will render completely unstyled at this point. The <link> to your stylesheet was inside the head you just deleted, and you cannot put one inside <baseline-head>. It comes back through settings, which is what settings.head.link in the settings file is for. Alarming, expected, and the single most disorienting moment in this conversion.

Drop the <heading-anchors> wrapper too, and the @zachleat/heading-anchors dependency with it. Baseline's auto heading IDs cover the ID generation; the visible anchor links are the actual trade. Worth doing deliberately rather than leaving: the element's script was inlined in the old head, so swapping in <baseline-head> leaves an inert custom element wrapping your content, markup that looks functional and does nothing.

Then make settings.js the only place the site states its identity. base.njk moves from metadata.language and metadata.title to settings.defaultLocale and settings.title, and the instruction list comes out of home.njk.

Verify this one in the output rather than by exit code. The homepage should now emit charset, viewport, a composed <title>, description, robots, canonical, Open Graph, a Twitter card, and a JSON-LD @graph carrying WebSite, Organization and WebPage nodes. The head module lists the full set.

Finish the config

Three registrations, straight onto the end of the file. Each one fails silently if you skip it.

eleventyConfig.addPassthroughCopy({
	'./src/content/feed/pretty-atom-feed.xsl': '/feed/pretty-atom-feed.xsl'
});

eleventyConfig.addPlugin(feedPlugin, {
	type: 'atom',
	outputPath: '/feed/feed.xml',
	stylesheet: 'pretty-atom-feed.xsl',
	templateData: {
		eleventyNavigation: { key: 'Feed', order: 4 }
	},
	collection: {
		name: 'posts',
		limit: 10
	},
	metadata: {
		language: settings.defaultLocale,
		title: settings.title,
		subtitle: settings.tagline,
		base: settings.url,
		author: settings.author
	}
});

eleventyConfig.addPlugin(pluginSyntaxHighlight, {
	preAttributes: { tabindex: 0 }
});

// Image optimization: https://www.11ty.dev/docs/plugins/image/#eleventy-transform
eleventyConfig.addPlugin(eleventyImageTransformPlugin, {
	formats: ['avif', 'webp', 'auto'],
	failOnError: false,
	htmlOptions: {
		imgAttributes: {
			loading: 'lazy',
			decoding: 'async'
		}
	},
	sharpOptions: {
		animated: true
	}
});

With the three imports at the top:

import { feedPlugin } from '@11ty/eleventy-plugin-rss';
import pluginSyntaxHighlight from '@11ty/eleventy-plugin-syntaxhighlight';
import { eleventyImageTransformPlugin } from '@11ty/eleventy-img';

Two things in there are not just a paste-back. The XSL passthrough points at the file's new home under src/content/feed/, and the feed's metadata block reads settings rather than the hardcoded values it shipped with. Those values were a third source of truth for site identity, and they would put example.com URLs in a live feed.

The image transform is supported alongside Baseline's image shortcode rather than replaced by it, so no image references in your content need touching. Skip it and nothing emits images out of src/content/ at all: the <img> tags point at files that were never built.

That is the config finished, at 84 lines against the original's 168, and nine registrations against sixteen.

Two things the deletions left behind are still outstanding, and so is the content. Both build cleanly, which is why they are last rather than forgotten.