Table of Contents

Globals

Baseline registers a handful of global data keys and a few Nunjucks globals. Most of them are reference targets you can read in templates; the rest are reserved namespaces that keep module-namespaced data from colliding with filters.


_baseline

The plugin's runtime introspection object. Built in three additive merges as the entry point runs. The shape mirrors Eleventy's own eleventy global: identity fields (name, version) at the top level, env for environment signals, with Baseline-specific data (options, features, paths) alongside.

_baseline = {
	name: 'Eleventy Baseline',
	version, // npm package version
	env: { mode, package }, // mode = ELEVENTY_ENV; package = npm package name
	options: {
		// Snapshot of the resolved options object (state.options).
	},
	features: {
		multilang, // boolean
		sitemap, // boolean
		navigator, // boolean
		head, // always true
		assets, // always true
		hasImageTransformPlugin
	},
	paths: { input, output, includes, data, assets, public }
};

Top-level identity

Key Type Source
name string 'Eleventy Baseline'
version string npm package version

Lifted to the top level so they sit alongside _baseline.env and _baseline.features the same way Eleventy's eleventy.version sits alongside eleventy.env. If you used _baseline.env.name or _baseline.env.version previously, those moved to _baseline.name and _baseline.version.

_baseline.env

Key Type Source
mode string process.env.ELEVENTY_ENV
package string npm package name

A note on mode: it reflects ELEVENTY_ENV, not Eleventy's own ELEVENTY_RUN_MODE. The two name different signals and have caught people out before. Project structure puts them side by side, with who sets each and what each one flips.


_baseline.options

A snapshot of the resolved options object (state.options). Carries every option Baseline computed after merging your options argument with defaults, in its on-the-wire shape (so multilang, not multilingual; assets.esbuild, not assetsESBuild). Useful for templates and filters that want to behave differently based on what was configured.

If you only need the boolean "is X active?" answer, _baseline.features below is the resolved view. _baseline.options is the raw resolved input.

_baseline.features

Which modules are on. Every value is a plain boolean, which is the difference between this and _baseline.options: features answers "is it active", options carries the shape you configured.

Key Type Notes
multilang boolean See note on naming below.
sitemap boolean Mirrors options.sitemap.
navigator boolean Coerced from options.navigator, so the object form reads as true here. The object itself is on _baseline.options.navigator.
head boolean Always true. The head module has no off switch.
assets boolean Always true. Neither does the assets module.
hasImageTransformPlugin boolean Detected via eleventyConfig.hasPlugin(), against both the exported name and the declared one.

There is no features.verbose, and no features.head.titleSeparator or features.assets.esbuild. Those are option values rather than activation flags, so they live on _baseline.options (options.head is {} until you set one, with the head module applying ' – ' and false at module-init time).

A naming nit worth flagging: the user-facing option is multilingual, but the resolved state key is multilang (short form). The features object reflects state, so you read _baseline.features.multilang even though you wrote options.multilingual.

_baseline.paths

Resolved directory paths from eleventyConfig.directories. Read-only; useful for filters and shortcodes that need to know where things live on disk. These are resolved paths rather than the bare names in the config export: each is project-relative, dot-prefixed and trailing-slashed, so it concatenates straight onto a relative path.

Key Value with the default config Notes
input ./src/
output ./dist/
includes ./src/_includes/
data ./src/_data/
assets ./src/assets/ The assets virtual directory.
public ./src/static/ The public virtual directory; on-disk folder is static/. See Config export.

If you previously used _baseline.assets.input or _baseline.assets.output, those keys moved. They are now _baseline.paths.assets (a directory path) and _baseline.paths.output. The shape changed in the audit; old references will need updating.


_pageContext

A normalised per-page object built at cascade-time and exposed to every page. One sentence here, full surface on its own page: see Page context.


_snapshot

A debugging snapshot populated by the navigator module. The module always registers, so _snapshot is on every page whatever the navigator option says; that option gates the virtual page alone. Exposes:

  • _snapshot.contentMap - Eleventy's content map at the time the page renders.
  • _snapshot.pageContext - every page-context object the registry has built so far.
  • _snapshot.seoGraph - every resolved SEO handle the registry has built so far, keyed by URL. The same values the head emits from.

Read in templates that want to introspect the build. See the navigator module for the full picture; the navigator template at /navigator-core.html is the canonical consumer.

_snapshot.contentMap is null while the navigator template itself renders, because the template renders before Eleventy emits eleventy.contentMap. Reading _snapshot from any other page sees the populated value.


A Nunjucks global, registered by the navigator module. The cross-page read surface for plugin-produced data, shape { nodes, edges, backlinks }:

  • _navigator.nodes is the per-page map from the content graph, keyed by URL. Each entry carries identity fields (title, slug, description, section, type, lang, locale, translationKey, isDefaultLang, date, url, breadcrumbs) merged with extracted fields (excerpt, headings, sections, images). Identity comes from the page's _pageContext; the extracted fields come from the rendered HTML.
  • _navigator.edges is a flat array of every link in the graph. Each edge is { internal, from, to, text, rel }. One edge per anchor in each page's extracted root.
  • _navigator.backlinks is the target-keyed enriched backlinks map: { targetUrl: Array<{ url, title?, excerpt? }> }. Pre-joined with the source page's title and excerpt so consumers read enriched records directly.

Authors paginate over _navigator.backlinks to generate "what links here" subpages, or read _navigator.nodes and _navigator.edges directly for cross-page features (related-page lists, navigation indices, link audits).

The navigator is both a runtime-introspection surface and the public read surface for plugin-produced cross-page data; the per-page view of the same substrate is on _node, _backlinks, and _outgoing below.


Three computed cascade keys, populated per page from the content-graph pre-pass. _node is the current page's own graph node; _backlinks and _outgoing are the edges pointing at it and away from it. Full shapes, the membership rules, and the reserved _edges key are on Content graph.

_backlinks and _outgoing carry raw edges, not enriched records. If you want the source page's title and excerpt for a backlink, read _navigator.backlinks (target-keyed and pre-joined) instead.

Two consumers, two shapes: the per-page keys carry the most local view; the cross-page map carries the enriched, target-keyed view a backlinks-index template needs.

All three keys read through coreContext.runtime.contentGraph via getters, so rebuilds that reassign the underlying graph reference are picked up automatically.


_pagebreak

Present only on a page split by a <!--pagebreak--> marker, and undefined everywhere else, so one guard covers a whole site. Baseline emits no navigation markup of its own: it hands over the parts and the layout draws the links.

{
	number: 2,        // 1-based, the part being rendered
	total: 3,
	parts: [
		{ number: 1, label: '1',          anchor: undefined, url: '/story/',   current: false },
		{ number: 2, label: 'Data files', anchor: undefined, url: '/story/2/', current: true  },
		{ number: 3, label: 'Verify',     anchor: 'setup',   url: '/story/3/', current: false }
	],
	previous: { /* a part, or undefined on part one */ },
	next: { /* a part, or undefined on the last part */ }
}

label is the marker's label where one was written and the part number where it was not, so it is always safe to print. Part one is the exception worth knowing: no marker precedes it, so it can never carry a label and always reads '1'. A template that wants to name it supplies that name itself. anchor is the #fragment from the marker, for a template that wants to deep-link into the part rather than to its top.

{% if _pagebreak %}
	<nav aria-label="Page">
		{% for part in _pagebreak.parts %}
			{% if part.current %}
				<span aria-current="page">{{ part.label }}</span>
			{% else %}
				<a href="{{ part.url }}">{{ part.label }}</a>
			{% endif %}
		{% endfor %}
	</nav>
{% endif %}

The marker syntax, and the cases where Baseline declines to split a page, are on Content helpers.


Reserved-but-empty keys

The entry point reserves additional keys as empty objects:

  • _assets
  • _head
  • _multilang
  • _sitemap

They exist so module-namespaced data can merge cleanly without colliding with same-named filters. No module currently writes into them; if you see one of these in a _data dump, it's {} by design.

The full INTERNAL_KEYS list, and which of them carry a value today, is on Internals.


See also