"use cache";
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
import { cwd } from "node:process";
import { compileMDX } from "next-mdx-remote/rsc";
import { type BlogFrontmatter } from "@/utils/types";
import { walkDir } from "@/utils/walk-dir";
export async function getArticles() {
const articlesPath = resolve(cwd(), "private/contents/news");
const filePaths = walkDir(articlesPath, ".mdx");
const articles = await Promise.all(
filePaths.map(async (filePath) => {
const source = readFileSync(filePath, "utf8");
const { frontmatter, content } = await compileMDX<BlogFrontmatter>({
source,
options: {
parseFrontmatter: true,
mdxOptions: { useDynamicImport: true },
},
});
return {
slug: frontmatter.slug,
title: frontmatter.title,
description: frontmatter.description,
author: frontmatter.author,
thumbnail: frontmatter.thumbnail,
rawDate: new Date(frontmatter.date),
content,
};
}),
);
const sorted = articles.sort(
(a, b) => b.rawDate.getTime() - a.rawDate.getTime(),
);
return sorted.map(({ rawDate, ...rest }) => ({
...rest,
date: rawDate.toLocaleDateString("en-US", {
month: "long",
day: "numeric",
year: "numeric",
}),
}));
}
export type Articles = Awaited<ReturnType<typeof getArticles>>;
#migrate to @next/mdx
1 messages · Page 1 of 1 (latest)
Hi @wind quiver. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
To migrate your code from using next-mdx-remote's compileMDX to the official @next/mdx approach in Next.js (App Router), you need to change how you handle MDX files and frontmatter. With @next/mdx, you don't use a runtime compile function like compileMDX. Instead, you import .mdx files directly, and you can export metadata (frontmatter) from those files using ES module exports.
Here's how you can migrate:
1. Configure @next/mdx in your project
Update your next.config.mjs to use @next/mdx and include .mdx in pageExtensions:
import createMDX from '@next/mdx'
/** @type {import('next').NextConfig} */
const nextConfig = {
pageExtensions: ['js', 'jsx', 'md', 'mdx', 'ts', 'tsx'],
}
const withMDX = createMDX({
// Add remark/rehype plugins here if needed
})
export default withMDX(nextConfig)
How to use markdown and MDX in Next.js
2. Add an mdx-components.tsx file
This is required for MDX to work with the App Router:
import type { MDXComponents } from 'mdx/types'
export function useMDXComponents(components: MDXComponents): MDXComponents {
return {
...components,
}
}
mdx-components.tsx file convention
3. Export frontmatter from your MDX files
Instead of parsing frontmatter at runtime, you can export metadata directly from your MDX files:
export const metadata = {
slug: "my-article",
title: "My Article",
description: "This is a description.",
author: "Author Name",
thumbnail: "/path/to/thumbnail.jpg",
date: "2024-06-01",
}
# My Article
Content goes here...
Frontmatter in MDX with @next/mdx
4. Import MDX files and their metadata
You can now import the MDX file and its metadata directly:
import Article, { metadata } from '@/private/contents/news/my-article.mdx'
export async function getArticles() {
// You can use dynamic imports or require.context to import all MDX files
// For each, access the metadata export
return [
{
slug: metadata.slug,
title: metadata.title,
description: metadata.description,
author: metadata.author,
thumbnail: metadata.thumbnail,
rawDate: new Date(metadata.date),
content: <Article />,
},
// ...repeat for other articles
]
}
Referencing metadata from MDX files
5. Notes
- You no longer need to use
compileMDXor parse frontmatter at runtime. - If you want to programmatically import all MDX files, you may need to use dynamic imports or a custom script to gather all MDX modules and their metadata.
- If you still want to use YAML frontmatter, you can use remark plugins like
remark-frontmatterandremark-mdx-frontmatterin your MDX config, but the recommended approach is to use ES module exports for metadata.
Summary:
With @next/mdx, you import MDX files and their metadata directly, removing the need for runtime compilation and frontmatter parsing. Update your MDX files to export metadata, and import them in your code as shown above.
How to use markdown and MDX in Next.js