Configuring "Front Matter": A Developer's Reference

Datum

This page documents every front matter key Sculpin – PHP Static Site Generator itself recognises and acts on – what each one defaults to, what reads it, and what happens if you leave it out.

Front matter is the YAML block at the top of a source file, delimited by ---. Everything in it is parsed and exposed as page.KEY to templates; nested structures are reachable with dot notation (page.something.here).

A source without front matter still builds, but loses the computed <title> tag and any key-driven behaviour below.

This reference covers the Sculpin 3.x series, cross-checked against sculpin/sculpin at commit bff3efa.

How the Block Gets Parsed

Sculpin splits a source on the first 2 --- lines and hands the middle section to a YAML parser; everything after the second --- becomes the page’s content. Two details are easy to miss:

  • A date value that isn’t already numeric is run through PHP’s strtotime(), so date: March 15, 2024 and date: 2024-03-15 both work.
  • Malformed YAML in the front matter block doesn’t fail the build. Sculpin catches the parse error, logs it to the console, and treats the whole file as plain content instead.

Source in code: FileSource::init(). Docs: Sources.

Content and Presentation Keys

title
Free text. Feeds the :title and :slug_title permalink tags (see Configuring sculpin_kernel.yml) and, per Sculpin’s own advice, is what keeps your page’s <title> element from being empty. No key means no default is generated for you.
slug
A manual override for the auto-slugified title. Read directly by the permalink factory; if you don’t set it, permalink tags fall back to a slugified title or, failing that, the filename.
date
Sets the source’s publish date. If omitted, Sculpin tries to read one out of the file’s path instead (next section).
permalink
Overrides the content type’s or the kernel’s default permalink pattern for this one source only.
layout
Names the template that wraps this source’s content, using Twig’s extends / block mechanism rather than simple string injection – see Layouts for how that inheritance actually works.
---
layout: default
title: Hello World
slug: custom-slug-here
---

Source in code: title and slug are both read in SourcePermalinkFactory::generatePermalinkPathname(), permalink in getPermaLinkTemplate().

Dates Without a date Key

If a source has no explicit date, Sculpin looks for a date-shaped pattern anywhere in its relative path – YYYY-MM-DD or YYYY/MM/DD, optionally followed by digits it will try to read as a time – and uses the first match it finds. The result is stored as calculated_date, and copied into date only if date wasn’t already set.

This is why a post filed under _posts/2024-03-15-hello-world.md doesn’t need a date key at all, and why a stray four-digit number elsewhere in a folder name can occasionally be misread as one.

Source in code: CalculatedDateFromFilenameMap::process().

The draft key

draft
Marks a source unpublished. Whether it’s actually skipped depends on the owning content type’s publish_drafts setting (default: false in the prod environment, true everywhere else).

When a draft is suppressed, it’s flagged to be skipped by the rest of the build entirely, not just hidden from listings.

When a draft is allowed through, Sculpin quietly adds drafts to its tags array (creating the array if none exists), which makes „show me only drafts“ a one-line tags filter in a template rather than a separate mechanism.

Source in code: DraftsFilter::match(), DraftsMap::process().

The tags and categories keys

The two taxonomies enabled by default for the built-in posts type. Both are plain arrays; a content type can define entirely different taxonomy names in its own sculpin_kernel.yml configuration (covered in Configuring sculpin_kernel.yml).

---
tags: [howto, php]
categories: [tutorials]
---

Keys That Talk to Templates: use, generator, pagination

These 3 don’t describe the source itself so much as tell Sculpin what role the source plays in generating other pages. They mostly appear in view templates, not in ordinary content sources.

use
An array of registered data provider names. Every name listed gets its full collection loaded into data.<name> for that template – for example, use: [posts] makes every post available as data.posts for a listing page to loop over.
generator
Names one or more registered generators that should act on this source, turning a single template into a factory for many generated pages. An unrecognised name fails loudly with an exception naming the offending file, rather than silently producing nothing.
pagination
Configuration read only by the pagination generator, so it has no effect unless generator: pagination is also set. 2 sub-keys: provider (default data.posts; write data.<name> for a data provider or page.<key> for another array on the same source) and max_per_page (defaults to the project-wide sculpin_pagination.max_per_page, itself defaulting to 10).
---
generator: pagination
pagination:
  provider: data.posts
  max_per_page: 5
use:
  - posts
---

Each page the pagination generator produces gets its own computed values: pagination.items, pagination.page, pagination.total_pages, pagination.total_items, pagination.previous_page and pagination.next_page. Pages beyond the first also get an automatically rewritten permalink, typically ending in /page/2.html, /page/3.html and so on – none of this is something you set, only something you read back.

Source in code: use in FormatterManager::buildBaseFormatContext(), generator in GeneratorManager::generate(), pagination in PaginationGenerator::generate(). Docs: Custom Types.

Computed, Not Set

A handful of page.* values you’ll see in templates are never front matter – Sculpin fills them in itself, and setting them yourself has no effect:

Value What it holds
page.url The final generated URL for this source
page.blocks.content The source’s rendered body, for a layout to place
page.calculated_date The date Sculpin derived, whether or not you set date
page.next_<type> / page.previous_<type> Neighbouring items in a content type’s collection
page.pagination.* Per-page pagination state, described above

Any Other Key You Like

Front matter isn’t limited to the keys above. Anything else you add is stored as-is and reachable as page.yourKey, including nested structures reached with dot notation:

---
something:
    here:
        very: deep
---

{{ page.something.here.very }} renders deep. Source: Sources.

Where to look in the source

Topic Class / file Lines
Front matter parsing itself FileSource 54-123
title / slug / permalink SourcePermalinkFactory 70-182
Date from filename CalculatedDateFromFilenameMap 20-39
draft DraftsFilter, DraftsMap 27-42, 20-43
use FormatterManager 82-86
generator GeneratorManager 65-86
pagination PaginationGenerator 58-157

Sources

  1. Sources – sculpin.io
  2. Layouts – sculpin.io
  3. Content Types: Custom Types – sculpin.io
  4. Content Types: Posts – sculpin.io
  5. sculpin/sculpin source code (commit bff3efa) – sculpin, GitHub

License

This document is © Robert Wetzlmayr and licensed under Creative Commons Attribution-ShareAlike 4.0 International. Reuse, adaptation and redistribution are welcome, including commercially, as long as attribution is given and any adapted version carries the same license. Sculpin itself remains under its own MIT license; this notice covers the text and structure of this page only, not the software it describes.

Fork me!


Kategorien Sculpin