Render MDX with Next.JS
Libraries Needed
Library | Link |
---|---|
next-mdx-remote | https://www.npmjs.com/package/next-mdx-remote |
gray-matter | https://www.npmjs.com/package/gray-matter |
-
Create MDX files inside
/pages/posts
dir. -
Inside
getStaticProps
function inindex.tsx
file, we will read theposts
dir, and then read each file and extract all front-matter from each file using thegray-matter
library.
export async function getStaticProps() {// Read the directoryconst files = await fs.readdir(path.join("pages/posts"));// Read each file and extract frontMatterconst posts = await Promise.all(files.map(async (file) => {const mdWithMeta = await fs.readFile(path.join("pages/posts", file),"utf-8");const { data: frontMatter } = matter(mdWithMeta);return {frontMatter,slug: file.split(".")[0],};}));return {props: {posts,},};}
- Map the
posts
props in the UI like this.
{posts.map((post) => (<Link href={/post-[slug]} key={post.slug}><a style={{ display: "block" }}>{post.frontMatter.title}</a></Link>))}
- Create a
/pages/posts/[slug].tsx
file.
export async function getStaticPaths() {const files = fs.readdirSync(path.join("pages/posts"));// Generating slugsconst paths = files.map((filename) => {return {params: {slug: filename.replace(".mdx", ""),},};});return {paths,fallback: false,};}export const getStaticProps = async ({ params: { slug } }) => {const markdownWithMeta = await fs.readFileSync(path.join("pages/posts", slug + ".mdx"),"utf8"); // Read each fileconst { data: frontMatter, content } = matter(markdownWithMeta); // Extract front-matterconst mdxSource = await serialize(content); // Serialize contentreturn {props: {frontMatter,slug,mdxSource,},};};
💡
Note:
getStaticProps
(Static Generation) - Fetches data at build time
getStaticPaths
(Static Generation) - Specify dynamic routes to pre-render
pages based on data
getServerSideProps
(Server side rendering) - Fetches data on each request- Inside the JSX, use
MDXRemote
component to render mdx data.
import { serialize } from "next-mdx-remote/serialize";import { MDXRemote } from "next-mdx-remote";export default function Post(props: any) {return (<div><div><MDXRemote {...props.mdxSource} /></div></div>);}