Robin.te.Hofstee

Mastering Contentlayer2

Robin te Hofstee3 min readViews0
Mastering Contentlayer2

An advanced guide to transforming content into type-safe data using Contentlayer2

Understanding Contentlayer2

Contentlayer2 is a powerful content SDK that validates and transforms your local or remote content into type-safe JSON data. [cite_start]It acts as a bridge between your raw files and your application code.

Why Move to Contentlayer2?

While traditional CMS solutions can be slow or lack type safety[cite: 2], Contentlayer2 provides a modern developer experience:

  • Native TypeScript Integration: Every piece of content is automatically assigned a type based on your schema.
  • High Performance: It utilizes incremental builds and caching to ensure your development server remains fast even with hundreds of files.
  • Live Reloading: Changes to your .md or .mdx files are instantly reflected in your browser without a manual refresh.

Technical Workflow

Contentlayer2 processes your files through a three-step pipeline:

  1. Scanning: It identifies files matching your filePathPattern.
  2. Validation: It ensures every file contains the required frontmatter fields defined in your schema.
  3. Generation: It outputs a .contentlayer directory containing JSON data and TypeScript definitions.

Accessing Your Data

Once generated, you can import your content directly into your components:

import { allPosts, Post } from 'contentlayer/generated'
 
// Use-case: Generating a list of blog posts 
export const PostList = () => {
  return (
    <ul>
      {allPosts.map((post: Post) => (
       <li key={post._id}>{post.title}</li>
       ))}
    </ul>
  )
}
 

Advanced Schema Configuration

In Contentlayer2, your contentlayer.config.ts acts as the single source of truth for your data.

import { defineDocumentType, makeSource } from 'contentlayer2/source-files'
 
export const Post = defineDocumentType(() => ({
  name: 'Post',
  filePathPattern: `posts/**/*.mdx`,
  contentType: 'mdx',
  fields: {
    title: { type: 'string', required: true },
    date: { type: 'date', required: true },
    author: { type: 'string', required: false },
  },
  computedFields: {
    url: {
      type: 'string',
      resolve: (post) => `/blog/${post._raw.flattenedPath}`,
    },
  },
}))
 
export default makeSource({ contentDirPath: 'content', documentTypes: [Post] })
 

Conclusion

Contentlayer2 bridges the gap between static content and dynamic code. By enforcing a strict schema, you eliminate runtime errors related to missing content and enjoy a seamless development workflow.

Share this post
Robin te Hofstee

Written by Robin te Hofstee

Technology enthusiast with a deep love for programming. Sharing practical guides on React, Next.js, Linux and self-hosting.