# gatsby-transformer-remark

> Gatsby transformer plugin for Markdown using the Remark library and ecosystem

Latest version **6.16.0** (published 2026-01-26) · MIT license · 0 weekly downloads

## Install

```sh
npm install gatsby-transformer-remark
pnpm add gatsby-transformer-remark
yarn add gatsby-transformer-remark
bun add gatsby-transformer-remark
```

## Health

**Score 63/100 (C)** — status: stable.

Positive: has types package; no vulnerabilities; high maintenance score; popular repo; extremely popular.

Warnings: low downloads; no esm support.

## Facts

| | |
|---|---|
| Version | 6.16.0 |
| Published | 2026-01-26 |
| First published | 2017-04-18 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | separate (@types/gatsby-transformer-remark) |
| Module format | CommonJS |
| Node | >=18.0.0 <26 |
| Dependencies | 22 |
| Unpacked size | 115.9 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 55939 |
| Author | Kyle Mathews |
| Maintainers | pieh, kathmbeck, serhalp-netlify, mlgualtieri-gatsby, fk, tylerbarnes, daniellewgatsby |
| Keywords | gatsby, gatsby-plugin, markdown, remark |

## Links

- npm: https://www.npmjs.com/package/gatsby-transformer-remark
- Repository: https://github.com/gatsbyjs/gatsby
- Homepage: https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-transformer-remark#readme
- Issues: https://github.com/gatsbyjs/gatsby/issues
- npm.io page: https://npm.io/package/gatsby-transformer-remark

## Dependencies (22)

- [lodash](https://npm.io/package/lodash.md) ^4.17.21
- [remark](https://npm.io/package/remark.md) ^13.0.0
- [unified](https://npm.io/package/unified.md) ^9.2.2
- [remark-gfm](https://npm.io/package/remark-gfm.md) ^1.0.0
- [gray-matter](https://npm.io/package/gray-matter.md) ^4.0.3
- [remark-parse](https://npm.io/package/remark-parse.md) ^9.0.0
- [hast-util-raw](https://npm.io/package/hast-util-raw.md) ^6.1.0
- [remark-retext](https://npm.io/package/remark-retext.md) ^4.0.0
- [sanitize-html](https://npm.io/package/sanitize-html.md) ^2.11.0
- [@babel/runtime](https://npm.io/package/@babel/runtime.md) ^7.20.13
- [mdast-util-toc](https://npm.io/package/mdast-util-toc.md) ^5.1.0
- [retext-english](https://npm.io/package/retext-english.md) ^3.0.4
- [remark-footnotes](https://npm.io/package/remark-footnotes.md) ^3.0.0
- [remark-stringify](https://npm.io/package/remark-stringify.md) ^9.0.1
- [unist-util-visit](https://npm.io/package/unist-util-visit.md) ^2.0.3
- [gatsby-core-utils](https://npm.io/package/gatsby-core-utils.md) ^4.16.0
- [hast-util-to-html](https://npm.io/package/hast-util-to-html.md) ^7.1.3
- [underscore.string](https://npm.io/package/underscore.string.md) ^3.3.6
- [unist-util-select](https://npm.io/package/unist-util-select.md) ^3.0.4
- [mdast-util-to-hast](https://npm.io/package/mdast-util-to-hast.md) ^10.2.0
- [mdast-util-to-string](https://npm.io/package/mdast-util-to-string.md) ^2.0.0
- [unist-util-remove-position](https://npm.io/package/unist-util-remove-position.md) ^3.0.0

## Alternatives

- [@mdxeditor/editor](https://npm.io/package/@mdxeditor/editor.md) — 962.4K weekly downloads
- [mmdb-lib](https://npm.io/package/mmdb-lib.md) — 680.9K weekly downloads
- [playcanvas](https://npm.io/package/playcanvas.md) — 36.2K weekly downloads
- [@glw907/cairn-cms](https://npm.io/package/@glw907/cairn-cms.md) — 967 weekly downloads
- [markdown-to-confluence](https://npm.io/package/markdown-to-confluence.md) — 103 weekly downloads

## Recent versions

- 6.16.0 (latest) — 2026-01-26
- 6.17.0-next.0 (next) — 2025-11-27
- 6.17.0-react19.1 (react19) — 2025-11-26
- 6.13.0-alpha-alt-image-cdn.44 (alt-image-cdn) — 2023-11-03
- 6.9.0-image-cdn-configurable.4 (image-cdn-configurable) — 2023-04-11
- 5.25.1 (latest-v4) — 2022-12-20
- 4.12.0 (latest-v3) — 2022-12-07
- 6.0.0-alpha-drupal-proxyurl.14 (drupal-proxyurl) — 2022-11-22
- 5.24.1-alpha-wordpress-image-err.27 (wordpress-image-err) — 2022-11-09
- 5.14.0-alpha-transformer-json.26 (alpha-transformer-json) — 2022-10-12
- 6.0.0-alpha-v5.d20221012t101120.57 (alpha-v5) — 2022-10-12
- 5.25.0-alpha-image-cdn-pathprefix.48 (image-cdn-pathprefix) — 2022-10-07
- 5.23.0-alpha-image-cdn-enc.24 (image-cdn-enc) — 2022-09-16
- 5.23.0-alpha-a5-peer.54 (alpha-a5-peer) — 2022-09-14
- 5.23.0-alpha-preview-gh-api.26 (preview-gh-api) — 2022-09-08
- … 725 more at https://npm.io/package/gatsby-transformer-remark/versions

## README

# gatsby-transformer-remark

Parses Markdown files using [remark](http://remark.js.org/).

## Install

Install the plugin to your site:

```shell
npm install gatsby-transformer-remark
```

Add it to your `gatsby-config`:

```js:title=gatsby-config.js
module.exports = {
  plugins: [
    {
      resolve: `gatsby-transformer-remark`,
      options: {},
    },
  ],
}
```

## Options

```js:title=gatsby-config.js
module.exports = {
  plugins: [
    {
      resolve: `gatsby-transformer-remark`,
      options: {
        // Footnotes mode (default: true)
        footnotes: true,
        // GitHub Flavored Markdown mode (default: true)
        gfm: true,
        // Add your gatsby-remark-* plugins here
        plugins: [],
        // Enable JS for https://github.com/jonschlinkert/gray-matter#optionsengines (default: false)
        // It's not advised to set this to "true" and this option will likely be removed in the future
        jsFrontmatterEngine: false,
      },
    },
  ],
}
```

The following parts of `options` enable the `remark-footnotes` and `remark-gfm`
plugins:

- `options.footnotes`
- `options.gfm`

A full explanation of how to use markdown in Gatsby can be found here: [Adding Markdown Pages](https://www.gatsbyjs.com/docs/how-to/routing/adding-markdown-pages/)

There are many `gatsby-remark-*` plugins which you can install to customize how Markdown is processed. Check out the [source code for using-remark](https://github.com/gatsbyjs/gatsby/tree/master/examples/using-remark) as an example.

### `gray-matter` options

`gatsby-transformer-remark` uses [gray-matter](https://github.com/jonschlinkert/gray-matter) to parse Markdown frontmatter, so you can specify any of the options mentioned [in its README](https://github.com/jonschlinkert/gray-matter#options) in the `options` key of the plugin.

**Example: Excerpts**

If you don't want to use `pruneLength` for excerpts but a custom separator, you can specify an `excerpt_separator`:

```js:title=gatsby-config.js
module.exports = {
  plugins: [
    {
      resolve: `gatsby-transformer-remark`,
      options: {
        excerpt_separator: `<!-- end -->`
      }
    },
  ],
}
```

## Parsing algorithm

It recognizes files with the following extensions as Markdown:

- `md`
- `markdown`

Each Markdown file is parsed into a node of type `MarkdownRemark`.

All frontmatter fields are converted into GraphQL fields through [inference](https://www.gatsbyjs.com/docs/glossary/#inference).

This plugin adds additional fields to the `MarkdownRemark` GraphQL type
including `html`, `excerpt`, `headings`, etc. Other Gatsby plugins can also add
additional fields.

## How to query

A sample GraphQL query to get MarkdownRemark nodes:

```graphql
{
  allMarkdownRemark {
    edges {
      node {
        html
        headings {
          depth
          value
        }
        frontmatter {
          # Assumes you're using title in your frontmatter.
          title
        }
      }
    }
  }
}
```

### Getting table of contents

Using the following GraphQL query you'll be able to get the table of contents

```graphql
{
  allMarkdownRemark {
    edges {
      node {
        html
        tableOfContents
      }
    }
  }
}
```

### Configuring the `tableOfContents`

By default, `absolute` is set to `false`, generating a relative path. If you'd like to generate an absolute path, pass `absolute: true`. In that case, be sure to pass the `pathToSlugField` parameter, often `fields.slug`, to create absolute URLs. **Note** that providing a non-existent field will cause the result to be `null`. To alter the default values for `tableOfContents` generation, include values for `heading` (string) and/or `maxDepth` (number 1 to 6) in GraphQL query. If a value for `heading` is given, the first heading that matches will be omitted and the ToC is generated from the next heading of the same depth onwards. Value for `maxDepth` sets the maximum depth of the toc (i.e. if a maxDepth of 3 is set, only h1 to h3 headings will appear in the toc).

```graphql
{
  allMarkdownRemark {
    edges {
      node {
        html
        tableOfContents(
          absolute: true
          pathToSlugField: "frontmatter.path"
          heading: "only show toc from this heading onwards"
          maxDepth: 2
        )
        frontmatter {
          # Assumes you're using path in your frontmatter.
          path
        }
      }
    }
  }
}
```

To pass default options to the plugin generating the `tableOfContents`, configure it in `gatsby-config.js` as shown below. The options shown below are the defaults used by the plugin.

```js:title=gatsby-config.js
module.exports = {
  plugins: [
    {
      resolve: `gatsby-transformer-remark`,
      options: {
        tableOfContents: {
          heading: null,
          maxDepth: 6,
        },
      },
    },
  ],
}
```

### Excerpts

#### Length

By default, excerpts have a maximum length of 140 characters. You can change the default using the `pruneLength` argument. For example, if you need 500 characters, you can specify:

```graphql
{
  allMarkdownRemark {
    edges {
      node {
        html
        excerpt(pruneLength: 500)
      }
    }
  }
}
```

#### Format

By default, Gatsby will return excerpts as plain text. This might be useful for populating [opengraph](https://en.wikipedia.org/wiki/Facebook_Platform#Open_Graph_protocol) HTML tags for SEO reasons. You can also explicitly specify a `PLAIN` format like so:

```graphql
{
  allMarkdownRemark {
    edges {
      node {
        excerpt(format: PLAIN)
      }
    }
  }
}
```

It's also possible to ask Gatsby to return excerpts formatted as HTML. You might use this if you have a blog post whose excerpt contains markdown content -- e.g. header, link, etc. -- and you want these links to render as HTML.

```graphql
{
  allMarkdownRemark {
    edges {
      node {
        excerpt(format: HTML)
      }
    }
  }
}
```

You can also get excerpts in Markdown format.

```graphql
{
  allMarkdownRemark {
    edges {
      node {
        excerpt(format: MARKDOWN)
      }
    }
  }
}
```

Any file that does not have the given `excerpt_separator` will fall back to the default pruning method.

## Troubleshooting

### Excerpts for non-latin languages

By default, `excerpt` uses `underscore.string/prune` which doesn't handle non-latin characters ([https://github.com/epeli/underscore.string/issues/418](https://github.com/epeli/underscore.string/issues/418)).

If that is the case, you can set `truncate` option on `excerpt` field, like:

```graphql
{
  markdownRemark {
    excerpt(truncate: true)
  }
}
```

### Excerpts for HTML embedded in Markdown files

If your Markdown file contains HTML, `excerpt` will not return a value.

In that case, you can set an `excerpt_separator` in the `gatsby-config`:

```js:title=gatsby-config.js
module.exports = {
  plugins: [
    {
      resolve: `gatsby-transformer-remark`,
      options: {
        excerpt_separator: `<!-- endexcerpt -->`
      },
    },
  ],
}
```

Edit your Markdown files to include that HTML tag after the text you'd like to appear in the excerpt:

```markdown
---
title: "my little pony"
date: "2017-09-18T23:19:51.246Z"
---

<p>Where oh where is that pony?</p>
<!-- endexcerpt -->
<p>Is he in the stable or down by the stream?</p>
```

Then specify `MARKDOWN` as the format in your GraphQL query:

```graphql
{
  markdownRemark {
    excerpt(format: MARKDOWN)
  }
}
```

---
_Source: https://npm.io/package/gatsby-transformer-remark · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
