Choosing Where Data Lives in Eleventy: Global Files, Directory Data, or Front Matter
Eleventy's data cascade offers four practical layers for shared values. This guide compares global data, directory data, layout front matter, and page front matter, then shows a scratch project that proves the override order.
16 Sept 2026, 05:12 UTC

You have a value — a site URL, a navigation list, an API response — and several templates need it. Eleventy gives you at least four places to put that data, and they merge into a single object at render time. Pick the wrong layer and you either duplicate values across dozens of files or spend an afternoon wondering why a page ignores the setting you just changed. The decision comes down to three constraints: how many pages need the value, whether it is static or fetched, and how often individual pages must override it.
The decision and its constraints
Eleventy resolves data through a cascade. When sources conflict, the more specific source wins. From lowest to highest priority, the practical order is: global data files in _data, directory data files, layout front matter, and template front matter. (Eleventy's full cascade includes a few more steps, such as computed data, but these four cover most real projects.) Your job is to put each value at the lowest layer that still reaches every page that needs it — and no lower, or you invite accidental overrides.
Comparing the supported options
| Layer | Scope | Async support | Best for | Main risk |
|---|---|---|---|---|
Global data (_data/*.json or .js) | Every template | Yes, in .js files via exported async functions | Site-wide config, shared navigation, fetched CMS content | Async fetches run at build time and can slow or break every build |
Directory data (folder/folder.11tydata.js or .json) | All templates in that directory tree | Yes, in .11tydata.js files | Section defaults like a shared layout, tag, or permalink pattern for /blog/ | Deep nesting makes the merged result hard to trace |
| Layout front matter | Templates using that layout | No | Chrome-level defaults: body classes, shared meta values | Easy to forget it exists when debugging a page's data |
| Template front matter | One template | No (use computed data for logic) | Per-page titles, dates, one-off overrides | Duplication if the value actually belongs to a whole section |
Trade-offs that matter in practice
Global data is processed once per build. A _data/posts.js file that fetches from a headless CMS runs a single time, and every template reads the same resolved object. That is exactly what you want for shared API content — but it also means a slow endpoint slows the entire build, and a failed request fails everything. Add timeouts and consider caching responses to disk during development.
Directory data is the most underused layer. Instead of repeating layout: post.njk and tags: blog in forty front matter blocks, one blog/blog.11tydata.json file applies them to the whole folder. The cost shows up later: with nested directories each contributing a data file, the final merged object is additive, and finding which layer set a value requires checking every file up the tree.
Front matter always wins. This is a feature, not a footgun — it lets one page override a section default without restructuring anything. But if you find yourself overriding the same directory value on most pages, the default is wrong; move it.
A concrete setup to validate the priority order
You can confirm the cascade behavior in a scratch project. Assumes Eleventy 2.x or 3.x installed locally (npm install @11ty/eleventy), run from the project root with no special permissions.
Create a global default in _data/site.json:
{ "accentColor": "blue" }Create a directory override in blog/blog.11tydata.json:
{ "accentColor": "green", "layout": "post.njk" }Create blog/one.md with a front matter override:
---
accentColor: red
---
# Page one
Accent: {{ site.accentColor }} / {{ accentColor }}And blog/two.md with no front matter color:
---
---
# Page two
Accent: {{ accentColor }}Run npx @11ty/eleventy --serve and inspect the output. Expected result: one.md renders red (front matter beats directory data), while two.md renders green (directory data beats the global default). If you see blue on a blog page, the directory file's name does not match the folder name — blog.11tydata.json must sit inside and be named after blog/.
Debugging the merged object
When a value is wrong and the source is unclear, dump what the template actually receives. In a Nunjucks or Liquid template, print the suspect variable directly, or use Eleventy's log filter (available in recent versions) to write it to the terminal during the build: {{ accentColor | log }}. For deeper inspection, Eleventy's official debug plugin or a temporary console.log inside an .11tydata.js file shows the resolved value at that layer. Check layers in priority order from the top: front matter first, then layout, then directory files walking up the tree, then _data.
Limitations
Layout front matter applies to the layout's own rendering context, which trips people up when they expect it to behave like page data. Async global data has no built-in incremental caching — every full build re-fetches unless you add a cache layer yourself. And the cascade merges objects deeply in some cases but replaces arrays rather than concatenating them in others; verify array behavior (for example with tags, which has special handling) before relying on it. Treat the priority order above as the stable, documented core, and confirm edge cases against the version you run.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.