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.jsimport { 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