Introduction#

GitHub this note shows how to use ContentLayer to transform mdx (markdown) files into react components

  • Setup Contentlayer with React App router
  • Create a simple blog with mdx files

Setup Project#

First let create a new next.js project

npx create-next-app@latest

Then, let setup contentlayer

npm install contentlayer next-contentlayer

Project Structure

|--app
|--global.css
|--layout.css
|--page.tsx
|--blog
|--page.tsx
|--posts
|--post-1.mdx
|--post-2.mdx
|--contentlayer
|--tailwind.config.js
|--package.json
|--next.config.js
|--contentlayer.config.js

Setup ContentLayer#

Create and update the contentlayer.config.js as below

// contentlayer.config.js
import { defineDocumentType, makeSource } from 'contentlayer/source-files'
export const Post = defineDocumentType(() => ({
name: 'Post',
filePathPattern: `**/*.mdx`,
contentType: 'mdx',
fields: {
title: {
type: 'string',
description: 'The title of the post',
required: true
},
description: {
type: 'string'
},
date: {
type: 'date',
description: 'The date of the post',
required: true
}
},
computedFields: {
url: {
type: 'string',
resolve: post => `/posts/${post._raw.flattenedPath}`
}
}
}))
export default makeSource({
contentDirPath: 'posts',
documentTypes: [Post]
})

Update the next.config.js with baseUrl as

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

Use Contentlayer#

Now we can use contentlayer to transform the mdx file into json by npm run build and check the generated things in .contentlayer

npm run build

Then just pass the generated content in to the MDXComponent and provide styles via components as above section

'use client'
import { allPosts } from '.contentlayer/generated'
import { useMDXComponent } from 'next-contentlayer/hooks'
const getPost = async () => {
const post = allPosts[0]
return post
}
const mdxComponents = {
// h2: ({ props }: any) => (
// <h2 className="prose text-3xl" apply="mdx.h2" {...props} />
// ),
}
export const Post = async ({ params }: any) => {
const post = allPosts[0]
const MDXContent = useMDXComponent(post.body.code)
return (
<div className="dark:text-white dark:bg-slate-800 min-h-screen">
<div className="max-w-4xl mx-auto px-7 prose-h2:text-lg prose dark:prose-invert">
<MDXContent components={mdxComponents}></MDXContent>
</div>
</div>
)
}
export default Post

Reference#