{"slug": "i-finally-understand-eleventys-data-cascade", "title": "I Finally Understand Eleventy’s Data Cascade.", "summary": "The article explains the author's understanding of Eleventy's data cascade, which is the system that aggregates data from multiple sources and determines precedence when conflicts arise. The cascade prioritizes data based on colocation, meaning data defined closer to a specific template (like frontmatter) overrides more global data. Global data, defined in the `_data/` folder or config file, is evaluated first and has the weakest precedence, making it suitable for site-wide values.", "body_md": "**This is a living document!**\n\nWhat follows is my mental model of how Eleventy aggregates data for templates. It’s subject to change as I learn more and more about Eleventy, and as Eleventy itself changes.\n\nThis post walks through the data cascade **as of the 2.0 release.** You can skip to [the changes that came with 1.0](#changes-to-the-data-cascade-in-eleventy-10), or the [pre-1.0 version of this article](/blog/eleventy-data-cascade/original/) has been archived if you need that instead!\n\n## Introduction\n\nLast summer, [I overhauled my blog](/blog/in-with-the-new/), rebuilding it from the ground up with a static site generator called [Eleventy](https://www.11ty.dev/). I had just come off the heels of taking Andy Bell’s [ Learn Eleventy From Scratch](https://learneleventyfromscratch.com/) course, and I was feeling jazzed about being able to build lightweight sites.\n\nThere was just one thing, one piece of Eleventy, that took me months to fully wrap my head around: **the data cascade.**\n\nEleventy is powered by templating. You can inject data into your contents and layouts using [various templating languages](https://www.11ty.dev/docs/languages/). For instance, say your blogpost has some `title`\n\ndata. You could use that `title`\n\nin your layouts!\n\nWhen Eleventy generates the pages of your site, it aggregates data supplied from several places and then injects that data into your contents. The process of aggregating this data from each of these different places and deciding which data should have precedence in the case of a conflict is what Eleventy calls the [data cascade](https://www.11ty.dev/docs/data-cascade/).\n\nFor several months, I didn’t feel like I had a good grip on the cascade. I had numerous questions: How would I know whether data was available to me at any given moment? Where could I use data? Which data would override which other data? Why should I place some data here, and some other data there?\n\nI had to read Eleventy’s docs about data several times, and then put it into practice on several different sites in several different ways. I’m especially grateful for the [Lunch.dev Community Calendar project](https://github.com/LunchDevCommunity/community-calendar), which has been built out over several live group sessions. You can practically see the moment the cascade clicked for me in [our session on “Add to Calendar” links with computed data](https://events.lunch.dev/add-calendar-links-to-11ty-with-computed-data/).\n\nWhat follows is my mental model of Eleventy’s data cascade, presented in the hopes that it will help you wrap your head around where you can place data in your Eleventy sites and why.\n\n## A Few Definitions\n\n- Templates are the files that define your contents. In a blog, for instance, this could be the Markdown file that contains your blogpost.\n- Layouts are templates that wrap around other templates. You could, for instance, wrap your blogpost’s template in a layout that provides the page’s HTML scaffold and its styles.\n- Data is provided to your templates (and, therefore, to your layouts as well) as variables that can be injected into your contents. Each template is supplied its own data, based on the data cascade.\n\n## Colocation\n\nWhile I was ambling along with the data cascade, able to define and use data but not totally sure why and how it worked, I built up a bit of an intuition about how it worked: **colocation**. Data that is defined closer to your content will be evaluated later in the data cascade, and will have a higher precedence.\n\nI’m happy to report that this holds up! Even if you don’t totally understand how the data cascade works, you can debug your data first by looking at a template’s frontmatter, and then working your way out.\n\n## Step 1: Global Data\n\nThe first data to be evaluated is global data. [Global data](https://www.11ty.dev/docs/data-global/) is available in every template and layout, but it has the weakest precedence—it’ll be overruled by any more-specific data that gets evaluated later. This makes it really ideal for **site-wide concerns**, as well as for data that needs to be **fetched from external sources** such as APIs.\n\nEleventy provides two ways to supply global data: global data files and [through your Eleventy config file](#step-2-config-global-data). In this *first* step of the data cascade, Eleventy looks at **global data defined through global data files.** By default, Eleventy will look for a folder at the root level of your project called ** _data/**. This is your global data folder. You can\n\n[configure your global data folder’s path](https://www.11ty.dev/docs/config/#directory-for-global-data-files)in your Eleventy configuration file if you want, but I tend not to. The default works just fine for me.\n\nEleventy will look for all `*.js`\n\nand `*.json`\n\nfiles in your global data folder, and expose their exports to your templates, using the global data file’s name as the variable name. For instance, this site has a `_data/`\n\nglobal data file that looks like this:**navigationLinks**.json\n\nEleventy takes that JSON array and exposes it for me as the\n\nvariable in every one of my templates and layouts. In one of my layouts, I iterate over that **navigationLinks**`navigationLinks`\n\nvariable to populate the page’s `<nav>`\n\n:\n\nGlobal data was a good fit for defining my navigation links because navbars tend to be a site-wide concern. Even if I do decide to have separate navbar contents on a particular page down the road, it still makes sense to define a sensible global default and override the specifics closer to that particular template.\n\nIn addition to JSON global data files, Eleventy supports JavaScript global data files, in which the whole Node.js ecosystem is your oyster. This could be useful, for instance, if you want to [fetch any data from external APIs](https://www.11ty.dev/docs/quicktips/eliminate-js/), or [expose Node.js environment variables](https://www.11ty.dev/docs/data-js/#example-exposing-environment-variables) so that your templates know whether the site is being built for production or for development.\n\nOne recent use case I had for JavaScript global data was [building a contributors page for the Lunch.dev Community Calendar](https://events.lunch.dev/eleventy-contributors-page/). The repository had an [ .all-contributorsrc](https://github.com/LunchDevCommunity/community-calendar/blob/main/.all-contributorsrc) file, generated by the\n\n[All Contributors](https://allcontributors.org/)GitHub bot, but because of the repository structure, that data was totally outside Eleventy’s data cascade.\n\nI created a file called `_data/`\n\n, and in it, I used Node.js’s **contributors**.js`fs`\n\nmodule to read and parse the `.all-contributorsrc`\n\nfile from the filesystem, and then export its contents:\n\nThen, as I was building the `/contributors`\n\nroute, I was able to iterate over that\n\nvariable:**contributors**\n\nI think this just goes to show that the whole Node.js ecosystem is fair game in JavaScript global data files.\n\n## Step 2: Config Global Data\n\nThe second type of global data, [config global data](https://www.11ty.dev/docs/data-global-custom/) (added in 1.0), allows you to inject global data into the cascade in your Eleventy config file. Like global data defined in global data files, config global data will apply to every template and layout in your project. However, config global data has a higher precedence than global data defined via global data files.\n\nTo set up config global data, go to your [Eleventy config file](https://www.11ty.dev/docs/config/#default-filenames) (which will be called `.eleventy.js`\n\nor something like `eleventy.config.js`\n\n) and call your Eleventy config’s `addGlobalData`\n\nmethod:\n\nThe first argument passed to `addGlobalData`\n\nis the data property’s name, and the second is its value.\n\nAlternatively, you can pass a function (even an async function!) in place of the value, and the data property will be set to whatever that function returns. For instance, you could get [info about a given GitHub repository](https://api.github.com/repos/11ty/eleventy):\n\nThen throughout your project, you could access your repository’s information with the `repo`\n\nproperty:\n\nYou’d use config global data for pretty much the same reasons you’d use global data files for — the only difference being you don’t have to scaffold out a global data file to get global data into your project.\n\nSo why introduce a second way to provide global data? As convenient as config global data can be, it’s not a feature that’s *really* intended for us to use directly in our config — though we totally can! Its intended purpose is to give [Eleventy plugins](https://www.11ty.dev/docs/plugins/) an avenue to inject their own data into the cascade. This opens up worlds of possibilities for plugins to, for instance, integrate content management systems or other external data into your Eleventy workflow.\n\n## Step 3: Layout Frontmatter\n\nThe next step in the data cascade is [layout frontmatter](https://www.11ty.dev/docs/layouts/#front-matter-data-in-layouts). Layout frontmatter is defined at the top of your layout file, inside a block marked with `---`\n\n:\n\n```\n\t\t---\n\t\ttitle: 'Ben Myers'\n\t\tsocialImage: '/assets/default-social-image.png'\n\t\t---\n\t\t\n\t\t<!DOCTYPE html>\n\t\t<html lang=\"en\">\n\t\t<head>\n\t\t\t<meta property=\"og:image\" content=\"{{ socialImage }}\" />\n\t\t\t<title>{{ title }}</title>\n\t\t</head>\n\t\t…\n```\n\nFrom what I can tell, layout frontmatter is best used when a page needs some information—like a path to a social image—and nine times out of ten, you plan to provide a specific value for that information in your templates. You need a fallback on the off chance that you *don’t* supply that information. It’s a fallback designed to be overridden.\n\n*Prior to 1.0, layout frontmatter came between template data files and template frontmatter.*\n\n## Step 4: Directory Data Files\n\nMany Eleventy sites use the repository’s directory structure to group similar content. For instance, I have a `blog/`\n\ndirectory for articles such as this one, and a `talks/`\n\ndirectory for presentations I’ve given.\n\nIf your site uses directories to organize your templates like this, you might find yourself wanting some data to apply to every template in your directory at once. A *super* common use case for this would be applying a default [layout](https://www.11ty.dev/docs/layouts/) to all templates in a directory, like maybe applying a `blogpost.html`\n\nlayout to every template in `blog/`\n\n. Another use case might be [formatting permalinks](https://11ty.rocks/tips/permalinks/) across the board.\n\nThis is what [directory data files](https://www.11ty.dev/docs/data-template-dir/) are for. To make a directory data file for our `blog/`\n\ndirectory, we create a new file inside `blog/`\n\nand call it one of the following names:\n\n`/blog/blog.json`\n\n`/blog/blog.11tydata.json`\n\n`/blog/blog.11tydata.js`\n\nNotice how the filename matches its directory name—this is how Eleventy knows that this JSON or JavaScript file contains directory data. (Also, [that 11tydata suffix is configurable](https://www.11ty.dev/docs/config/#change-file-suffix-for-data-files) if you like)\n\nYour directory data file should contain/export an object, such as:\n\nIt’s worth noting that directory data files apply to subdirectories, too. If those subdirectories have their own directory data files, the subdirectories’ data files overrule the parent directories’ data files, thanks to **colocation**.\n\nIn general, I use directory data files to set up **sensible defaults across content of a certain kind**—defaults that any individual template in the set can override if need be, but which generally hold up across the board.\n\n## Step 5: Template Data Files\n\nJust as you can use a data file to define data that applies across an entire directory, you can create a [template data file](https://www.11ty.dev/docs/data-template-dir/) that supplies data for an individual template. For instance, if I wanted to supply data specifically for my `/blog/`\n\ntemplate, I could create a file called:**in-with-the-new**.md\n\n`/blog/`\n\n**in-with-the-new**.json`/blog/`\n\n**in-with-the-new**.11tydata.json`/blog/`\n\n**in-with-the-new**.11tydata.js\n\nA template data file **must live in the same directory as the template** and it **must have the same name as the template**, barring the file extension.\n\nAs with directory data files, template data files must contain/export an object, whose properties define the data that should get added to the cascade.\n\nThese fields will overrule fields from global or directory data, since template data files target individual templates and are much more colocated with specific content.\n\nAt first, I was surprised to find that template data files existed, since I use [template frontmatter](#step-6-template-frontmatter) for template-specific data. Template data files seem great if you prefer to separate your content from your content’s metadata, but I personally prefer to have fewer files and more colocation.\n\nHowever, I’ve recently found a use case where I really love template data files: supplying serverless templates with data. Thanks to [Eleventy Serverless](https://www.11ty.dev/docs/plugins/serverless/), introduced in 1.0, one template can be used to generate dynamic pages at request time. When I need to work with serverless data, I find template data files (combined with [computed data discussed below](#step-7-computed-data)) easier and more flexible to use than [template frontmatter](#step-6-template-frontmatter). For more information about using template data files and computed data with Eleventy Serverless, see [my 11ties talk about building a serverless color contrast checker](/talks/11ties-contrast-checker/)!\n\n## Step 6: Template Frontmatter\n\nUp next is [template frontmatter](https://www.11ty.dev/docs/data-frontmatter/). Like layout frontmatter, template frontmatter is defined at the top of the template file, delineated with `---`\n\n:\n\n```\n---\ntitle: 'Out With The Old, In With The New'\ndate: 2020-08-16\ndescription: 'How and why I rebuilt my blog from the ground up with Eleventy.'\nsocialImage: '/assets/covers/in-with-the-new.png'\n---\n\n## Introduction\n\nThis summer…\n```\n\nYour data can’t get more specific and colocated than being declared in the same file as your content. Because of that, template frontmatter overrides global data, directory data, layout data, and data defined in template data files. This makes it a great choice for setting really content-specific data.\n\nThere’s not honestly much more one can even *say* about template frontmatter… except that it’s not the end of Eleventy’s data cascade. There’s still one more step to go.\n\n## Step 7: Computed Data\n\nRecently, [we implemented “Add to Calendar” links on the Lunch.dev Community Calendar](https://events.lunch.dev/add-calendar-links-to-11ty-with-computed-data/). These links prepopulate an event on your Google Calendar (or other calendar app) with all of its details—its title, date, and description. We wanted Eleventy to generate those links for us based on the data we’d already provided. This ended up being the perfect use case for **computed data.**\n\n[Computed data](https://www.11ty.dev/docs/data-computed/) is data injected at the very end of the cascade, based on all the data that was aggregated previously in the cascade. Because it’s evaluated at the end of the cascade, it has the highest precedence, and will overrule data defined earlier.\n\nTo define some computed data, go to *any* step of the data cascade and declare an `eleventyComputed`\n\ndata object. As Eleventy reaches any step along the data cascade, if it notices an `eleventyComputed`\n\nproperty, it sets that property aside to be evaluated at the end. `eleventyComputed`\n\ncan be a deeply nested object, and any methods inside that object will be called and their return values used as the values of the data.\n\nIn our case, we wanted every event template in our `schedule/`\n\ndirectory to generate their own “Add to Calendar” links, so we went to the `/schedule/schedule.11tydata.js`\n\n[directory data file](#step-4-directory-data-files) and created an `eleventyComputed`\n\nproperty. Inside, we declared methods like `googleCalendarLink()`\n\n, `outlookCalendarLink()`\n\n, and so forth. These methods all receive a `data`\n\nargument that receives every piece of data aggregated by the cascade so far. We were able to pull off just the properties we cared about, and generate multiple “Add to Calendar” links with the [ calendar-link](https://www.npmjs.com/package/calendar-link) npm package. In all, it looked something like this:\n\nThen, in our layouts, we were able to consume the `googleCalendarLink`\n\ndata:\n\nEven though this `eleventyComputed`\n\nproperty happens to be in a directory data file, it receives the `title`\n\n, `description`\n\n, and `date`\n\ndata that’s been declared in each event’s frontmatter.\n\n(As a sidenote, computed data can depend on *other* computed data — [Eleventy does its best to resolve that dependency tree for you!](https://www.11ty.dev/docs/data-computed/#advanced-details))\n\n## Changes to the Data Cascade in Eleventy 1.0\n\nIf you’ve leveraged the data cascade in your Eleventy projects prior to version 1.0, you might have noticed some slight changes.\n\nThe first change is purely additive: supplying [config global data via addGlobalData](#step-2-config-global-data).\n\nThe second change involves moving [layout frontmatter’s](#step-3-layout-frontmatter) place in the cascade. Prior to 1.0, layout frontmatter occupied a bizarre spot in the cascade between template data files and template frontmatter. This was a [confusing exception](https://github.com/11ty/eleventy/issues/915) to the cascade’s principle of [colocation](#colocation), but since fixing it constituted a breaking change, the fix was held off until 1.0. It now occupies a spot in the cascade between config global data and directory data, which feels like a more natural fit to me.\n\n## Takeaways\n\nEleventy provides many ways for you to inject data into the cascade, depending on how broadly or specifically you want said data to apply. Broadly speaking, the closer your data is to your content, the more likely it is to apply.\n\n**You may or may not end up using each step of the cascade!** In the sites I’ve built with Eleventy so far, I’ve predominately focused on using global data, directory data, and template frontmatter, and I’ve only needed to sprinkle in a little bit of computed data. This is mostly because the sites I’ve built haven’t really needed the other steps.\n\nThis post was written with my mental model based on the sites I’ve built so far. I’m sure I’ve missed something, or there are use cases I haven’t considered! If there’s something I’ve missed, [please feel free to reach out and let me know!](https://twitter.com/BenDMyers)", "url": "https://wpnews.pro/news/i-finally-understand-eleventys-data-cascade", "canonical_source": "https://benmyers.dev/blog/eleventy-data-cascade/", "published_at": "2021-02-21 00:00:00+00:00", "updated_at": "2026-05-23 14:18:12.250402+00:00", "lang": "en", "topics": ["developer-tools", "data"], "entities": ["Eleventy", "Andy Bell"], "alternates": {"html": "https://wpnews.pro/news/i-finally-understand-eleventys-data-cascade", "markdown": "https://wpnews.pro/news/i-finally-understand-eleventys-data-cascade.md", "text": "https://wpnews.pro/news/i-finally-understand-eleventys-data-cascade.txt", "jsonld": "https://wpnews.pro/news/i-finally-understand-eleventys-data-cascade.jsonld"}}