EnglishNederlandsFrançais Toggle theme

Eleventy Baseline

Start building your site, skip the recurring setup work.
Table of Contents

Internals

You can run Baseline without knowing any of this. The page exists for the moments when you peek into _snapshot, watch a console log, or follow a stack trace into the plugin and want to know what each piece is called.

Reference register. Brief by design.


Registry

A registry is a per-config bag of state. Baseline keeps one root registry as a WeakMap keyed by eleventyConfig, then carves out named scopes inside it (e.g. core:page-context, core:virtual-dir). Each scope holds three things:

  • a cache (identity-keyed memoisation, used by the page-context builder),
  • a values map (named entries, used by stores),
  • a listeners set (event-listener dedup keys, so re-registering a plugin doesn't double-attach handlers).

Why a WeakMap: Eleventy can run multiple configs in the same Node process (parallel builds, tests, hot reload). Keying by the config instance keeps state isolated and lets it get collected when the config goes out of scope.

The registry source: _baseline/core/registry.js.

Stores

A store is a small wrapper over a registry scope that captures Eleventy's lifecycle events into a value the rest of Baseline can read. Two ship today:

  • content-map store - captures eleventy.contentMap and exposes it to the page-context registry (canonical URL resolution) and the navigator (_snapshot.contentMap).
  • translation-map store - populated by the multilang module; read by the head module at transform-time to emit hreflang alternates.

Both attach exactly one listener per (event, key) pair, courtesy of the registry's listener dedup. Re-registering the plugin is safe.

Virtual directories

A virtual directory is an extra key on eleventyConfig.directories that Eleventy itself does not honour. Baseline adds two: assets and public.

The mechanism: Object.defineProperty adds the key with a getter that reads from a live cache. The cache is pre-populated from eleventyConfig.dir at plugin-init time (so synchronous readers like watch globs see a valid path) and refreshed on eleventy.directories (so the final, normalised paths land before any consumer reads them post-cascade).

Why not just use eleventyConfig.dir.assets? Eleventy's ProjectDirectories.setViaConfigObject() only accepts input, output, data, includes, and layouts. Anything else is silently dropped. Synthesising the keys onto eleventyConfig.directories is the workaround.

The asymmetry between the virtual public key and the on-disk static/ folder is documented in Config export.

Reserved data keys

Baseline pre-registers eight _* keys as empty objects so module-namespaced data merges cleanly and does not collide with same-named filters. The full list (INTERNAL_KEYS):

_baseline, _assets, _head, _multilang, _navigator, _sitemap, _snapshot, _pageContext.

Of those, three are actually populated today (_baseline, _pageContext, _snapshot); the other five are reserved-but-empty. See Globals for what's populated and where.

The _internal: true opt-out is documented on Page context; it skips a template from the page-context registry.


See also

Previous: Page context

Next: Filters