Generated Data

The Contentlayer build process transforms content from your source(s) into data objects that can be consumed by your application.

This reference explains the location, shape, and structure of the generated data objects.

Generated Data Objects

Data objects are built into a three-tier system that works like this:

  1. JSON documents represent each individual transformed document.
  2. Document collections manifest for exporting collections of documents.
  3. All collections manifest for exporting every document collection, as well as a combined collection of all documents.

See below for details about each individual piece.

JSON Documents

Generated JSON documents contain the data that was transformed from the content source.

File Location

They are placed in a type-specific directory within Contentlayer's data directory, following this pattern:

.contentlayer/generated/[DOCTYPE]/[ID].json

For example, if the document type was called Page and the ID of one object was index.md, then the path to that file would be:

.contentlayer/generated/Page/index.md.json

Data Structure

The data structure is essentially a list of key-value pairs, minus a few generated and reserved properties (see below). Using the page example from above, if the index.md file had title and description fields, along with markdown content below the file's frontmatter, it might look like this:

{
  "title": "...",
  "description": "...",
  "body": {
    "raw": "...",
    "html": "..."
  },
  "_id": "index.mdx",
  "_raw": {
    "sourceFilePath": "index.mdx",
    "sourceFileName": "index.mdx",
    "sourceFileDir": ".",
    "contentType": "markdown",
    "flattenedPath": ""
  },
  "type": "Doc"
}

Field Shapes

The shape of data for each field is dependent on both the data source and field type. See individual source references for more information.

Generated Properties

There may be generated properties depending on your content source. For example, the local file source generates a property for the document type and for the body content.

These properties can be configured so that you control what become reserved words, meaning you can't have another field using these names. For example, using the default configuration for the local file source, you wouldn't be able to set fields named body or type.

Reserved Properties

The following properties are non-configurable and reserved for generated documents. They may not be used as field names.

  • _id: The ID value for the individual document.
  • _raw: a series of meta attributes about the document.

Document Collection Manifest

The document type manifest is responsible for importing and exporting document collections — an array of individual documents of the same type.

Here's an example of a Page document type with two documents in the collection:

import indexMdx from './Page/index.mdx.json'
import aboutMdx from './Page/about.mdx.json'

export const allPages = [indexMdx, aboutMdx]

Manifest Exports

The manifest exports a single object that is an array of all imported JSON documents.

The naming convention is to prepend the pluralized document type with "all". If Page is the document type name, then the exported object will be called allPages.

File Location

The file is located in the main Contentlayer data directory and named according to its main export. In the example above where the document type name is Page, the file will live at .contentlayer/generated/allPages.mjs.

All Documents Manifest

The main manifest file is responsible for exporting every document collection, as well as an allDocuments collection that is an array of every document across all document types.

It it colocated with the collection manifest in the .contentlayer/generated directory as index.mjs.

Continuing the Page example, a simple version of the file may look like this:

export { isType } from 'contentlayer/client'

export * from './allPages.mjs'
import { allPages } from './allPages.mjs'

export const allDocuments = [...allPages]

isType Utility

This file also exports an isType utility that could be conveniently imported from this file or directly from contentlayer/client.

This is most frequently used to determine if a particular document is of a particular type, taking into account your specific configuration.

Rather than using a filter like this (where you need to know the type field name):

allDocuments.filter((doc) => ['Page', 'Post'].includes(doc.type))

You can do this instead:

import { isType, allDocuments } from 'contentlayer/generated'

allDocuments.filter(isType(['Page', 'Post']))

Nested Objects

Nested objects are not written to individual documents, nor are they exported by any of the manifests.

Instead, nested objects are nested directly in the documents that are using them.


Was this article helpful to you?
Provide feedback

Last edited on March 31, 2023.
Edit this page