Eleventy: Assign layout to multiple documents by targetting paths/collections

Created on 2 Feb 2018  路  7Comments  路  Source: 11ty/eleventy

With a lot of similar content (e.g. blog posts), it would be nice to assign a layout to them at one swoop.

Let鈥檚 say I have a bunch of documents in src/posts. Then, I would like to somehow target these documents via their common path (could be relative to dir.input, e.g. posts).

An obvious approach would be introducing a new configuration option.

Additionally, would a zero-configuration scenario somehow work? For the documents in src/posts, Eleventy could guess that the default layout for posts is required. If there is one (maybe in _includes/layouts/posts.html), use it; otherwise, continue as usual.

enhancement

Most helpful comment

With this, how does one apply a layout globally? For example, I have a test.html inside dir.input with no front matter. How can I apply _includes/layouts/default.njk to all templates by default?

Preferably, I wouldn鈥檛 need adding any front matter to my content files. Ideally, I would have a directory with dumb content files (e.g. markdown, html) that are processed as templates without having any additional meta data themselves. That would be wonderful.

All 7 comments

I like it!

Lemme let that zero-config idea marinade for a bit. Those things can cascade in weird ways if you add too many of them. Just want to make sure we wouldn鈥檛 see side effects there. One negative to the zero-config option is that I鈥檓 trying to encourage people to use file extensions in the layout key to be more explicit about which layout to use. If you use a posts layout value, it can be ambiguous as to which of the following would be chosen, if multiple template types exist: posts.liquid, posts.njk, posts.html, for example. (We search to find a matching template in order of the templateFormats extensions). So zero-config would be a continuation of that pseudo-anti-pattern.

To me the config API method seems the most straightforward and obvious:

eleventyConfig.addDefaultLayout('myglob/**/*.md', 'layouts/default.liquid');

Another idea I鈥檝e been considering which might be of wider use (and overlap here) is a config option to add default data (which could also add an optional glob option):

// apply to all templates
eleventyConfig.addData({ layout: "posts.njk", mykey: "myvalue" });
// apply to only these globbed templates
eleventyConfig.addData('myglob/**/*.md', { layout: "posts.njk", mykey: "myvalue" });

This might be a little bit more useful, broadly speaking.

Lemme let that zero-config idea marinade for a bit. Those things can cascade in weird ways if you add too many of them. Just want to make sure we wouldn鈥檛 see side effects there.

Absolutely. This is a non-trivial consideration. If executed badly, it鈥檒l create more problems than benefits in the long run.

A few observations (regarding your first reply):

  • The config API is straightforward (what a weirdly long English word) indeed. So far, I don鈥檛 see any big problems with this.
  • Deducting the layout auto-magically is tricky. As you mentioned, the directory does not include information about the templating engine; hence, it cannot be deducted easily. Then again, the configuration already has a default templating engine it looks for first, before searching for potential matches, right? Currently, without any configuration, Eleventy would be able to deduct that it鈥檚 looking for a _layout for posts documents_ with the _default templating engine Liquid_. Does that sound correct?
  • Naming. For a directory of documents (e.g. posts), one would typically use the plural form, but for the layout file, one would choose post.ext. This is not a big issue, one will just have to choose: a layout file posts.ext or a documents directory post. The other will match, but one will _seem_ incorrect.

Considering this, can a document override the templating engine via front matter? If so, one would still be able to mix templating engines as they please with the added benefit that now, they could make use of the default and/or configured settings.

Applying data scoped by path:

That sounds very interesting. It sounds like a good idea to keep it abstract as in _you can configure things for a certain scope, but you choose what it is_.

(Edit: If all that works out, it would enable Eleventy to create a feature-rich static site from documents that don鈥檛 include any extra data [i.e. front matter]. It would be really nice to have a set of completely independent documents without being tightly locked into a particular static site generator.)

https://github.com/11ty/eleventy/blob/master/docs/data.md#template-and-directory-specific-data-files

Coming in 0.2.14!

With this, how does one apply a layout globally? For example, I have a test.html inside dir.input with no front matter. How can I apply _includes/layouts/default.njk to all templates by default?

Preferably, I wouldn鈥檛 need adding any front matter to my content files. Ideally, I would have a directory with dumb content files (e.g. markdown, html) that are processed as templates without having any additional meta data themselves. That would be wonderful.

I second @kleinfreund. I still haven't figured out to set a default layout at top level, for all templates.

This doesn't work for me in a minimal setup:

// .eleventy.js
{
  input: "src/site",
  output: "build"
}

Tree:

  /site
    index.hbs
    site.json
    /_includes
      /layouts
        main.hbs

site.json:

{
  "layout": "layouts/main.hbs"
}

index.hbs:

Some stuff

layouts/main.hbs

Content:

{{{ content }}}

Let me know if I should open an issue on this, since it differs from the behaviour (from what I can read) described in https://www.11ty.io/docs/data-template-dir/#apply-a-default-layout-to-multiple-templates.

cc @zachleat

I like @zachleat's eleventyConfig.addData() idea above. This could solve the default layout problem I've been facing as well (end up creating many .json files in root that do nothing more than define a layout).

I like @kleinfreund's idea above, too. It reminds me of how harp.js handles JSON data. A global root-level harp.json file worked well for defaults and other globals, while local _data.json files worked great for overriding and additional data. Specific files can be targeted by keying its basename in the JSON.

The main problem seems to be more specific to root-level templates; the directory/template specific data works well (i.e. posts/posts.json), but it currently doesn't apply to root-level templates.

A simple _data.json (or _data/_data.json) would be nice, which would basically do the same as the eleventyConfig.addData() idea above. Be nice if I could do either.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jamrelian picture jamrelian  路  3Comments

zellwk picture zellwk  路  3Comments

AjitZero picture AjitZero  路  3Comments

aaronstezycki picture aaronstezycki  路  3Comments

veleek picture veleek  路  3Comments