front-matter
front-matter is a small CommonJS parser for YAML metadata placed at the very start of a text string. Give it a Markdown document and it returns the parsed attributes, the remaining body, the original YAML text, and the line where the body begins. It performs no file I/O, rendering, validation, or serialization. Its narrow API suits older Node.js tools that need only to split a document and parse its YAML header.
Keep it where its tiny CommonJS API already works, especially if bodyBegin matters. For a new content pipeline, gray-matter offers a broader feature set and a healthier default path.
Use it if
- You maintain a CommonJS content tool that already uses front-matter and its attributes/body return shape
- You need bodyBegin for mapping parser or lint errors back to source lines
- Your documents use YAML fenced by --- or the less common = yaml = marker
- You want a synchronous string-in, object-out parser and will handle file reads and schema validation yourself
- You are choosing a parser for a new project: version 4.0.2 was published in May 2020 and the repository has not been pushed since August 2023
- You need ESM exports or a documented browser build; the package entry point is CommonJS and the README examples use require
- You need JSON, TOML, or custom delimiters; the source recognizes only YAML between ---, = yaml =, or a closing ... marker
- You want built-in stringify support; the public API only parses strings and tests whether a front matter header is present
- You need current YAML behavior and security fixes quickly; version 4.0.2 depends on the older js-yaml 3.x line instead of js-yaml 4
Setup reality
Installation is only `npm install front-matter`, with no peer dependencies, native compilation, credentials, or config file. The important constraint is input shape. The opening marker must be on the first line, although a UTF-8 byte order mark is accepted, so leading comments or blank lines cause the entire input to be returned as body with empty attributes. The module does not read files, so use `fs.readFile` or `fs/promises` and pass decoded text yourself. It is CommonJS (`require('front-matter')`); ESM projects can default-import it through Node interoperability, but the package has no exports map and does not declare a native ESM entry point. Safe parsing is the default. Setting `{ allowUnsafe: true }` switches from js-yaml's `safeLoad` to `load`, which permits JavaScript-specific YAML types and should not be enabled for untrusted documents. Malformed YAML throws a YAMLException rather than returning an error object. There is no metadata schema validation and no serializer, so dates, arrays, unknown keys, and required fields remain your responsibility. The result always has attributes, body, and bodyBegin; frontmatter exists only when a valid fenced header was found. Version 4.0.2 carries js-yaml `^3.13.1`, an older dependency line worth considering in long-lived new projects.
Patterns
Parse YAML metadata and bodyparse-document
const fm = require('front-matter')
const doc = fm('---\ntitle: Hello\ntags: [node, docs]\n---\nArticle text')
console.log(doc.attributes.title)
console.log(doc.body)The opening marker must be on the first line or the input is treated as body-only content.
Read and parse a Markdown fileread-markdown-file
const { readFile } = require('node:fs/promises')
const fm = require('front-matter')
const source = await readFile('./post.md', 'utf8')
const { attributes, body } = fm(source)The package performs no file I/O; always decode the file to a string before parsing.
Use the CommonJS package from ESMimport-from-esm
import fm from 'front-matter'
const { attributes, body } = fm(source)This relies on Node's CommonJS default-import interoperability; the package has no native ESM export map.
Check for a front matter headerdetect-front-matter
const fm = require('front-matter')
if (fm.test(source)) {
const parsed = fm(source)
console.log(parsed.attributes)
}test checks syntax only; it does not validate or parse the YAML payload.
Handle documents without metadatahandle-body-only
const parsed = fm(source)
if (Object.keys(parsed.attributes).length === 0) {
console.log('No front matter')
}
console.log(parsed.body)With no valid header, body is the original input, bodyBegin is 1, and frontmatter is absent.
Map a body line to its source linemap-body-lines
const parsed = fm(source)
const bodyLine = 3
const sourceLine = parsed.bodyBegin + bodyLine - 1
console.log({ bodyLine, sourceLine })bodyBegin is one-based, matching ordinary editor line numbers.
Access the original YAML textpreserve-raw-yaml
const parsed = fm(source)
if (parsed.frontmatter !== undefined) {
console.log(parsed.frontmatter)
}frontmatter excludes the delimiter lines and is missing when no valid header was parsed.
Parse the alternate YAML markeruse-yaml-marker
const parsed = fm('= yaml =\ntitle: Alternate\n= yaml =\nBody')
console.log(parsed.attributes.title)The source accepts `= yaml =`, but the conventional `---` marker is much more portable across content tools.
Close front matter with three dotsuse-document-end-marker
const parsed = fm('---\ntitle: Dot ending\n...\nBody')
console.log(parsed.body)A closing `...` is accepted, but the opening marker still has to be `---` or `= yaml =`.
Catch malformed YAMLcatch-invalid-yaml
try {
const parsed = fm(source)
usePost(parsed)
} catch (error) {
console.error('Invalid front matter:', error.message)
}Parsing errors are thrown by js-yaml; the package does not return an error field or partial result.
Validate required metadata after parsingvalidate-attributes
const { attributes, body } = fm(source)
if (typeof attributes.title !== 'string' || !attributes.title.trim()) {
throw new TypeError('front matter requires a title')
}
publish({ title: attributes.title, body })YAML parsing is not schema validation; check types and required keys before using metadata.
Opt into JavaScript-specific YAML typesallow-unsafe-yaml
const parsed = fm(source, { allowUnsafe: true })
console.log(parsed.attributes)Do not enable allowUnsafe for user-controlled content; it switches from safeLoad to js-yaml's broader load behavior.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| gray-matter | npm | Choose it for a more widely used parser with stringify support, custom engines, and custom delimiters |
| vfile-matter | npm | Choose it when content already flows through the unified and vfile ecosystem |
| yaml-front-matter | npm | Choose it when its filename-based loading API matches a small legacy script |