How to set up Content Layer in a Next.js app with the App Router

VivekVivek
3 min read

Sure, here's the corrected markdown code with the necessary formatting fixes:


Here are all the steps involved in integrating Content Layer with a NextJs application using the app router, along with code examples:

Step 1: Setting Up a Next.js Project

First, make sure that you have set up a properly functioning project in Next.js. The following way is how one sets up a Next.js project:

npx create-next-app@latest my-nextjs-app
cd my-nextjs-app

Step 2: Installing Content Layer

Install Content Layer and dependency modules with:

npm install contentlayer next-contentlayer

Step 3: Setting up Content Layer

Create contentlayer.config.js in your project root:

// contentlayer.config.js

import { defineDocumentType, makeSource } from 'contentlayer/source-files'

const BlogPost = defineDocumentType(() => ({
  name: 'BlogPost',
  filePathPattern: `blog/*.md`,
  fields: {
    title: { type: 'string', required: true },
    date: { type: 'date', required: true },
    content: { type: 'string', required: true },
  },
}))

export default makeSource({
  contentDirPath: 'content',
  documentTypes: [BlogPost],
})

Step 4: Create Content Directory and Markdown Files

Create a content directory in the root of your project. Inside the content directory, create a blog directory and add a sample Markdown file:

my-nextjs-app/
├── content/
│   └── blog/
│       └── first-post.md

Example first-post.md:

---
title: "First Post"
date: "2024-07-05"
---

This is the content of the first blog post.

Step 5: Update next.config.js

Update next.config.js to include the Content Layer plugin:

// next.config.js

const { withContentlayer } = require('next-contentlayer')

module.exports = withContentlayer({
  reactStrictMode: true,
})

Step 6: Create Blog Components

With your data ready, it's time to create the UI for it. Create a pages/blog directory and add an [slug].js to handle individual blog posts:

// pages/blog/[slug].js

import { allBlogPosts } from 'contentlayer/generated'
import { useMDXComponent } from 'next-contentlayer/hooks'
import { useRouter } from 'next/router'

export async function getStaticPaths() {
  return {
    paths: allBlogPosts.map(post => ({ params: { slug: post._id.replace(/\.md$/, '') } })),
    fallback: false,
  }
}

export async function getStaticProps({ params }) {
  const post = allBlogPosts.find(post => post._id.replace(/\.md$/, '') === params.slug)
  return { props: { post } }
}

export default function BlogPost({ post }) {
  const MDXContent = useMDXComponent(post.body.code)
  return (
    <article>
      <h1>{post.title}</h1>
      <p>{post.date}</p>
      <MDXContent />
    </article>
  )
}

Now, create an index.js inside pages/blog to show all the blog posts in a list:

// pages/blog/index.js

import Link from 'next/link'
import { allBlogPosts } from 'contentlayer/generated'

export async function getStaticProps() {
  return {
    props: {
      posts: allBlogPosts,
    },
  }
}

export default function Blog({ posts }) {
  return (
    <div>
      <h1>Blog</h1>
      <ul>
        {posts.map(post => (
          <li key={post._id}>
            <Link href={`/blog/${post._id.replace(/\.md$/, '')}`}>
              <a>{post.title}</a>
            </Link>
          </li>
        ))}
      </ul>
    </div>
  )
}

Step 7: Start Your Application

Start your application to see the blog already working:

npm run dev

Now, open http://localhost:3000/blog and see a list of your blog posts. Click on one to see its content.


These are the steps I personally followed for setting up the bog of my AI Interviewing app project, Recroo AI. You may read the article here about why we decided to use Content Layer for the blog section of recrooai.com

10
Subscribe to my newsletter

Read articles from Vivek directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Vivek
Vivek

Curious Full Stack Developer wanting to try hands on ⌨️ new technologies and frameworks. More leaning towards React these days - Next, Blitz, Remix 👨🏻‍💻