Field definitions specify the expected shape and behavior of your content. They tell Contentlayer how to parse each property in a content object into data that your application can use.

All fields share the same basic options, while other options are available depending on the type of field. See below for more information.

Shared Options

The name of the field is defined as the key of the definition object (see example). All field definitions have the following options available:

  • type (string, required): The name of the type.
  • required (boolean, default: false): Whether to validate the existence of the field when parsing content.
  • description (string): A short description to editors how the field is to be used.

The field type then dictates all other available options. Look below for more information.

Example:

This is a type definition that defines a single field with the name title and of type string that is not required.

defineDocumentType(() => ({
  // ...
  fields: {
    title: { type: 'string' },
  },
}))

boolean

A boolean field can have either a true or false value.

Options:

  • default (string): A default value for the field if it is empty.

Example:

defineDocumentType(() => ({
  // ...
  fields: {
    isActive: {
      type: 'boolean',
      default: false,
    },
  },
}))

date

Date fields return an instance of Date.

Options:

  • default (string): A default value for the field if it is empty.

Example:

defineDocumentType(() => ({
  // ...
  fields: {
    publishAt: {
      type: 'date',
    },
  },
}))

enum

Enums are a specialized string field, where the string must match one of the defined options.

Options:

  • default (string): A default value for the field if it is empty.
  • options (string[]): An array of acceptable options for the field.

Example:

defineDocumentType(() => ({
  // ...
  fields: {
    theme: {
      type: 'enum',
      options: ['light', 'dark'],
      default: 'dark',
    },
  },
}))

json

JSON fields are open-ended and can store data of any valid JSON structure.

Options:

  • default (string): A default value for the field if it is empty.

Example:

defineDocumentType(() => ({
  // ...
  fields: {
    options: {
      type: 'json',
    },
  },
}))

list

A list is an array of values that can be either strings or nested objects.

Options:

Example:

defineDocumentType(() => ({
  // ...
  fields: {
    tags: {
      type: 'list',
      of: { type: 'string' },
    },
  },
}))

The default list type expects an array of strings, like this:

---
tags:
  - My First Tag
  - Another Tag
---

Nested Objects List

To specify a list of nested objects, use the of option. Here's an example of the definition:

const Tag = defineNestedType(() => ({
  name: 'Tag',
  fields: {
    title: { type: 'string', required: true },
  },
}))

defineDocumentType(() => ({
  // ...
  fields: {
    // ...
    tags: {
      type: 'list',
      of: Tag,
    },
  },
}))

Now you could use the nested objects in your content files.

---
tags:
  - title: My First Tag
  - title: Another Tag
---

markdown

Given a markdown string, this creates an object containing the following properties:

  • raw: The input string from the content file.
  • html: Output HTML to use in your components.

Options:

  • default (string): A default value for the field if it is empty.

Example:

defineDocumentType(() => ({
  // ...
  fields: {
    // ...
    description: {
      type: 'markdown',
    },
  },
}))

If your content file has the following:

---
description: Hello world
---

The result would be shaped like this:

{
  "description": {
    "raw": "Hello world",
    "html": "<p>Hello world</p>"
  }
}

mdx

Given an MDX string, this creates an object containing the following properties:

  • raw: The input string from the content file.
  • code: Output JavaScript code that can be loaded into your components.

Options:

  • default (string): A default value for the field if it is empty.

Example:

defineDocumentType(() => ({
  // ...
  fields: {
    description: {
      type: 'mdx',
    },
  },
}))

If your content file has the following:

---
description: Hello world
---

The result would be shaped like this:

{
  "description": {
    "raw": "Hello world",
    "code": "var Component=(()=>{var m=Object.create ..."
  }
}

nested

A nested field is a directly-embedded object that must match the shape of one or more types declared with the of option.

Options:

  • default (string): A default value for the field if it is empty.
  • of (NestedType or [NestedType]): A nested document type definition. Learn more about nested types.

Example:

const Category = defineNestedType(() => ({
  name: 'Category',
  fields: {
    title: { type: 'string', required: true },
  },
}))

defineDocumentType(() => ({
  // ...
  fields: {
    category: {
      type: 'nested',
      of: Category,
    },
  },
}))

The shape of the content would then look like this:

---
category:
  title: Sportsball
---

This would produce a document where category was an embedded object with a title property.

{
  "category": {
    "title": "Sportsball"
  }
}

Polymorphic Nested Objects

You can specify multiple nested field types by passing an array of nested types to the of option.

const Tag = defineNestedType(() => ({
  name: 'Tag',
  fields: {
    title: { type: 'string', required: true },
  },
}))

const Category = defineNestedType(() => ({
  name: 'Category',
  fields: {
    title: { type: 'string', required: true },
  },
}))

defineDocumentType(() => ({
  // ...
  fields: {
    category: {
      type: 'nested',
      of: [Category, Tag],
    },
  },
}))

This requires that you specify the type of the object in your content using the type property.

---
category:
  type: Tag
  title: Hello World
---

number

Options:

  • default (string): A default value for the field if it is empty.

Example:

defineDocumentType(() => ({
  // ...
  fields: {
    count: {
      type: 'number',
      default: 0,
    },
  },
}))

reference

A path to another document file of a specific types. The path should be relative to the contentDirPath option passed to makeSource.

References are not currently transformed or embedded. They are simply passed through as strings.

Options:

  • default (string): A default value for the field if it is empty.
  • of (DocumentType): A document type definition.

Example:

const Category = defineNestedType(() => ({
  name: 'Category',
  filePathPattern: 'categories/*.md',
  fields: {
    title: { type: 'string', required: true },
  },
}))

defineDocumentType(() => ({
  // ...
  fields: {
    category: {
      type: 'reference',
      of: Category,
    },
  },
}))

Your content file would then point the referenced doc, using a path relative to the contentDirPath option passed to makeSource.

---
category: categories/hello-world.md
---

This is presented as is in the output document at this time.

{
  "category": "categories/hello-world.md"
}

string

Options:

  • default (string): A default value for the field if it is empty.

Example:

defineDocumentType(() => ({
  // ...
  fields: {
    title: {
      type: 'string',
      required: true,
    },
  },
}))

Was this article helpful to you?
Provide feedback

Last edited on May 24, 2023.
Edit this page