Markdown Front Matter: The Complete Guide to YAML Metadata Headers

You open a Markdown file and notice a block of text at the top wrapped in --- — that's front matter. It doesn't show up on the page, but behind the scenes it controls the title, date, tags, template, and other important metadata.

If you've built a blog with Jekyll or Hugo, or managed notes in Obsidian, front matter is something you can't really avoid. This article covers the YAML syntax, how to write it, differences across tools, and the pitfalls I've run into myself. A basic understanding of Markdown syntax is all you need to follow along.

What Is Front Matter

Front matter is a block of metadata at the very beginning of a Markdown file. It's delimited by triple dashes --- at the start and end, with YAML key-value pairs in between. It tells the tool processing the file: "Hey, this article has this title, that date, and these categories."

A minimal example:

---
title: My First Article
date: 2026-05-13
---

Content starts here...

A few hard rules: front matter must be the very first thing in the file (no blank lines before it), the content between the two --- lines must be valid YAML, and the closing --- is required.

One point of confusion — --- in the body of a Markdown file renders as a horizontal rule, but when it appears at the very top of a file, all major parsers recognize it as the front matter delimiter instead.

YAML Syntax Cheat Sheet

The content inside front matter follows YAML syntax. If you've never worked with YAML before, here's a quick rundown of the essentials.

Basic Key-Value Pairs

title: My First Article
author: Alice
draft: false
views: 1024

Add a space after the colon, then write the value. Booleans use true / false, and numbers are written directly.

An easy trap to fall into: if your value contains a colon : or a hash #, you must wrap it in quotes — otherwise the parser will choke. For example:

title: "Getting Started: From Scratch"
description: "Tip #1: Keep it simple"

Without quotes, everything after : gets parsed as a new key-value pair, and everything after # is treated as a comment and ignored.

Lists

Both styles work — pick whichever you prefer:

Inline style:

tags: [markdown, yaml, tutorial]

Block style:

tags:
  - markdown
  - yaml
  - tutorial

Nested Objects

seo:
  title: "SEO Title"
  description: "Page description"
  image: "/images/cover.png"

Nested levels are indented with two spaces. Honestly, I used to indent with Tab out of habit, and Jekyll builds would just fail — the YAML spec only accepts spaces, and Tab characters break parsing. This is one of the most common mistakes for beginners.

Date Format

ISO 8601 is the recommended format:

date: 2026-05-13
lastmod: 2026-05-13T14:30:00+08:00

Some tools only need the date portion, while others expect a full timestamp. Check your tool's documentation for specifics.

Common Fields Reference

Different tools support different fields, but the ones below are widely recognized across most platforms:

FieldDescriptionExample
titleArticle titletitle: My First Article
datePublication datedate: 2026-05-13
lastmodLast modified datelastmod: 2026-05-13
authorAuthor nameauthor: Alice
tagsTag listtags: [markdown, yaml]
categoriesCategoriescategories: [tutorial]
descriptionPage description (SEO)description: A guide to...
draftDraft flagdraft: true
layoutTemplate to uselayout: post
slugCustom URL slugslug: my-first-post
weightSort order weightweight: 10

These field names are conventions, not part of the YAML standard. In other words, you can write banana: true, but no tool will recognize it — it'll just be silently ignored.

Tool Differences Comparison

This is where front matter gets confusing: the same field can behave differently depending on the tool. I compared several popular ones:

FeatureJekyllHugoVitePressObsidian
Format supportYAMLYAML / TOML / JSONYAMLYAML
Empty front matter✅ File is processed
tags for taxonomy❌ Needs custom handling✅ Dataview queries
draft: true skips build❌ Not by default✅ Skipped in production❌ Needs config❌ Display only
Nested objects⚠️ Some plugins support
Custom fields✅ Via Liquid templates.Params access$frontmatter✅ Dataview queries
TOML support✅ Uses +++ delimiter

Take the draft field as an example: in Hugo, articles with draft: true are automatically skipped during production builds, which is really convenient. But in Jekyll, draft articles get published by default unless you add the --drafts flag or manage them in the _drafts directory.

I figured out these differences the hard way while maintaining both a Jekyll blog and a Hugo documentation site simultaneously.

A Complete Front Matter Example

Here's a configuration you'd actually use in a real project:

---
title: "Markdown Front Matter: A Complete Guide"
date: 2026-05-13T10:00:00+08:00
author: "Alice"
tags:
  - markdown
  - yaml
  - tutorial
categories:
  - documentation
description: "From YAML syntax to tool differences — everything you need to know about Markdown Front Matter."
draft: false
slug: markdown-front-matter-guide
seo:
  title: "Markdown Front Matter & YAML Metadata"
  description: "What front matter is, how to write it, and how tools differ."
  image: "/images/frontmatter-cover.png"
---

## Content Starts Here

Your article content...

Troubleshooting Common Issues

When front matter goes wrong, it's usually one of these scenarios:

YAML Parse Errors

Symptoms: the tool reports invalid front matter, or field values aren't what you expected.

Things to check:

  1. Is indentation using spaces? — Tab characters break parsing; this is the #1 cause
  2. Is there a space after the colon?title:my article (wrong) vs title: my article (correct)
  3. Are special characters quoted? — Values containing : # [] need quotes
  4. Are list items aligned? — The - in block-style lists must be consistently indented

Front Matter Not Taking Effect

Symptoms: you wrote front matter but the tool doesn't seem to recognize it.

Common causes:

  • A blank line or BOM character before the opening --- (file encoding issue)
  • Using ... instead of --- as the closing delimiter (some tools don't support this)
  • Wrong file extension (e.g., Jekyll requires .md or .html)

Values Parsed Incorrectly

version: 1.0

You might expect version to be the string "1.0", but the YAML parser treats it as the float 1.0. The fix: add quotes.

version: "1.0"

A similar gotcha applies to true/false/yes/no/on/off — YAML parses all of these as booleans. If your value happens to be one of these words (e.g., tags like tags: [on, off]), remember to quote them.

Parsing Front Matter with Code

Sometimes you need to batch-process Markdown files and extract the metadata from front matter. In the JavaScript ecosystem, the go-to library is gray-matter:

const matter = require('gray-matter');

const file = matter.read('./article.md');
console.log(file.data);    // { title: '...', date: '...', tags: [...] }
console.log(file.content); // Content below the '---' delimiter

Python users can use python-frontmatter:

import frontmatter

with open('article.md') as f:
    post = frontmatter.load(f)

print(post['title'])   # Article title
print(post.metadata)   # Full front matter dictionary
print(post.content)    # Body content

Both libraries follow the same approach: split a Markdown file into data (metadata) and content (body) so you can handle them separately.

References