gray-matter

Fast, dependable front-matter parser for YAML, JSON, TOML, and CoffeeScript metadata blocks

Library
npm
v4.0.3
4,495 stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
38 /100 Needs Attention
Development Activity 0
Maintenance 0
Community 52
Maturity 60
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
80 /100 Excellent
Architecture 80
Code Quality 78
Innovation 75
Learning Curve 88

gray-matter takes a string or file and splits it into a parsed metadata object plus the remaining content, handling the --- delimited front-matter blocks used across static site generators and content pipelines. It parses YAML by default and ships built-in support for JSON, TOML, and JavaScript, with a pluggable engine system for adding custom languages like CoffeeScript.

Unlike regex-based alternatives, gray-matter uses real parsers for each supported language, so it correctly handles edge cases such as non-front-matter fenced code blocks that happen to contain --- sequences. It’s a foundational dependency behind Gatsby, Metalsmith, Assemble, VitePress, TinaCMS, and many other content-driven tools, with over 4,400 GitHub stars and roughly 8 million weekly npm downloads.

What You Get

  • A single matter(input, options) function that returns data, content, excerpt, isEmpty, and non-enumerable debugging fields (orig, language, matter, stringify)
  • Built-in engines for YAML (via js-yaml), JSON, and JavaScript front-matter, plus a pluggable options.engines API for TOML, CoffeeScript, CSON, or any custom format
  • matter.stringify() to serialize data back into a front-matter block prepended to content, useful for linting or programmatically updating files
  • matter.read(filepath, options) to parse front-matter directly from a file path without a manual fs.readFileSync call
  • matter.test(string) to cheaply check whether a string contains front-matter before doing a full parse
  • Excerpt extraction via options.excerpt (boolean, string separator, or custom function) for pulling a summary that sits between the front-matter and the main body
  • Custom delimiter support (options.delimiters) for projects that don’t want to use the default --- fence

Common Use Cases

  • Extracting page metadata (title, date, tags, layout) from Markdown files in a static site generator or content pipeline, as Gatsby, Metalsmith, and Astro-adjacent tooling do
  • Building a custom MDX/Markdown content loader that needs both the parsed frontmatter object and the raw body content for further processing
  • Round-tripping content: reading a file’s front-matter, programmatically modifying fields, and writing it back with matter.stringify()
  • Generating excerpts/summaries for blog listings by extracting the text between front-matter and a separator marker
  • Supporting multiple metadata formats (YAML plus TOML or JSON) in the same project via custom engines, for tools that need to interoperate with Jekyll- or Hugo-authored content

Under The Hood

Architecture gray-matter’s public entry point (index.js) exposes a cached matter() function that normalizes input via lib/to-file.js (wrapping raw strings into a file-like object with non-enumerable orig/language/matter/stringify properties), then delegates delimiter detection and language dispatch to parseMatter. Actual parsing is handled by lib/parse.js, which resolves the requested language against lib/engine.js (a per-language engine lookup) and calls its parse function; excerpt extraction (lib/excerpt.js) and section splitting (via the section-matter dependency) run as a second pass over the already-split content. lib/stringify.js mirrors this for the reverse direction, merging file.data with new data and re-serializing through the same engine abstraction. The design cleanly separates “find the front-matter block” from “parse this language,” which is what makes adding a new format (TOML, CoffeeScript) a matter of registering an engine object rather than touching the core split logic.

Tech Stack The library is plain CommonJS JavaScript with no build step (main: index.js, typings: gray-matter.d.ts, Node >=6.0). Its only runtime dependencies are js-yaml (YAML parsing/stringifying), kind-of (type-checking in to-file.js), section-matter (multi-section front-matter splitting), and strip-bom-string (BOM stripping before parsing). Tests run on Mocha (npm test), with fixtures under test/fixtures covering YAML, JSON, TOML, CoffeeScript, CSON, and custom-engine cases; a bower.json and browser field ({"fs": false}) reflect its age and its usability in bundled browser contexts.

Code Quality The test/ directory has 17 spec files (~900 lines) exercising core parsing, excerpts, custom delimiters/languages, Windows line endings, empty-input handling, Vinyl-file compatibility, and each built-in engine individually — a thorough surface for a library this size. Source files are small, single-purpose modules (parse.js, stringify.js, excerpt.js, defaults.js, engine.js) each under 60 lines with JSDoc comments on public functions and explicit TypeError/SyntaxError throws for invalid engine configuration, which keeps failure modes predictable. One notable code-quality caveat: the built-in javascript engine parses front-matter via eval(), which is a deliberate but security-relevant design choice callers should be aware of when accepting untrusted input.

API Design The primary API is a single function call — matter(str) — that returns a plain object, which is about as low-friction as a parsing library can get; matter.read(), matter.stringify(), and matter.test() extend the same mental model without introducing new concepts. TypeScript typings ship in the package itself (gray-matter.d.ts), and the README documents every option (excerpt, excerpt_separator, engines, delimiters, language) with runnable examples. The main friction point for new users is discovering the pluggable-engine mechanism for non-default languages (TOML/CoffeeScript require passing an external parser explicitly), but this is a reasonable tradeoff to keep the core dependency-free.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers