---
title: 'Debugging with Navigator'
description: 'Use Baseline debug filters and the navigator to inspect Eleventy data, render context, and the page-context snapshot without shipping debug tools to production.'
slug: 'debugging-navigator'
type: 'article'
date: 2026-01-26T00:00:00.000Z
lang: 'en'
url: 'https://www.eleventy-baseline.dev/docs/feature-guide/debugging-navigator/'
---

When something looks off in a build, Baseline's debug helpers let you see the data Eleventy is working with from inside any template. By the end of this chapter you'll know which helper to reach for, when, and how to keep them out of production.

The cost of leaving them in dev is essentially nothing; the cost of shipping them is real.

The navigator is Baseline's built-in inspection surface. It comes in three flavours:

- The debug filters (`_inspect`, `_json`, `_keys`). Always available.
- The runtime helpers (`_runtime()`, `_ctx()`). Always available, and they return live snapshots.
- The navigator template. A virtual page Baseline can register at `/navigator-core.html`. On in dev by default, off in production.

{% alertBlock %}

A snapshot, in this context, is a structured dump of state at the moment it's read.

{% endalertBlock %}

---

## What you will build

- A debug page that prints selected data through Baseline's filters.
- An inline section using `_runtime()`, `_ctx()`, and `_snapshot`.
- Optionally, the navigator template enabled for a one-page view of the cascade.

---

## Prerequisites

- Baseline installed and loaded, as in previous tutorials.
- A sample page already exists (e.g. from the simple site tutorial).
- `package.json` with `"type": "module"` and the `dev`/`build` scripts:
  ```json
  {
  	"name": "simple-baseline-site",
  	"type": "module",
  	"scripts": {
  		"start": "rimraf dist/ && npx @11ty/eleventy --serve",
  		"build": "rimraf dist/ && cross-env ELEVENTY_ENV=production npx @11ty/eleventy"
  	}
  }
  ```

---

## 1) Enable (or skip) the navigator template

The navigator template is on by default in development and off in production. If that suits you, skip to step 2; no configuration needed.

To control it explicitly, the `navigator` option takes either a boolean or an object:

```js
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, {
			navigator: {
				template: true,
				inspectorDepth: 2
			}
		})
	);
}

export const config = baselineConfig;
```

`inspectorDepth` is the default depth `_inspect` uses, set to 2. Per-call overrides take precedence: {% raw %}`{{ page | _inspect({ depth: 4 }) }}`{% endraw %} uses depth 4 regardless of the global default.

---

## 2) Add a debug page

Create `src/content/pages/debug-playground.md`:

{% raw %}

```md
---
title: 'Debug Playground'
description: 'Inspect data with Baseline debug helpers.'
slug: 'debug-playground'
layout: 'layouts/base.njk'
---

## Collections (first 3)

<pre>
{% for item in collections.all.slice(0, 3) %}
- {{ item.url }}
{% endfor %}
</pre>

## Page keys

<pre>{{ _pageContext | _keys }}</pre>

## Page data (inspect)

<pre>{{ _pageContext | _inspect({ getters: true, depth: 2 }) }}</pre>

## Page data (json)

<pre>{{ _pageContext | _json(2) }}</pre>
```

{% endraw %}

---

## 3) Use the runtime and context helpers inline

Both helpers return live state at render time:

- `_runtime()` returns `{ env, ctx, globals }`: environment data, the current render context, and registered globals.
- `_ctx()` returns just the current render context (the same `ctx` you'd find inside `_runtime()`).

{% raw %}

```nunjucks
<h2>Runtime (env + ctx + globals)</h2>
<pre>{{ _runtime() | _inspect() }}</pre>

<h2>Render context only</h2>
<pre>{{ _ctx() | _inspect({ depth: 2 }) }}</pre>
```

{% endraw %}

These dumps can be large. Use them locally; remove or guard them before shipping.

---

## 4) Read the `_snapshot` global

`_snapshot` is a computed global with the shape `{ contentMap, pageContext }`. The content map is the per-build inventory of pages; `pageContext` is the full normalised map of all your content and modules read from internally.

{% raw %}

```nunjucks
<h2>Content map</h2>
<pre>{{ _snapshot.contentMap | _json(2) }}</pre>

<h2>Page context</h2>
<pre>{{ _snapshot.pageContext | _json(2) }}</pre>
```

{% endraw %}

One quirk worth knowing: `_snapshot.contentMap` is null on the navigator template itself, because the content-map event hasn't fired yet at that point in the lifecycle. Read it from any ordinary page instead.

---

## 5) Run and inspect

```bash
npm start
```

Open `/debug-playground/` to see the filters and global outputs.

---

## 6) Visit the navigator template (optional)

With `navigator.template: true`, Baseline registers a virtual page at `/navigator-core.html`. It renders the same kind of snapshot as `_runtime()`, but as its own page rather than embedded in one of yours. Keep it disabled in production.

---

## 7) Production considerations

- Set `navigator: false` for production builds.
- `_runtime()` and `_ctx()` expose the full render context, including data-layer values you don't want public. Remove them from any template you ship.
- `_inspect` and `_json` are safe to leave registered, but watch what you pipe into them on a production page.

---

## Next steps

- Mark debug pages with `draft: true` so they stay out of production automatically. The [[sitemaps-and-drafts | sitemaps and drafts tutorial]] covers the rest of the draft story.
- Narrow your inspection by slicing collections or selecting specific data keys before piping them into a filter. Bigger dumps aren't always more useful.
- The [[navigator | navigator module reference]] has the full option shape; the [[globals | globals reference]] covers `_snapshot` and `_baseline.features`; the [[filters | filters reference]] lists the debug filters.
