Sheet 11 Revision 1.7.1
Content
Content authoring patterns and frontmatter conventions.
On this page
Frontmatter Schema
Every content file starts with YAML frontmatter:
---
layout: layouts/page.njk # Required
title: Page Title # Required
description: Meta desc # Recommended
date: 2026-01-08 # Recommended
draft: false # Optional
tags: [tag1, tag2] # Optional
image: /path/to/og.jpg # Optional
---
Layout Options
| Layout | Use Case |
|---|---|
layouts/base.njk |
Raw HTML shell, rarely used directly |
layouts/page.njk |
Standard content pages |
layouts/docs.njk |
Documentation with sidebar TOC |
layouts/post.njk |
Blog posts (if using blog) |
Facts Not Yet Known
When a site is built before every fact is in hand (a role, a year, a contact email), the gap is marked in the data, never guessed. Keep the facts in one JavaScript data file and mark each gap with blank():
// src/_data/person.js
const blank = (hint) => ({ kind: "blank", hint });
export default {
name: "Danny Caruso",
contact: blank("public email"),
credits: [{ show: "Bury the Dead", role: blank("role"), year: 2021 }],
};
Render every fact through one macro, so a gap shows as a marked gap:
{# src/_includes/macros/fact.njk #}
{% macro fact(value) -%}
{%- if value.kind == "blank" -%}<span class="blank">{{ value.hint }}</span>{%- else -%}{{ value }}{%- endif -%}
{%- endmacro %}
{% from "macros/fact.njk" import fact %}
<p>{{ fact(person.contact) }}</p>
Style .blank as a dashed tag with ::after { content: " to come"; }. The macro escapes facts like any other output, and filling a gap is a one-line change to the data file.
Markdown Content
Markdown files are processed with Nunjucks, so you can use template features:
# {{ title }}
Published on {{ date | readableDate }}
## Section Heading
Regular markdown content here.
{% include "partials/cta.njk" %}
Collections
Define collections in eleventy.config.js:
eleventyConfig.addCollection("posts", function (collectionApi) {
return collectionApi
.getFilteredByGlob("src/content/posts/**/*.md")
.filter((item) => !item.data.draft)
.sort((a, b) => b.date - a.date);
});
Data Cascade
Eleventy merges data from multiple sources (highest priority first):
- Frontmatter in the template
- Template-specific data file (
page.11tydata.js) - Directory data file (
posts.json) - Global data files (
_data/*.json)