The hidden grammar of almost every config file, blog post, API response, and developer tool on the web — explained from scratch, with zero assumed knowledge.
---) that tools use to understand and process the file. Everything inside is written as key-value pairs — a label, a colon, a value — which is how structured data is stored throughout computing. Every value has a data type: text (string), a number, true/false (boolean), a list (array), a nested group (object), or a date. Front matter can be written in three formats — YAML (most readable), TOML (explicit types), or JSON (most machine-friendly). This one pattern shows up in Markdown files, static site generators, CMS platforms, config files, API responses, and environment variables — learn it once and you'll recognise it everywhere.
Before we define anything, let's establish why this is worth your attention.
When you fill in a form on a website — your name, your email address, whether you want to receive newsletters — you are entering key-value pairs. The form label is the key. What you type is the value. The form as a whole is a structured object. Every time you hit "Submit", that data gets sent to a server as key-value pairs.
When a weather app shows you "Temperature: 22°C", that's a key-value pair. When a music streaming service remembers "Last played: Bowie, Changes", that's a key-value pair. When a blog platform knows when a post was written and who wrote it — key-value pairs, all of it.
Key-value pairs are how computers store and communicate almost all structured information. The front matter in a Markdown file is just the most visible and approachable version of a pattern that runs through the entire technology stack.
By the end, you'll be able to read and write front matter correctly, recognise key-value pairs in any context (YAML, JSON, config files, API responses), understand why types matter, and know which format to reach for in different situations. This vocabulary will follow you through every technical tool you ever use.
A key-value pair is a labelled container. The key is the label on the outside; the value is what's inside. A collection of key-value pairs is a filing cabinet — every drawer labelled, every item findable. The format (YAML, TOML, JSON) is just different styles of drawer labels.
Front matter is a special section placed at the very beginning of a file — before any content — fenced off with three dashes on each side. It's not shown to readers. It's instructions for the machine.
A book's cover page, copyright page, and table of contents aren't the story. They're metadata — information about the book that helps readers, libraries, and bookshops understand and categorise it before they open to chapter one.
Front matter is the same idea. It's the digital equivalent of that cover apparatus: structured information about the file that tools (not readers) consume. The reader only ever sees what comes after.
Here's the structure, laid bare:
--- ← opening fence (three dashes) title: "My Post Title" date: 2026-03-19 published: true --- ← closing fence (three dashes) # The article starts here Everything below the closing --- is the real content. This is what readers see. The front matter above is invisible.
Different tools use front matter differently — but they all read the same fields. A static site generator reads title to populate the page title tag. It reads date to sort posts chronologically. It reads published: false to exclude draft posts from the live site. None of this requires you to write custom code — you just add the right key-value pairs.
Every line inside front matter follows the same pattern. Understanding this pattern is the unlock — everything else follows from it.
author: "Maria Santos" ↑ ↑ ↑ key colon value (space required)
Think about a hotel check-in form. It has printed labels on the left — Guest Name:, Arrival Date:, Number of Nights:, Smoking Room: — and spaces on the right for you to fill in. The labels are the keys. Your answers are the values.
A computer reading your front matter does exactly what the hotel receptionist does: scans the labels, reads the values, and acts on what it finds. It knows to sort your post by the date value, to display your name because author has a value, to skip the post because published is false.
title not Titleword-count) or underscores (word_count)publishedAt every time, never sometimes published_atKey-value pairs give machines a reliable contract: to find the title, look up the key title. To find the date, look up date. No ambiguity, no guesswork, no reading comprehension required. This predictability is why the same pattern appears in databases, APIs, config files, and environment variables — everywhere structured data needs to be stored and retrieved.
Every value in a key-value pair is a specific type. The type isn't just a label — it determines what the computer can do with the value. Getting the type wrong is the #1 cause of front matter bugs.
Strings are the most common type. Any text value — a title, a name, a URL, a description — is a string. In YAML, you can write strings with or without quotes, but quoting is recommended to avoid ambiguity.
title: "My First Post" ← quoted author: Maria Santos ← unquoted (also valid) slug: "my-first-post" image: "/images/hero.jpg" description: "A post about learning" # multiline string (use | to preserve newlines) excerpt: | This is the first line. This is the second line.
Quote strings that contain colons, special characters, or that look like another type. title: "true" ensures it's a string, not a boolean. title: "2026-03-19" ensures it's text, not a date.
Numbers are written without quotes. There are two kinds: integers (whole numbers: 1, 42, 1500) and floats (decimals: 3.14, 4.5). The difference matters when the tool does arithmetic with your value.
word_count: 1500 ← integer rating: 4.5 ← float (decimal) read_time: 7 ← integer (minutes) version: 2 ← integer # WRONG — this is a string, not a number: word_count: "1500" ← quoted = string!
Booleans are the simplest type: exactly two valid values, true or false. They act as on/off switches — is this post published? Is it featured? Should comments be enabled? No quotes, no capitalisation.
published: true ← boolean featured: false ← boolean allow_comments: true ← boolean # WRONG — these are strings, not booleans: published: "true" ← quoted = string! published: True ← capitalised = string in JSON!
If your CMS checks if published === true and you pass the string "true", the check fails. The string and the boolean are different things, even though they look the same to human eyes.
An array holds multiple values under one key — a list of tags, a list of authors, a list of related post slugs. In YAML, you can write arrays in two styles: inline (everything on one line) or block (one item per line, indented).
# Inline style tags: ["tech", "learning", "AI"] categories: ["tutorials"] # Block style (same result, more readable) tags: - "tech" - "learning" - "AI" # Array of numbers related_ids: [42, 87, 103]
Objects are key-value pairs inside key-value pairs. They let you group related fields together under a parent key. In YAML, nesting is shown with indentation — 2 spaces per level, consistently.
author: name: "Alex Chen" email: "alex@example.com" twitter: "@alexchen" seo: title: "Custom SEO Title" description: "The meta description" image: "/og-image.jpg" noindex: false
In YAML, indentation is not cosmetic — it's structural. name indented under author means it belongs to the author object. Mis-indent it and it becomes a top-level key, breaking your structure. Always use spaces, never tabs.
Dates in YAML follow the ISO 8601 standard: YYYY-MM-DD for dates, YYYY-MM-DDTHH:MM:SSZ for full timestamps. Tools use date values for sorting, display, and scheduling. Written without quotes in YAML — adding quotes makes them a string.
date: 2026-03-19 ← date only updated: 2026-03-20 published_at: 2026-03-19T09:00:00Z ← full timestamp # This is a string, not a date: date: "2026-03-19" ← quoted = string date: "March 19, 2026" ← wrong format = string
A tool that sorts blog posts by date needs a real date value — not the text string "2026-03-19". A tool that filters unpublished posts needs a real boolean — not the string "true". Using the wrong type doesn't always cause an error you can see. Sometimes the data just silently does the wrong thing, which is harder to debug.
Front matter can be written in three formats. They all express the same key-value pairs — they just use different punctuation and conventions. Most tools default to YAML, but knowing the others helps you read any file you encounter.
The same front matter, written in all three formats:
--- title: "My Post" date: 2026-03-19 published: true tags: - "tech" - "AI" ---
+++ title = "My Post" date = 2026-03-19 published = true tags = [ "tech", "AI" ] +++
{
"title": "My Post",
"date": "2026-03-19",
"published": true,
"tags": [
"tech",
"AI"
]
} | Feature | YAML | TOML | JSON |
|---|---|---|---|
| Fence style | --- on each side | +++ on each side | Opening { to closing } |
| Key-value separator | Colon + space: key: value | Equals sign: key = value | Colon in quotes: "key": value |
| String quotes | Optional (recommended) | Required | Required (double quotes only) |
| Comments | Yes (# comment) | Yes (# comment) | No |
| Indentation | Structural (required) | Not structural | Cosmetic only |
| Default in | Jekyll, Astro, Hugo (optional), Eleventy | Hugo, Rust's Cargo.toml, Python's pyproject.toml | APIs, JavaScript, package.json |
| Best for | Human-authored files (blog posts, configs) | Project config files with explicit types | Machine-to-machine communication |
If your tool doesn't specify, use YAML. It's the most readable, the most widely supported in static site generators, and the one you're most likely to encounter in tutorials and documentation. Once you know YAML, reading TOML and JSON is straightforward — they're all the same idea in different clothing.
Front matter and key-value pairs aren't confined to blog posts. Once you know what to look for, you'll find this pattern throughout the entire technology stack.
Every .md file in a blog or documentation site typically has front matter controlling title, date, author, tags, SEO, draft status, and layout template.
These tools read front matter to build navigation, sitemaps, tag pages, and RSS feeds. The keys they recognise (and what they do with the values) are documented for each tool.
Headless CMS systems store all content as structured fields — which are key-value pairs in a database. When you design a content type, you're defining what keys exist and what types their values should be.
Every tool you install comes with a config file that's key-value pairs: the package name, version, dependencies, scripts to run. Reading config files becomes easy once you know the pattern.
When you request data from Spotify, GitHub, OpenWeather, or any other API, you get back a JSON object — which is key-value pairs. The keys are the field names; the values are the data.
.env files store secrets and configuration as key-value pairs: DATABASE_URL=postgres://.... The key is the variable name your code references; the value is the environment-specific secret.
A row in a database table is a collection of key-value pairs. The column names are the keys; the cell contents are the values. NoSQL databases like MongoDB store documents that are literally JSON objects — key-value pairs all the way down.
Workflow configuration files for automated testing and deployment are key-value pairs in YAML. on: push, runs-on: ubuntu-latest — the same grammar you learned in section 02, applied to infrastructure.
The reason this pattern is so universal is that key-value pairs are the simplest possible way to store structured information that's both human-readable and machine-parseable. Every technology that needs to store or transmit structured data eventually converges on some version of this pattern. Learning it once gives you a model for understanding dozens of formats and tools.
Most front matter bugs come from a small set of recurring mistakes. Learning to recognise them is faster than learning from experience.
The mistake: title:"My Post" — no space between colon and value.
The fix: title: "My Post" — always a colon, then a space, then the value.
Why it breaks: YAML parsers treat title: and the space as part of the key syntax. Without it, the parser can't split the line into key and value correctly.
The mistake: published: "true" or word_count: "1500".
The fix: Remove the quotes. published: true and word_count: 1500.
Why it breaks: Quotes turn any value into a string. "true" is the five-character text string t-r-u-e, not the boolean value true. Code that checks if published === true will fail silently.
The mistake: Pressing Tab to indent nested objects or block arrays.
The fix: Always use spaces — 2 per level of nesting.
Why it breaks: YAML explicitly prohibits tab characters for indentation. A tab character in a YAML file will cause a parse error, even if it looks identical to spaces on screen.
The mistake: Writing the opening --- but not the closing ---.
The fix: Always close your front matter fence with three dashes on their own line.
Why it breaks: Without the closing fence, the parser treats your entire document (article text and all) as part of the front matter, causing a parse error when it hits the first line that doesn't look like a key-value pair.
The mistake: Writing date: March 19, 2026 or date: 19/03/2026.
The fix: Always use ISO 8601 format: date: 2026-03-19.
Why it breaks: Tools that sort by date parse the date field as an ISO 8601 timestamp. Anything else gets treated as a string and sorts alphabetically — so "December" sorts before "February" because D comes before F — putting December ahead of February even though it's later in the year.
The mistake: title: "My Post's Story — the string contains an apostrophe and is missing its closing quote.
The fix: Use double quotes and escape internal apostrophes, or use single-quoted strings: title: 'My Post''s Story'.
Why it breaks: An unclosed string tells the parser to keep reading until it finds the closing quote — which means it may consume multiple lines.
YAML error messages almost always include a line number. Go to that line immediately — the problem is almost never where you expect it. Run your front matter through an online YAML validator (search "YAML lint") to catch errors before your build tool does. Most modern code editors (VS Code, Cursor) also highlight YAML syntax errors in real time.
Everything from this guide, condensed into a quick-reference format.
--- (YAML/JSON) or +++ (TOML). Invisible to readers; consumed by tools. key: value. The fundamental unit of structured data. Universal across all formats. title: "My Post" — or unquoted for simple values: author: Maria word_count: 1500 or rating: 4.5 published: true or featured: false tags: ["tech", "AI"] tags: - "tech" - "AI" author: name: "Alex" email: "a@x.com" date: 2026-03-19 ---. Separator: colon + space. Optional quotes. Comments with #. Indentation is structural. Default for most static sites. +++. Separator: equals sign. Required quotes for strings. Comments with #. Default for Hugo and Rust projects. { }. Separator: colon. All keys and strings require double quotes. No comments. Universal for APIs and JavaScript. title:"..." → fix: title: "..." published: "true" → fix: published: true --- opener needs a --- closer "March 19, 2026" → fix: 2026-03-19 (no quotes) Natural T3 continuations of this topic — not live yet, but they're coming.
The YAML 1.2 spec's four processing layers, parser divergence, advanced Zod schemas, and typed config alternatives at scale.
The spec that defines what your data is allowed to look like — powers VS Code autocomplete, API contracts, and Astro content schemas.
Why .env files exist, how dotenv works, what secrets managers do, and why you should never hardcode a key.