Collections: Setting Front-matter defaults with nested directories?

Hi,

Relatively new with Jekyll and have been searching all over the web for an answer to this, but have struck out.

I’m building software documentation, a manual and tutorials. I’ve structured the site so there’s one collection directory _doc at site root. Within that dir are two dirs: product-manual and tutorial-1. Looks like this:

_docs/
    product-manual/
        001-intro.md
        002-first-section.md
    tutorial-1/
        001-intro.md
        002-first-section.md

These will share almost all the same front matter, so in order to be DRY, I wanted to store that info in defaults within _config.yml. I’ve tried 30 different ways, quadruple checked my YAML indentation (I have a love/hate relationship with YAML), tried values with and without quotes. Every time I edit the config.yml I stop and restart the server. I don’t see any build errors post-restart.

I know the front matter settings work, as when I place them in the docs, I see all the styling from the theme. When I leave the docs with the double --- at the top, the pages must be processed, as the markdown content is output as unstyled HTML output—but it is converted to HTML.

Could someone take a look and see what I might be doing wrong? (Unfortunately, this isn’t in a public repo.)

# Collections
collections_dir: docs
collections:
  product-manual:
    permalink: "/:collection/:path/"
    output: "true"
  tutorial-1:
    permalink: "/:collection/:path/"
    output: "true"

# Defaults
defaults:
  - scope:
      path: ""
      type: "posts"
    values:
      layout: "single"
      author_profile: false
      read_time: true
      comments: true
      share: true
      related: true
  - scope:
      path: "docs"
      type: ""
    values:
      layout: "single"
      author_profile: false
      read_time: true
      comments: # true
      share: false
      related: false
      sidebar:
        nav: "manual"
      toc: true

Thanks so much for having a look.

Best,
~brian

1 Like

no experience with this particular use case but have you tried it like the example in the docs?

 scope:
      path: ""
      type: "my_collection" # a collection in your site, in plural form
    values:
      layout: "default"

not sure what in plural form means. But it is using type to specificy the collection. and leaveing path empty, kind of the opposite of your example but maybe one of your 30 other attempts.

@rydar — thanks so much for your response. You’re right! I’ve had it reversed as well. (And just double checked by swapping the path and type just now—No joy.)

in plural form

I too am confused by this.

have you tried doing just a minimal example with only one change to eliminate a possible problem with a larger list? like just try to change the layout?

Sorry I don’t have much experience with front matter defaults, others do though and hopefully they will chime in.

The issue is path: "docs"

Your file path for that collection is really _docs, omitting the underscore is likely the problem.
You can also leave off the path and target by type instead. Type would be the collections name, in this case docs.

If you want to see some real world examples of adding defaults for collections take a look at my example folder in one of my themes.

There I have a “Recipes” collection, who’s Markdown files are in _recipes and defaults set with the following:

collections:
  recipes:
    output: true
    permalink: /:collection/:path/

defaults:
  - scope:
      path: "_recipes"
      type: recipes
    values:
      layout: post
      comments: true
      share: true
2 Likes

@briandigital Irrespective of using Front Matter Defaults in your config file, I’d like to clarify a few things:

  • collections_dir setting should reflect the actual folder name. But, currently, Jekyll doesn’t support having the custom collections_dir starting with an underscore. (_). It’s documented in this page. Ergo, your folder should be renamed: _docs => docs
  • “Collection folders” should always start with an underscore. Ergo, _docs/product-manual/ => docs/_product-manual/ and _docs/tutorial-1/ => _docs/_tutorial-1/

Thanks so much for all your attempts, but none of these are working for me. I vastly simplified everything for troubleshooting—took away all sub folders, etc. Then I tried to recreate Michael’s recipes setup, which is fitting because I’m working from one of his themes to begin with.

Here’s the simplified setup which currently puts a page at the right URL, but does not add any front matter to it, leaving me with an unstyled page.

File structure:

site-root/
  manual/
    overlays.md

Inside overlays.md

---
title: All About Overlays
---
followed by Markdown (which is being converted to HTML properly)

config.yml

collections:
  manual:
    permalink: "/:collection/:path/"
    output: "true"

defaults:
  - scope:
      path: ""
      type: "manual"
    values:
      layout: "single"

This mimics Michael’s config file here: https://github.com/mmistakes/minimal-mistakes/blob/master/docs/_config.yml

I checked my alignment in the config file with tab stop guides (set to 2 spaces each). I restart the server after every saved edit within config.yml.

I’m viewing the file at http://localhost:4000/manual/overlays/

Other content files that have layout: single placed in the head the old fashion way do render with the single template.

An example of those other files is seen rendered correctly at http://localhost:4000/manual/004-source-modes/

Any thoughts? I mean this should be easier than this, right? :exploding_head:

FTR, I’m using jekyll 3.7.3

Thank you, @ashmaroli @mmistakes especially.

I think manual needs to be _manual for the actual folder name - you still reference it as manual in the config though.

What @rydar said, you need the underscore. Rename the manual folder in your site-root to _manual and that should do the trick.

What’s happening now is Jekyll is treating manuals/overlays.md as a page and not a collection document. So the way you’re trying to scope it with your front matter default is failing.

@rdyar @mmistakes — thank you. I’ve got one setup working…

This is the structure that’s working for me right now:

File structure:

site-root/
  _manual/
    overlays.md

Inside overlays.md

---
title: All About Overlays
---
followed by Markdown (which is being converted to HTML properly)

config.yml

collections:
  manual:
    permalink: "/:collection/:path/"
    output: "true"

defaults:
  - scope:
      path: ""
      type: "manual"
    values:
      layout: "single"

And overlays is rendering in the single template. :tada:

I couldn’t get any combo of filling in a path in defaults to work.

Now I’m going to look into what happens if I start nesting. I really want one containing directory, because I’m going to have one, long, many-page manual, and then maybe 10? multi-page tutorials. That could get unwieldy in the site root, fast.

You likely don’t need to worry about path unless you’re trying to be really specific about what gets what defaults. Usually type is enough unless you want something more granular.

path excepts glob patterns now too, which should give you the extra flexibility if you need it.

I’m trying to achieve this structure: http://localhost:4000/docs/manual/overlays/

Currently…

File structure:

site-root/
    docs/
      _manual/
        overlays.md

config.yml

collections_dir: docs
collections:
  manual:
    permalink: "/:collection/:path/"
    output: "true"

defaults:
  - scope:
      path: ""
      type: "manual"
    values:
      layout: "single"

In the _site folder, it’s not rendering _manual at all.

What values do I need in each pair in config? I’ve tried several to no avail. (I have a feeling I’m going to be writing a blog post explaining this when I’m done.)

Thanks again.

Not sure. collections_dir is fairly new and I’ve never used it. I’ve seen other threads about it so maybe try and search those out to see if related.

Can’t remember if it was on talk.jekyll.com or under issues on GitHub jekyll/jekyll.

maybe try it with out the permalink? looks like the permalink you specified is what you would get with out specifying it.

In the site folder I think you would end up with a manual folder inside docs.

@briandigital The collections_dir is just a magic directory house all collections (including the _posts directory) for cleaner structure. By default, the final URL of a processed collection-document will not be affected by the collections_dir name.

To get the final URL as http://localhost:4000/docs/manual/overlays/, the permalink should be as following:

collections_dir: docs
collections:
  manual:
    permalink: "docs/:collection/:path/"
    output: "true"

I have everything working as I want it now. Here’s a recap for anyone following, or you future folk who come in search of answers about config.yml, collections, collections_dir, and front-matter defaults in collections.

directory and file structure, from site root:

docs/
    _manual-name
        content.md
    _tutorial-name
        content.md

Collections Directories — Important take aways:

  1. Collections Directories must not have an underscore at the beginning of its name.
  2. Collections Directories will not render in the URL path unless you manually put them into the permalink keypair.
  3. Subdirectories of Collections Directories must be prefixed with an underscore (assuming they are each a collection themselves).

In config.yml

# Collections
collections_dir: docs
collections:
  manual:
    permalink: "/:collection/:path/"
    output: "true"
  tutorial:
    permalink: "/:collection/:path/"
    output: "true"

Collections Config - Important take aways:

  1. value for collections_dir must not start with an underscore (because Collections Directories cannot, and this value must match what your directory is named exactly.)
  2. collections value must not start with an underscore, despite the fact that their actual directory must be prefixed with an underscore. (This point is super confusing for some of us.)
  3. If you want the collections_dir to show in the URL, you need to manually prefix it to the permalink value. It does not need a slash before it (I think!)
    # defaults:
      - scope:
          path: ""
          type: "manual"
        values:
          layout: "single"
          author_profile: false
          read_time: true
          share: false
          related: false
          sidebar:
           nav: "manual"
          toc: true
      - scope:
          path: ""
          type: "tutorial-name"
        values:
          layout: "single"
          author_profile: false
          read_time: true
          share: false
          related: false
          sidebar:
           nav: "manual"
          toc: true

Front-matter Defaults Important Take aways

  1. Stay away from path unless you need to be specific. I had a lot of trouble trying to get it to do anything useful.
  2. You need a - scope: entry for each collection within the collections_dir. It must not have an underscore at the beginning (despite the fact the actual collection requiring an underscore as the first character of the directory name)

I tried to make one defaults entry that covered all collections within the collections_dir, because mine all happen to have the same front-matter requirements. I thought I could do this by using a glob with the path: like path: docs/* but that doesn’t work.

Happy to receive clarifications or corrections to this. I think some of this should find its way back into the official docs, but I’m too newbie with Jekyll to feel comfortable with that. However, if someone else is comfortable with that, I’m happy to review or contribute to the effort. Just reach out. Thanks again to anyone who wrote in and offered assistance.

5 Likes

nice work, thanks for the recap, that is very helpful.

can i link this anwser for my blog?