Enabling MDX Support in Contentlayer Articles - Modern Next.js Blog Series #08
- Published on
This article is also published on it 邦幫忙 2022 iThome Ironman Competition
TL;DR
This is the 8th article in the "Modern Blog 30 Days" series. In the previous article, we implemented the article detail page in Markdown format. In this article, we will extend it to support the MDX format, which allows any React component to be inserted within Markdown, enhancing the flexibility of the article content!
The result screenshot is as follows:
The modified code for this article is as follows:
Enabling MDX Format Support in Contentlayer
Modify the contentlayer.config.ts file
Change the filePathPattern filename and add a contentType:
Copied!import { defineDocumentType, makeSource } from "./src/lib/contentLayerAdapter"; export const Post = defineDocumentType(() => ({ name: "Post", // Update filePathPattern from *.md to *.mdx, filePathPattern: `content/posts/**/*.mdx`, // and add the following line for contentType contentType: "mdx", fields: { title: { type: "string", required: true, }, description: { type: "string", required: true, }, slug: { type: "string", required: true, }, date: { type: "date", required: true, }, }, computedFields: { path: { type: "string", resolve: (post) => `/posts/${post.slug}`, }, }, })); export default makeSource({ contentDirPath: "content", documentTypes: [Post], });
Modify the article detail page's src/pages/posts/[slug].tsx file
Replace the div that renders HTML with <MDXContent />
:
Copied!import { format, parseISO } from "date-fns"; import type { GetStaticPaths, GetStaticProps, NextPage } from "next"; import Head from "next/head"; // Add the following line import { useMDXComponent } from "next-contentlayer/hooks"; import { allPosts, Post } from "@/lib/contentLayerAdapter"; import styles from "@/styles/Home.module.css"; export const getStaticPaths: GetStaticPaths = () => { const paths = allPosts.map((post) => post.path); return { paths, fallback: false, }; }; export const getStaticProps: GetStaticProps<Props> = ({ params }) => { const post = allPosts.find((post) => post.slug === params?.slug); if (!post) { return { notFound: true, }; } return { props: { post, }, }; }; type Props = { post: Post; }; const PostPage: NextPage<Props> = ({ post }) => { // Also add the following line const MDXContent = useMDXComponent(post.body.code); return ( <div className={styles.container}> <Head> <title>{post.title}</title> <meta name="description" content={post.description} /> <link rel="icon" href="/favicon.ico" /> </Head> <main className={styles.main}> <h1 className={styles.title}>{post.title}</h1> <time dateTime={post.date}> {format(parseISO(post.date), "LLLL d, yyyy")} </time> // Replace the div that renders HTML with <MDXContent /> // <div dangerouslySetInnerHTML={{ __html: post.body.html }} /> <MDXContent /> </main> </div> ); }; export default PostPage;
Change all article file extensions from .md to .mdx
Change all article file extensions under content/posts/
to .mdx
This completes the support for the MDX format!
Add Any React Component and Insert It Into an MDX Article
Next, let's test inserting a React component into the Markdown content of an MDX article.
Add src/components/CustomInput.tsx
Copied!const CustomInput = () => { return ( <div> <p>Hello</p> <input type="text" /> </div> ); }; export default CustomInput;
Modify content/posts/20220831-markdown-demo.mdx
Insert the CustomInput component:
Copied!--- title: Markdown demo description: This is a demo of Markdown slug: markdown-demo date: 2022-08-31 type: Post --- import CustomInput from "../../src/components/CustomInput"; ## H2 title ### H3 title Some content with [link](https://www.google.com) <CustomInput />
Results
Done! Using pnpm dev
and entering an article with customized MDX components, you will see the MDX component displayed on the screen.
The URL will look like this:
http://localhost:3000/posts/markdown-demo
The screenshot below shows an added text input box made with React:
The modified code for this article is as follows:
Next Article
Congratulations! So far, we can also write articles in MDX format! This allows us to insert any custom component made with React anywhere, making the content of articles more flexible!
But the entire blog is still quite unattractive, so let's start beautifying it next!
We will use Tailwind CSS, a popular CSS Framework these days. In the next article, let's install and use it!