front-matter, gray-matter, and yaml-front-matter are utilities designed to extract metadata (front matter) from the top of files, typically Markdown or text files. This metadata is often used in static site generators (like Jekyll, Hexo, or Next.js) to define page titles, dates, layouts, and other configuration. While they share the same core purpose, they differ significantly in supported formats (YAML, JSON, TOML), parsing engines, extensibility, and current maintenance status. gray-matter is generally the most robust and actively maintained, while yaml-front-matter is often considered legacy.
When building static sites, documentation tools, or content management systems, you often need to store metadata at the top of a file. This is called "front matter." It usually sits between delimiters (like ---) and contains YAML, JSON, or TOML. Three common packages handle this in the JavaScript ecosystem: front-matter, gray-matter, and yaml-front-matter. While they solve the same problem, their capabilities and maintenance status vary widely.
The most critical difference is what data formats each package supports out of the box.
front-matter focuses primarily on YAML.
js-yaml library under the hood.// front-matter: YAML only by default
import fm from 'front-matter';
const file = `---
title: Hello
---
Content here`;
const result = fm(file);
console.log(result.attributes.title); // "Hello"
gray-matter supports multiple languages natively.
// gray-matter: Multi-language support
import matter from 'gray-matter';
// YAML
const yamlFile = matter(`---
title: Hello
---
Content`);
// JSON
const jsonFile = matter(`+++json
{
"title": "Hello"
}
+++
Content`);
console.log(yamlFile.data.title); // "Hello"
console.log(jsonFile.data.title); // "Hello"
yaml-front-matter is strictly for YAML.
gray-matter.// yaml-front-matter: Strictly YAML
import yfm from 'yaml-front-matter';
const file = `---
title: Hello
---
Content here`;
const result = yfm.loadFront(file);
console.log(result.title); // "Hello"
// Note: API returns attributes directly on the object, not nested
How you access the data and write it back differs between these libraries. This affects how much boilerplate code you write.
front-matter returns a structured object.
attributes holds the metadata.body holds the content.// front-matter: Read-only structure
import fm from 'front-matter';
const result = fm(file);
const meta = result.attributes;
const content = result.body;
// No built-in stringify method to reconstruct the file
gray-matter offers a symmetric API (read and write).
data holds the metadata.content holds the body..stringify() to write changes back to disk cleanly.// gray-matter: Read and Write
import matter from 'gray-matter';
const file = matter(fileString);
file.data.title = "Updated Title";
// Reconstruct the file with new front matter
const newFile = matter.stringify(file.content, file.data);
yaml-front-matter merges metadata into the result.
__content property usually holds the body.gray-matter.// yaml-front-matter: Merged result
import yfm from 'yaml-front-matter';
const result = yfm.loadFront(file);
const title = result.title; // Direct access
const content = result.__content; // Body is a property
// No built-in stringify method
Real-world projects often need custom delimiters (like +++ for Hugo) or custom parsing logic.
front-matter allows some delimiter config.
// front-matter: Custom delimiters
import fm from 'front-matter';
// Configuring delimiters is less straightforward
// often requires passing options to the function if supported
// or relying on default '---'
const result = fm(file, { delimiters: '+++' });
gray-matter is highly extensible.
+++ for TOML).// gray-matter: Custom delimiters and engines
import matter from 'gray-matter';
// Using +++ for TOML or custom YAML
const file = matter(fileString, {
delimiters: '+++',
engines: {
yaml: require('js-yaml').safeLoad
}
});
yaml-front-matter has minimal configuration.
gray-matter.// yaml-front-matter: Limited config
import yfm from 'yaml-front-matter';
// Mostly relies on default '---' delimiters
// Harder to customize parsing behavior
const result = yfm.loadFront(file);
This is a critical architectural decision factor. Using unmaintained packages introduces security and compatibility risks.
front-matter is stable but slower moving.
gray-matter is the active standard.
yaml-front-matter is effectively legacy.
gray-matter.| Feature | front-matter | gray-matter | yaml-front-matter |
|---|---|---|---|
| Primary Format | YAML | YAML, JSON, TOML | YAML |
| Stringify Support | ❌ No | ✅ Yes | ❌ No |
| Custom Delimiters | ⚠️ Limited | ✅ Yes | ❌ No |
| API Style | { attributes, body } | { data, content } | Merged Object |
| Maintenance | Stable | Active | Legacy |
| Best For | Simple YAML parsing | Modern SSG / Build Tools | Legacy Maintenance |
gray-matter is the clear winner for modern development. It handles the complexity of different formats, allows you to write data back to files easily, and is actively maintained. It saves you from writing boilerplate code to handle edge cases.
front-matter is a decent runner-up if you only care about YAML and want a very lightweight dependency without the extra features of gray-matter. It is safe to use but offers less flexibility.
yaml-front-matter should generally be avoided in new projects. It lacks the features and maintenance cadence of the other two. Only use it if you are stuck maintaining an older system that depends on its specific API behavior.
Final Thought: In 2024 and beyond, gray-matter is the architectural standard for front matter parsing. It balances power, flexibility, and stability better than the alternatives.
Avoid yaml-front-matter for new projects as it is largely considered legacy and less actively maintained compared to gray-matter. Only choose this if you are maintaining an older codebase that already depends on it and refactoring is not feasible, or if you have a very specific requirement for its narrow YAML-only implementation that matches an old workflow.
Choose front-matter if you need a lightweight, stable parser specifically for YAML front matter and want to stick with the js-yaml engine directly. It is a solid choice for simple use cases where you do not need JSON or TOML support, and you prefer a minimal API surface without extra abstraction layers.
Choose gray-matter for most modern projects, especially if you need support for multiple languages (YAML, JSON, TOML) or custom delimiters. It is actively maintained, highly extensible with custom engines, and offers the best developer experience with features like stringifying content back with front matter intact. It is the industry standard for this task.
Parses yaml or json at the front of a string. Places the parsed content, plus the rest of the string content, into an object literal.
This readme is for the 4.x release, which introduces breaking changes. View the changelog for more information.
This
---
name: Derek Worthen
age: 127
contact:
email: email@domain.com
address: some location
pets:
- cat
- dog
- bat
match: !!js/regexp /pattern/gim
run: !!js/function function() { }
---
Some Other content
var fs = require('fs');
var yamlFront = require('yaml-front-matter');
fs.readFile('./some/file.txt', 'utf8', function(fileContents) {
console.log(yamlFront.loadFront(fileContents));
});
outputs
{
name: 'Derek Worthen',
age: 127,
contact: { email: 'email@domain.com', address: 'some location' },
pets: [ 'cat', 'dog', 'bat' ],
match: /pattern/gim,
run: [Function],
__content: '\nSome Other Content'
}
May also use JSON
---
{
"name": "Derek Worthen",
"age": "young",
"anArray": ["one","two"],
"subObj":{"field1": "one"}
}
---
Some content
NOTE: The
---are required to denote the start and end of front matter. There must be a newline after the opening---and a newline preceding the closing---.
$ npm install yaml-front-matter
Use the -g flag if you plan on using the command line tool.
$ npm install yaml-front-matter -g
var yamlFront = require('yaml-front-matter');
The dist/yamlFront.js client script will expose the yaml-front-matter library as a global, yamlFront. The client script for js-yaml is also required. May need to load espirma for some use cases. See js-yaml for more information.
<script src="https://unpkg.com/js-yaml@3.10.0/dist/js-yaml.js"></script>
<script src="yamlFront.js"></script>
<script>
// parse front matter with yamlFront.loadFront(String);
</script>
Note: yaml-front-matter is delivered as a umd package so it should work within commonjs, amd and browser (as a global) environments.
$ npm install --dev && npm start
Then visit localhost:8080.
Outputs build files to dist/.
$ npm install --dev && npm run build
npm install --dev && npm test
Usage: yaml-front-matter [options] <yaml-front-matter content>
Options:
-h, --help output usage information
-v, --version output the version number
-c, --content [name] set the property name for the files contents [__content]
--pretty formats json output with spaces.
Note The cli uses
safeLoadFrontand therefore will not parse yaml containing regexps, functions or undefined values.
# Piping content from one file, through yaml parser and into another file
cat ./some/file.txt | yaml-front-matter > output.txt
Yaml front matter wraps js-yaml to support parsing yaml front-matter.
var input = [
'---\npost: title one\n',
'anArray:\n - one\n - two\n',
'subObject:\n prop1: cool\n prop2: two',
'\nreg: !!js/regexp /pattern/gim',
'\nfun: !!js/function function() { }\n---\n',
'content\nmore'
].join('');
var results = yamlFront.loadFront(input);
console.log(results);
outputs
{ post: 'title one',
anArray: [ 'one', 'two' ],
subObject: { obj1: 'cool', obj2: 'two' },
reg: /pattern/gim,
fun: [Function],
__content: '\ncontent\nmore' }
Front-matter is optional.
yamlFront.loadFront('Hello World');
// => { __content: "Hello World!" }
Content is optional
yamlFront.loadFront('');
// => { __content: '' }
Same api as loadFront except it does not support regexps, functions or undefined. See js-yaml for more information.
The options object supports the same options available to js-yaml and adds support for an additional key.
options.contentKeyName: Specify the object key where to store content not parsed by yaml-front-matter. defaults to __content.yamlFront.loadFront('Hello World', {
contentKeyName: 'fileContents'
});
// => { fileContents: "Hello World" }