Eleventy 1.x → 3.x upgrade plan #

Status: not started. This document is a pre-work assessment only — nothing
in this repo has been changed to prepare for the upgrade. It exists so the
upgrade can be picked up as a self-contained piece of work in a separate
session.

Why this isn't urgent #

The local-build slowness that prompted this investigation (/tags/* pages
pushing content-only rebuilds past 2 minutes) was fixed separately without
touching the Eleventy version — see the tagList collection gating in
.eleventy.js and tags.njk. This upgrade is a distinct piece of work with
its own risk profile; don't bundle it with build-speed fixes.

Current state (verified) #

Target #

Upgrade to @11ty/[email protected] (or whatever the latest 3.x patch is
at the time this work starts — re-check npm view @11ty/eleventy versions
first, a lot may have shipped since this was written).

This repo has a lot of custom configuration (.eleventy.js is ~350 lines,
plus 10 files under _11ty/ implementing custom transforms and a vendored
plugin under third_party/). Stepping through each major version's own
migration guide and re-testing at each stop will make it much easier to
isolate which change caused which regression, versus debugging a 1→3 jump in
one go. Treat 2.x as a checkpoint to get a green build and passing tests
before continuing to 3.x, not as a version to ship.

Breaking changes that matter for this repo #

1. Browser Sync → @11ty/eleventy-dev-server (lands in 2.0, not 3.0) #

This is the change most likely to bite. Verified by diffing the dependencies
block of each package version on npm:

So the swap happens the moment you move off 1.x, not when you get to 3.x.
Two places in this repo talk to Browser Sync directly and will silently stop
working (no crash — the config calls just become no-ops or throw depending on
version) unless rewritten against the new dev server's config surface:

Symptom if this is missed: local npm run serve either fails outright at
startup, or CSP violations appear in the browser console for the dev-only
live-reload script (this would not affect production, since
isDevelopmentMode() gates it — but it makes local dev noisy/broken).

2. Official plugin major-version bumps #

Checked via npm view <pkg> version (latest) against what's currently pinned
in package.json:
PluginPinnedLatestJump
@11ty/eleventy-plugin-rss^1.0.73.0.02 majors
@11ty/eleventy-plugin-syntaxhighlight^3.0.15.0.22 majors
@11ty/eleventy-navigation^0.1.31.0.51 major (0.x→1.x)

None of the three declare a peerDependencies entry pinning a specific
Eleventy version (checked via npm view <pkg> peerDependencies — all empty),
which is a good sign they're loosely coupled via the plugin API rather than
version-locked. Still, each is a multi-major jump with its own changelog to
read — don't assume addPlugin(pluginRss) etc. keep working unchanged.
Budget time to re-check each plugin's own breaking-change notes and smoke-test
the feed/syntax-highlighting/nav output after bumping.

3. Vendored plugin: third_party/eleventy-plugin-local-images #

Not on npm — it's committed source, so it won't auto-update, but it also
won't get any upstream fixes. It uses node-fetch@^2.6.7 (CJS-style,
pre-native-fetch) and JSDOM directly via eleventyConfig.addTransform,
neither of which is coupled to the Eleventy version. Should keep working
as-is through the upgrade, but:

4. markdown-it version — not actually a concern #

.eleventy.js calls eleventyConfig.setLibrary("md", markdownLibrary)
(line 310) with its own markdown-it instance, built from the project's own
markdown-it@^12.3.2 devDependency — not whatever version Eleventy core
bundles internally. So Eleventy 2.x/3.x bumping their internal markdown-it
(13.x, then 14.x) has no effect on this repo's markdown rendering. No
action needed here; noted only so it isn't mistaken for a risk during the
upgrade.

5. Custom transform chain — needs full regression testing regardless of cause #

Not a specific "breaking change" documented anywhere, but worth calling out:
this repo runs 7 custom transforms on every HTML page
(_11ty/apply-csp.js, _11ty/img-dim.js, _11ty/json-ld.js,
_11ty/optimize-html.js (which itself registers 3: purifyCss,
minifyHtml, optimizeAmp), _11ty/youtube-html-transform.js, and the
vendored localimages transform), several of which independently parse the
page with JSDOM. None of this is Eleventy-version-specific code, but the
transform pipeline execution order and the outputPath argument each
transform receives are both things that could theoretically shift across
major versions. After upgrading, diff a representative sample of output HTML
(a normal post, an AMP post if any exist, the home page, one tag page) byte-
for-byte against the pre-upgrade _site output, not just "does it build
without errors."

Suggested phased plan #

  1. Branch + baseline. New branch off main. Run npm run build on the
    current 1.0.2 setup and keep the resulting _site/ (or a hash of it)
    as the comparison baseline before touching anything.
  2. Step to 2.x.
  3. Step to 3.x.
  4. Bump the three official plugins (eleventy-plugin-rss,
    eleventy-plugin-syntaxhighlight, eleventy-navigation) to their latest
    majors, one at a time, re-running npm run build-ci after each so a
    regression is easy to attribute to a single package.
  5. Full regression pass:
  6. Deploy to a preview (Netlify branch deploy, or equivalent) before
    merging to main, since CI (CI=true) is where the full /tags/* set
    and all 906+ copied assets get exercised for the first time in this
    process.

Rollback #

Each step above is a separate commit, so rolling back is git revert to the
last-known-good commit (or dropping the branch entirely pre-merge). Nothing
in this plan touches production data or requires irreversible steps —
Eleventy version bumps are package.json/package-lock.json changes plus
config edits, fully reversible with git.

Effort estimate #

Medium-large — mostly concentrated in the dev-server rewrite (step 2) and the
regression-testing discipline in step 5, not in the version bumps themselves.
Rough order of magnitude: a focused day for steps 1-4, plus however long the
manual regression pass in step 5 takes to feel confident about (this is the
part most likely to reveal something this document didn't anticipate).