Add @collection() shortcode
I wanted a more flexible way to show lists of related posts. The old way involved adding a collection block to a page’s front matter, like this:
[collection]
include = ["essays"]
This worked, but it had big limitations: you could only have one collection, and it always appeared at the bottom of the page.
The new @collection() shortcode lets me drop collections (as many as I want) anywhere in any document, directly from the body of the document.
I also added much improved sorting and filtering options.
So, TLDR, to show the 5 most recent quotes I’ve saved that are tagged favourite:
@collection(include="quotes" limit=5 filter="tags=favourite")
Which would render as:
Rabbi Zachi Asher, Curtains of Fear, The Epichorus, Temenos, 2025
Ronald Sukenick, The Permanent Crisis, Epoch, 1960
Rakhim Davletkali, Dreaming of obsession, 2014
Byrne Hobart, Working in Public and the Economics of Free, The Diff, 2020
My first effort had a circular dependency problem: how can you generate a page that needs a list of other pages, when those other pages might not have been generated yet? The solution is necessarily two-pass, and so while sharing its syntax with the other shortcodes, it does not run until later in the build.
-
First Pass: When the site generator sees a
@collection()shortcode, it doesn’t build the list right away. Instead, it leaves a unique placeholder and makes a note of the document and the parameters that were used. -
Second Pass: After all the pages have had their main content generated, a final step loops over the documents it made a note of. It now has all the data it needs to build the collection, so it renders the list into HTML and swaps it with the placeholder.
Despite being two pass, it’s pretty efficient as it only re-visits the pages that actually need it.
Collections exclude the current page unless the include_self=True boolean is passed, such as for a series table of contents.
Collections can contain documents that themselves contain collections, even wehn rendering the whole child document (e.g. style="body"). This is achieved through iterative.
Filtering:
-
include="[tags]": Includes documents matching a comma-separated list of categories or tags.-
@collection(include="essays, wandering")
-
-
exclude="[tags]": Excludes documents from the included set. k -@collection(include="essays", exclude="personal") -
filter="[filters]": Filters documents by metadata fields. Supports . for nested fields (e.g., available.year) and checks for list membership (e.g., tags=…).-
@collection(filter="favourite=True") -
@collection(filter="creator=Silas Jelley, available.year=2024") -
@collection(include="notes", filter="tags=python")
-
Sorting & Slicing:
-
order="[order]": Sets the sort order.- reverse-chronological (default), chronological, alphabetical.
-
@collection(include="pearls", order="alphabetical")
-
limit="[int]": Limits the number of documents displayed.-
@collection(include="main", limit=5) -
offset="[int]": Skips the first N documents. -@collection(include="main", limit=5, offset=5) -
Paginate collections:
@collection(include="photos", limit=10, offset=20)shows the third page of photos if you’re showing 10 per page.
-
Display Styles:
-
style="[style]": Controls the appearance.- title (default): A simple list of linked titles and dates.
- summary: Titles, dates, and a short summary of the content.
- body: The full rendered HTML body of each document.
-
@collection(include="changelogs", style="body")
-
numbered=True: Renders a title style collection as a numbered list (<ol>).-
@collection(include="series-a", order="chronological", numbered=True)
-
-
show_date=False: Hides the date in title and summary styles.-
@collection(include="essays", show_date=False)
-
Behavior:
-
include_self=True: Includes the current document in the list if it matches the filters. The default (False) is to exclude it to prevent circular references.-
@collection(include="series-a", include_self=True)
-
This change completely removes the old front matter based collection system.