Welcome to this comprehensive guide on building a modern page with MDX and Next.js! In this tutorial, we'll explore how to create a powerful, type-safe, and beautifully styled page using the latest web technologies. Whether you're a seasoned developer or just starting with Next.js, this guide will walk you through everything you need to know to set up a production-ready markdown page.
What You'll Learn
Setting up a Next.js project with MDX support
Understanding the project structure and file organization
The [slug] folder name uses Next.js dynamic routing
This is where we'll render our MDX pages
src/contents/posts/:
This is where all your MDX page files will live
Each .mdx file in this directory represents a page
The filename (without .mdx) will be used as the URL slug
For example, example-post.mdx will be accessible at /post/example-post
Important Note: The contents folder and its structure is not created automatically by Next.js. You'll need to create these folders manually:
bash
mkdir -p src/contents/posts
This is where you'll store all your MDX blog post files.
3. Import Required Modules
tsx
//post/[slug]/page.tsximport path from "path";import {promises as fs} from "fs";import { compileMDX } from "next-mdx-remote/rsc";import { notFound } from "next/navigation";
Let's understand what each import does:
path: Node.js built-in module which will be used to read the file path of our MDX files
fs: Node.js file system module (using promises version) to read MDX files from the filesystem
compileMDX: Core function from next-mdx-remote that compiles MDX content into React components and also parses the frontmatter
notFound: Next.js utility to show 404 page when a post isn't found
What is Frontmatter?
Frontmatter is metadata at the top of your MDX files, enclosed between --- markers. It's commonly used to store information about your page like title, date, author, etc. Here's an example:
mdx
---title: "My First Post"date: "2024-03-20"author: "John Doe"tags: ["Next.js", "MDX", "Web Development"]---# My First PostThis is the actual content of my post...
When this MDX file is compiled, the frontmatter will be available as a JavaScript object:
js
{ title: "My First Post", date: "2024-03-20", author: "John Doe", tags: ["Next.js", "MDX", "Web Development"]}
4. Post Component
tsx
//post/[slug]/page.tsxexport default async function Post({ params }: { params: Promise<{ slug: string }> }) { try { const resolvedParams = await params; if (!resolvedParams || !resolvedParams.slug) { notFound(); } const { slug } = resolvedParams; // Read the MDX file with the help of path and fs module const fileContent = await fs.readFile( path.join(process.cwd(), "src/contents/posts", `${slug}.mdx`), "utf-8" ); // Compile the MDX file with the help of compileMDX function const { content, frontmatter } = await compileMDX({ source: fileContent, options: { parseFrontmatter: true, }, }); if (!fileContent) { notFound(); } return ( <article className="prose"> <h1>{frontmatter.title}</h1> {content} </article> ); } catch (error) { console.error(error); //You can add toast here notFound(); }}
5. Styling with Tailwind Typography
But wait! Something's not quite right. Our pages look plain and unformatted. The markdown content isn't styled properly, and it doesn't have that polished, professional look we want. That's where Tailwind Typography comes to the rescue!
Why Are Styles Reset?
By default, Tailwind CSS resets all default browser styles to ensure consistency across different browsers. This is great for building custom UIs, but it means our markdown content loses its default styling. That's why our pages initially look unstyled - we need to explicitly tell Tailwind how to style our markdown content.
What is Tailwind Typography?
Tailwind Typography is a plugin that provides beautiful typographic defaults to any vanilla HTML. It's perfect for styling markdown content because it:
Automatically styles all your markdown elements (headings, lists, blockquotes, etc.)
Let's walk through the complete process of creating and viewing a page:
Create the Page
bash
# Create the posts directory if it doesn't existmkdir -p src/contents/posts# Create your MDX filetouch src/contents/posts/my-first-post.mdx
Write Your Content
mdx
// contents/posts/my-first-post.mdx---title: "Hello, MDX World!"date: "2024-03-20"author: "Your Name"tags: ["MDX", "Next.js", "Tailwind"]---# Welcome to My First MDX PostThis is a sample post to demonstrate how MDX and Tailwind Typography work together.## Features We're Using- **Markdown** for content- **MDX** for React components- **Tailwind Typography** for styling### Code ExampleHere's a simple React component we can use in our MDX:```tsxfunction Greeting({ name }: { name: string }) { return <h2>Hello, {name}!</h2>}```### Blockquotes> This is a blockquote. It's styled automatically by Tailwind Typography!### Lists1. First item2. Second item3. Third item- Unordered list- With multiple items- And proper spacing### Tables| Feature | Description ||---------|-------------|| MDX | Markdown with JSX || Typography | Beautiful text styling || Dark Mode | Automatic dark mode support |
View Your Post
Start your development server: npm run dev
Visit: http://localhost:3000/post/my-first-post
What's Happening Behind the Scenes
When you visit /post/my-first-post:
Next.js matches the URL to your [slug] dynamic route
The Post component reads the MDX file
next-mdx-remote compiles the MDX content
Tailwind Typography styles the content with the prose class
Common Issues and Solutions
Post not found? Check if:
The file exists in src/contents/posts
The filename matches the URL slug
The file extension is .mdx
Styles not applying? Verify:
The prose class is added to your article element
Tailwind Typography is installed and configured
Your tailwind.config.ts includes the typography plugin
Your global.css include all three base, components, utilities of tailwindcss
Thats it!
You've successfully set up a modern MDX page with Next.js! You now have:
A powerful page system that combines the best of Markdown and React
Beautiful typography that makes your content shine