Organize your pages as collections
In this article, we'll cover organizing your markdown pages as collections.
What are collections?
Collections let you group related content together. For example, if you're using Poet for a documentation website, you might organize your pages into collections such as "Docs" or "API". Or if you're building a help center, you can use collections to organize your articles into different categories.
The primary use case for collections in Poet is to create navigation menus and organize the order of items inside. You can think about it as a way of putting content pages into different folders without actually needing to have any specific folder structure in your project. Instead of using folders, you can specify the name of the collection and fields like parent
and after
to define the hierarchy and order of pages within the collection.
Adding pages to collections
Adding pages to collections is optional. To do so, you need to add a [[collection]]
section to the front matter of your markdown page and specify the name
of the collection. You can also specify the parent
and after
fields to define the hierarchy and order of pages. For example:
[[collection]]
after = "documentation/introduction"
name = "documentation_pages"
parent = "documentation/index"
A single markdown page can belong to many collections. This is why Poet also has a concept of the primary_collection
field. This field is defined in the front matter outside of the [[collection]]
section, and there can be only one primary_collection
per page. This is particularly useful when you want to use the same layout file for pages that belong to different collections and render the navigation menu based on the primary_collection
.
If you don't specify the primary_collection
field, and there's only one collection defined in the [[collection]]
section, Poet will automatically use that collection as the primary one.
Poet will raise an error when building the site if you reference the primary collection somewhere (for example, in a layout) and you have multiple collections defined in the [[collection]]
section but haven't defined which collection is primary.
Practical example
Let's now see collections in action by adding more content to our project and then creating a layout that will leverage the collections to create a left-side menu, like on the screenshot below:

We'll create a new content/documentation
folder and three new pages, to have a structure like this:
my-poet-project/
├─ content/
│ ├─ documentation/
│ │ ├─ index.md <- new file
│ │ ├─ introduction.md <- new file
│ │ ├─ installation.md <- new file
│ ├─ about.md
│ ├─ index.md
├─ resources/
│ ├─ css/
│ │ ├─ layout-minimal.css
│ │ ├─ page-about.css
├─ shortcodes/
│ ├─ LayoutMinimal.rhai
│ ├─ PageAbout.rhai
index.md
The index.md
page will be responsible for rendering the "Documentation" collection title in the left-side menu. And this will be its only job in this example; the page itself won't be rendered thanks to the render = false
field in the front matter.
introduction.md
Next, we'll have the introduction.md
page that will be the first page in the "Documentation" collection. It will belong to the documentation_pages
collection, use the parent
field to specify that it should be listed under the title coming from the index.md
page, and use the after
field to specify that it should be listed directly after the index.md
page.
installation.md
Finally, we'll have the installation.md
page that will be the second page in the "Documentation" collection. It will also belong to the documentation_pages
collection, use the parent
field to make it listed under the title fromindex.md
page, and use the after
field to put it directly after the introduction.md
page.
Creating the layout
Finally, let's create the LayoutDocumentationPage
and the corresponding CSS file for the pages we just created that will render the left-side menu based on the documentation_pages
collection.
The project structure will now look like this:
my-poet-project/
├─ content/
│ ├─ documentation/
│ │ ├─ index.md
│ │ ├─ introduction.md
│ │ ├─ installation.md
│ ├─ about.md
│ ├─ index.md
├─ resources/
│ ├─ css/
│ │ ├─ layout-documentation-page.css <- new file
│ │ ├─ layout-minimal.css
│ │ ├─ page-about.css
├─ shortcodes/
│ ├─ LayoutDocumentationPage.rhai <- new file
│ ├─ LayoutMinimal.rhai
│ ├─ PageAbout.rhai
An example of the layout code can look like this:
fn render_menu(context, node, level, nested) {
component {
{switch level {
0 => component {
{node.reference.front_matter.title}
{nested}
},
_ => component {
{node.reference.front_matter.title}
}
}}
}
}
fn template(context, props, content) {
context.assets.add("resources/css/layout-documentation-page.css");
let menu_hierarchy = context.primary_collection.hierarchy;
component {
{render_hierarchy(
menu_hierarchy,
render_menu.curry(context)
)}
{context.front_matter.title}
{content}
}
}
The layout code above does two things, essentially.
The first is creating the render_menu
function that is responsible for rendering the navigation manu based on the items from the collections. It uses a switch statement to differentiate between the 0-level pages and the rest of the pages. Titles of the 0-level pages are rendered as plain text so that we can have a non-clickable title for the collection. Other pages are rendered as links.
And the second thing in this layout is, as usual, the template
function that extends the LayoutMinimal
layout and is responsible for rendering the actual page, including the left-side navigation and the main content area.
The order of the pages in the menu is determined by the after
field in the front matter of each page.
After adding some CSS, the end result can look something like this:

You can read more about collections in the Collections navigation article.