Skip to content

Frontmatter API Reference

Auto-generated API documentation for the frontmatter module.

frontmatter

Frontmatter parser and serializer — zero dependencies, stdlib only, Python 3.10+.

Part of zerodep: https://github.com/Oaklight/zerodep Copyright (c) 2026 Peng Ding. MIT License.

Parse and serialize file-header metadata (frontmatter) in YAML, TOML, or JSON format. YAML --- frontmatter is the de facto standard used by Jekyll, Hugo, Astro, MkDocs, Obsidian, and many other tools.

Example::

from frontmatter import loads, dumps, Document

# Parse
doc = loads("""---
title: Hello World
tags: [python, zerodep]
---
# Hello

This is the content.
""")
print(doc.metadata)  # {'title': 'Hello World', 'tags': ['python', 'zerodep']}
print(doc.content)   # '# Hello\n\nThis is the content.\n'

# Serialize
doc = Document({"title": "New Post"}, "Some content.")
print(dumps(doc))

# TOML frontmatter (Python 3.11+)
doc = loads("""+++
title = "Hello"
+++
Content here.
""")

# JSON frontmatter
doc = loads('{"title": "Hello"}\nContent here.')

Requires Python 3.10+.

FrontmatterError

Bases: Exception

Base exception for frontmatter parsing errors.

Source code in frontmatter/frontmatter.py
class FrontmatterError(Exception):
    """Base exception for frontmatter parsing errors."""

HandlerError

Bases: FrontmatterError

Raised when a requested handler is not available.

Attributes:

Name Type Description
handler

Name of the handler that caused the error.

Source code in frontmatter/frontmatter.py
class HandlerError(FrontmatterError):
    """Raised when a requested handler is not available.

    Attributes:
        handler: Name of the handler that caused the error.
    """

    def __init__(self, message: str, *, handler: str = "") -> None:
        self.handler = handler
        super().__init__(message)

Document dataclass

A document with frontmatter metadata and body content.

Attributes:

Name Type Description
metadata dict[str, Any]

Parsed frontmatter key-value pairs.

content str

The body text after the frontmatter block.

Source code in frontmatter/frontmatter.py
@dataclasses.dataclass
class Document:
    """A document with frontmatter metadata and body content.

    Attributes:
        metadata: Parsed frontmatter key-value pairs.
        content: The body text after the frontmatter block.
    """

    metadata: dict[str, Any] = dataclasses.field(default_factory=dict)
    content: str = ""

    def __bool__(self) -> bool:
        return bool(self.metadata) or bool(self.content)

    def get(self, key: str, default: Any = None) -> Any:
        """Get a metadata value by key."""
        return self.metadata.get(key, default)

    def __getitem__(self, key: str) -> Any:
        return self.metadata[key]

    def __setitem__(self, key: str, value: Any) -> None:
        self.metadata[key] = value

    def __contains__(self, key: str) -> bool:
        return key in self.metadata

    def keys(self) -> Any:
        """Return metadata keys."""
        return self.metadata.keys()

    def values(self) -> Any:
        """Return metadata values."""
        return self.metadata.values()

    def items(self) -> Any:
        """Return metadata items."""
        return self.metadata.items()

get(key, default=None)

Get a metadata value by key.

Source code in frontmatter/frontmatter.py
def get(self, key: str, default: Any = None) -> Any:
    """Get a metadata value by key."""
    return self.metadata.get(key, default)

keys()

Return metadata keys.

Source code in frontmatter/frontmatter.py
def keys(self) -> Any:
    """Return metadata keys."""
    return self.metadata.keys()

values()

Return metadata values.

Source code in frontmatter/frontmatter.py
def values(self) -> Any:
    """Return metadata values."""
    return self.metadata.values()

items()

Return metadata items.

Source code in frontmatter/frontmatter.py
def items(self) -> Any:
    """Return metadata items."""
    return self.metadata.items()

detect_handler(text)

Detect the frontmatter format of a text string.

Parameters:

Name Type Description Default
text str

The full document text.

required

Returns:

Type Description
str | None

"yaml", "toml", "json", or None if no frontmatter

str | None

is detected.

Source code in frontmatter/frontmatter.py
def detect_handler(text: str) -> str | None:
    """Detect the frontmatter format of a text string.

    Args:
        text: The full document text.

    Returns:
        ``"yaml"``, ``"toml"``, ``"json"``, or ``None`` if no frontmatter
        is detected.
    """
    stripped = text.lstrip(_BOM)
    if stripped.startswith(_YAML_FENCE + "\n") or stripped.startswith(
        _YAML_FENCE + "\r\n"
    ):
        return "yaml"
    if stripped.startswith(_TOML_FENCE + "\n") or stripped.startswith(
        _TOML_FENCE + "\r\n"
    ):
        return "toml"
    if stripped.startswith("{"):
        return "json"
    return None

check(text)

Check whether a text string contains frontmatter.

Parameters:

Name Type Description Default
text str

The full document text.

required

Returns:

Type Description
bool

True if frontmatter is detected.

Source code in frontmatter/frontmatter.py
def check(text: str) -> bool:
    """Check whether a text string contains frontmatter.

    Args:
        text: The full document text.

    Returns:
        ``True`` if frontmatter is detected.
    """
    return detect_handler(text) is not None

loads(text, *, handler=None)

Parse a text string with frontmatter.

Parameters:

Name Type Description Default
text str

The full document text.

required
handler str | None

Force a specific format ("yaml", "toml", "json"). If None, the format is auto-detected.

None

Returns:

Type Description
Document

A Document with parsed metadata and body content.

Raises:

Type Description
FrontmatterError

If parsing fails.

HandlerError

If the requested handler is not available.

Example::

doc = loads("---\ntitle: Hello\n---\nBody text.")
doc.metadata  # {'title': 'Hello'}
doc.content   # 'Body text.'
Source code in frontmatter/frontmatter.py
def loads(text: str, *, handler: str | None = None) -> Document:
    """Parse a text string with frontmatter.

    Args:
        text: The full document text.
        handler: Force a specific format (``"yaml"``, ``"toml"``, ``"json"``).
            If ``None``, the format is auto-detected.

    Returns:
        A ``Document`` with parsed metadata and body content.

    Raises:
        FrontmatterError: If parsing fails.
        HandlerError: If the requested handler is not available.

    Example::

        doc = loads("---\\ntitle: Hello\\n---\\nBody text.")
        doc.metadata  # {'title': 'Hello'}
        doc.content   # 'Body text.'
    """
    if handler is None:
        handler = detect_handler(text)

    if handler is None:
        # No frontmatter detected — entire text is content
        return Document(metadata={}, content=text)

    if handler == "yaml":
        parts = _split_fenced(text, _YAML_FENCE)
        if parts is None:
            return Document(metadata={}, content=text)
        raw, body = parts
        if not raw.strip():
            return Document(metadata={}, content=body)
        metadata = _parse_yaml(raw)
        return Document(metadata=metadata, content=body)

    if handler == "toml":
        parts = _split_fenced(text, _TOML_FENCE)
        if parts is None:
            return Document(metadata={}, content=text)
        raw, body = parts
        if not raw.strip():
            return Document(metadata={}, content=body)
        metadata = _parse_toml(raw)
        return Document(metadata=metadata, content=body)

    if handler == "json":
        parts = _split_json(text)
        if parts is None:
            return Document(metadata={}, content=text)
        raw, body = parts
        metadata = _parse_json(raw)
        return Document(metadata=metadata, content=body)

    raise HandlerError(
        f"unknown handler: {handler!r} (expected yaml/toml/json)", handler=handler
    )

load(source, *, handler=None)

Parse a file with frontmatter.

Parameters:

Name Type Description Default
source IO[str] | str | Path

A file path (str or Path) or an open text stream.

required
handler str | None

Force a specific format. If None, auto-detect.

None

Returns:

Type Description
Document

A Document with parsed metadata and body content.

Example::

doc = load("post.md")
doc = load(Path("post.md"))
with open("post.md") as f:
    doc = load(f)
Source code in frontmatter/frontmatter.py
def load(
    source: IO[str] | str | Path,
    *,
    handler: str | None = None,
) -> Document:
    """Parse a file with frontmatter.

    Args:
        source: A file path (``str`` or ``Path``) or an open text stream.
        handler: Force a specific format. If ``None``, auto-detect.

    Returns:
        A ``Document`` with parsed metadata and body content.

    Example::

        doc = load("post.md")
        doc = load(Path("post.md"))
        with open("post.md") as f:
            doc = load(f)
    """
    if isinstance(source, (str, Path)):
        text = Path(source).read_text(encoding="utf-8")
    else:
        text = source.read()
    return loads(text, handler=handler)

dumps(doc, *, handler='yaml', **kwargs)

Serialize a Document to a string with frontmatter.

Parameters:

Name Type Description Default
doc Document

The document to serialize.

required
handler str

Output format ("yaml", "toml", "json"). Defaults to "yaml".

'yaml'
**kwargs Any

Passed to the underlying serializer.

{}

Returns:

Type Description
str

The full document text with frontmatter and body.

Example::

doc = Document({"title": "Hello"}, "Body text.")
text = dumps(doc)
# ---
# title: Hello
# ---
# Body text.
Source code in frontmatter/frontmatter.py
def dumps(
    doc: Document,
    *,
    handler: str = "yaml",
    **kwargs: Any,
) -> str:
    """Serialize a ``Document`` to a string with frontmatter.

    Args:
        doc: The document to serialize.
        handler: Output format (``"yaml"``, ``"toml"``, ``"json"``).
            Defaults to ``"yaml"``.
        **kwargs: Passed to the underlying serializer.

    Returns:
        The full document text with frontmatter and body.

    Example::

        doc = Document({"title": "Hello"}, "Body text.")
        text = dumps(doc)
        # ---
        # title: Hello
        # ---
        # Body text.
    """
    if handler == "yaml":
        fence = _YAML_FENCE
        raw = _dump_yaml(doc.metadata, **kwargs) if doc.metadata else ""
    elif handler == "toml":
        fence = _TOML_FENCE
        raw = _dump_toml(doc.metadata, **kwargs) if doc.metadata else ""
    elif handler == "json":
        raw_json = _dump_json(doc.metadata, **kwargs) if doc.metadata else ""
        # JSON uses { } as delimiters, no fence
        if doc.content:
            return raw_json + doc.content
        return raw_json
    else:
        raise HandlerError(
            f"unknown handler: {handler!r} (expected yaml/toml/json)", handler=handler
        )

    parts = [fence, "\n"]
    if raw:
        # Ensure raw ends with newline
        if not raw.endswith("\n"):
            raw += "\n"
        parts.append(raw)
    parts.append(fence)
    parts.append("\n")
    if doc.content:
        parts.append(doc.content)
    return "".join(parts)

dump(doc, dest, *, handler='yaml', **kwargs)

Serialize a Document to a file with frontmatter.

Parameters:

Name Type Description Default
doc Document

The document to serialize.

required
dest IO[str] | str | Path

A file path (str or Path) or an open text stream.

required
handler str

Output format. Defaults to "yaml".

'yaml'
**kwargs Any

Passed to the underlying serializer.

{}

Example::

dump(doc, "post.md")
dump(doc, Path("post.md"), handler="toml")
with open("post.md", "w") as f:
    dump(doc, f)
Source code in frontmatter/frontmatter.py
def dump(
    doc: Document,
    dest: IO[str] | str | Path,
    *,
    handler: str = "yaml",
    **kwargs: Any,
) -> None:
    """Serialize a ``Document`` to a file with frontmatter.

    Args:
        doc: The document to serialize.
        dest: A file path (``str`` or ``Path``) or an open text stream.
        handler: Output format. Defaults to ``"yaml"``.
        **kwargs: Passed to the underlying serializer.

    Example::

        dump(doc, "post.md")
        dump(doc, Path("post.md"), handler="toml")
        with open("post.md", "w") as f:
            dump(doc, f)
    """
    text = dumps(doc, handler=handler, **kwargs)
    if isinstance(dest, (str, Path)):
        Path(dest).write_text(text, encoding="utf-8")
    else:
        dest.write(text)