eleventy icon indicating copy to clipboard operation
eleventy copied to clipboard

Add support for directory-based collections

Open j-f1 opened this issue 3 years ago • 4 comments

Is your feature request related to a problem? Please describe. I have a bunch of pages categorized by year and season on my website. I then want to display all the files for a given season together on a single index page for each season.

Describe the solution you'd like I would like a collection to be automatically created for each folder and subfolder in the input folder, and to have some sort of global data value listing all of those collections.

Maybe something like collections["folder:scripts"], collections["folder:scripts/2020-2021"], and collections["folder:scripts/2020-2021/fall"], plus a global folders that has a structure like this?

{
  scripts: {
    "2020-2021": {
      "fall": {}
    }
  }
}

…but I’m not super happy with that approach and I’m sure someone else can come up with a better one.

Describe alternatives you've considered

  • Manually adding tags to every page is annoying and repetitive, as there are a few hundred pages.
  • There are also a large number of folders, so adding a directory data file that specifies tags would similarly be quite repetitive.
  • My current approach queries the file system to enumerate all the collections I want to make, and then calls addCollection in a loop to create each one.
    • This approach requires restarting the dev server when creating a new folder, since Eleventy does not re-run the config file when reloading.
    • This approach also requires collecting information that Eleventy presumably already has.

j-f1 avatar May 12 '22 13:05 j-f1

I think this functionality would be great! I also have a scenario that would greatly benefit from this:

I am using Jérôme Coupé's way of translating content, this means that I am using permalink to write my websites in directories for each language respectively. So my websites are all in /en/, /de/, etc. In this project, I also had faq's that where language specific, meaning that some faq's where only visible in one language but not in the other. My initial idea was, to work with this structure:

en/
- faq/
- - A.md
- - B.md
- - C.md
- - faq.11tydata.js
- index.html
- en.11tydata.js
de/
- faq/
- - A.md
- - B.md
- - C.md
- - faq.11tydata.js
- index.html
- de.11tydata.js

But I realised that all of these pieces of content needed to be their own collection in order for me to access it as such. If they shared the tag faq, I instead needed to find a way to filter them. Which created another complication, because populating tags with eleventComputed is not possible.

The information about what faq's belong to where sits in eleventyComputed data, or in the directory structure. I found solutions to this issue thanks to @j-f1 's help in the 11ty Discord, but it would have been very intuitive, if we had something like local collections, based on folder structures.

nachtfunke avatar May 12 '22 15:05 nachtfunke

I imagine this might be difficult to do in a way that works for everybody's specific file/directory structure. I did make a rough attempt at an auto-collection creator, but it doesn't do as deeply nested as your example: https://github.com/pdehaan/11ty-glob-coll

But given a directory structure like:

src
├── blog/
│   ├── 2020/
│   │   └── one.md
│   ├── 2021/
│   │   ├── four.md
│   │   └── two.md
│   ├── 2022/
│   │   └── three.md
│   └── tips/
│       └── addplugin.md
└── index.liquid

It will try and make collections named "blog_2020", "blog_2021", "blog_2022", and "blog_tips" directories and create custom collections based on a rough "./src/blog/*/*.md" style glob. I don't have a huge number of directories so it would have probably been easier/cleaner to just add directory data files like "src/blog/2020/2020.json" (with a tags entry) and let Eleventy manage my collections, but might be trickier given a larger number of folders.

Not sure of an easy way to use eleventyComputed to dynamically set the tag name, and then potentially have some other script that creates custom collections based on those dynamically set tags (since dynamically set tags don't automatically create collections).

The repo also has a pagination file which will create www/blog/2020/index.html files with a listing of all the posts in that collection. You can find the custom plugin at auto_collection_plugin.js and the config in the .eleventy.js file.

pdehaan avatar May 16 '22 00:05 pdehaan

@nachtfunke I usually work with folder based collections for this king of setup using getFilteredByGlob instead of tags. With your FAQ use case, that would give you access to one FAQ collection per language that could contain different FAQ items. That being said, it does not solve the problem of collections based on deeply nested folder structure.

jeromecoupe avatar Sep 06 '22 20:09 jeromecoupe

@j-f1 Not sure if that would fit your exact use case, but I think my current take on this would probably be to build a scripts collection containing every script using getFilteredByGlob. I would then create custom filters (getScriptsByYear, getScriptsBySeason) that would filter that collection based on certain parameters (keys) available in the front-matter, like season or year, or both. That means you would have to move season and years in the front matter of those files, though.

EDIT: coming to think of it, maybe you could use the inputPath to filter things out to rely on your folder structure rather than on front-matter values.

If you would like to paginate those filtered collection items, then you need another approach, which involves creating chunked collections. Here is a (somewhat old) repo using that approach.

jeromecoupe avatar Sep 06 '22 20:09 jeromecoupe

I did make a rough attempt at an auto-collection creator, but it doesn't do as deeply nested as your example: https://github.com/pdehaan/11ty-glob-coll

Thank you @pdehaan 👏
This should be in the docs—too useful!

ed-ponce avatar Mar 21 '23 01:03 ed-ponce

Automatically creating collections based on folders is a feature of Pack11ty, my Eleventy starter: https://pack11ty.dev/documentation/collections/#auto-collections

I've been moving most features of Pack11ty into a plugin a few days ago, so that it can be added to any existing site: https://github.com/nhoizey/eleventy-plugin-pack11ty/

(Documentation is not yet fully up-to-date.)

If you have a collections/ sub-folder in your source folder, each of its sub-folders becomes a collection. For example, there will be a news collection with all content from collections/news/**/*.

There are also automated collections for archives like yearsWithNews, newsByYear, newsByMonth.

nhoizey avatar Mar 21 '23 16:03 nhoizey