How to Build Your Own Blog with Next.js and MDX
Modern blogging has come a long way from its humble origins. Today, developers and technical writers have a wide range of powerful tools and frameworks at their disposal for creating rich, interactive blogs. Two technologies that have gained popularity recently are Next.js, a React-based web development framework, and MDX, a format that combines Markdown with JSX.
In this guide, we‘ll walk through the process of building a fully-featured blog using Next.js and MDX from start to finish. By the end, you‘ll have a fast, SEO-optimized blog that‘s a joy to write for and a pleasure for readers to browse. Let‘s get started!
Why Build a Blog with Next.js?
Before we dive into the tutorial, let‘s quickly review what Next.js is and why it‘s a great fit for building blogs:
-
Performance – Next.js offers features like server-side rendering, route prefetching, and code splitting to optimize performance. This results in fast page loads and a smooth user experience.
-
Developer Experience – As a React framework, Next offers a component-based architecture, declarative routing, and helpful tooling to streamline development. Automatic code splitting, filesystem routing, and hot reloading all help boost productivity.
-
Full-Stack Capabilities – Next.js can run both client-side and server-side JavaScript code. This allows you to easily add backend functionality like fetching data from databases or submitting forms without needing a separate server.
-
Deployment – Next offers one-command deployment to hosting providers like Vercel or Netlify. Your blog can be up and running on the web in minutes.
What is MDX?
MDX is a special flavor of Markdown that allows you to use JSX inline. In other words, you can import and use React components right inside your Markdown content.
This is huge for blogging, since it means you can create highly customized posts with interactive elements like charts, image carousels, or embedded videos, while still retaining the simplicity of writing in plain text. MDX has the best of both worlds.
Some other benefits of MDX include:
-
Familiarity – Markdown is a popular and easy-to-learn syntax for writing web content. MDX builds on that foundation.
-
Flexibility – By leveraging the full power of React components, MDX opens up many new possibilities for page layouts and interactivity compared to plain Markdown or HTML.
-
Reusability – Custom MDX components you create for one page can be reused across your entire blog or even in other projects.
Setting Up the Next.js Project
With the introductions out of the way, let‘s set up a new Next.js project for our blog. Make sure you have Node.js installed, then open your terminal and run:
npx create-next-app@latest my-blog
cd my-blog
This will bootstrap a new Next project in the my-blog directory and navigate you there. Follow the prompts to complete the setup.
Next, let‘s install the dependencies we‘ll need to work with MDX:
npm install gray-matter react-markdown
gray-matter is a library that enables us to parse the YAML frontmatter metadata in our MDX files. react-markdown will handle converting the Markdown content to HTML for display in the browser.
Creating Content with MDX
Now let‘s write our first blog post using MDX! Create a new folder called posts in the root of your project. Inside it, add a file named post-1.mdx with the following content:
---
title: My First Blog Post
date: 2023-03-29
---
# Hello World!
My first post is written in **MDX**. I can use standard Markdown syntax to make my content more engaging.
I can also import and use React components inline:
<Button>Example Button</Button>
How cool is that?
At the top, we have a section of YAML frontmatter fenced in by — delimiters. We can put metadata about the post here, like the title and date. The rest of the file contains the content body in standard Markdown format.
The
Go ahead and add a few more MDX files to the posts folder to flesh out the blog content. You can use the same frontmatter fields in each.
Configuring Next.js for MDX
To tell Next.js how to handle the MDX files, we need to add some configuration. Create a new file in the root of the project called next.config.js and add the following:
const withMDX = require("@next/mdx")()
module.exports = withMDX({
pageExtensions: ["js","jsx","mdx"]
})
This uses the @next/mdx plugin to enable support for files with the .mdx extension. It also tells Next to consider MDX files as pages that can be rendered.
Creating the Blog Pages
With our content and config in place, we‘re ready to start building the actual pages of the blog. Let‘s begin with the index page that will display a list of all posts.
Create a new file at pages/index.js and add:
import fs from "fs"
import matter from "gray-matter"
import Link from "next/link"
export default function Home({ posts }) {
return (
<div>
<ul>
{posts.map(post => (
<li key={post.slug}>
<Link href={`/posts/${post.slug}`}>
<a>{post.title}</a>
</Link>
</li>
))}
</ul>
</div>
)
}
export async function getStaticProps() {
const files = fs.readdirSync("posts")
const posts = files.map(file => {
const slug = file.replace(/\.mdx$/, "")
const content = fs.readFileSync(`posts/${file}`, "utf8")
const { data } = matter(content)
return {
slug,
...data
}
})
return {
props: {
posts
}
}
}
Here‘s what‘s happening:
- We import some dependencies including the fs module for reading the filesystem and the gray-matter library for parsing the MDX frontmatter
- The default export is a React component that will render the page. It receives the posts data as a prop.
- The Home component renders a title and a list of links to each blog post
- The getStaticProps function is a special Next.js function that runs at build time. It reads the MDX files from the posts directory, extracts the frontmatter metadata using gray-matter, and returns the post data as props.
Now if you run npm run dev and visit http://localhost:3000, you should see your blog home page with a list of posts! Clicking a post link will show a 404 though, since we haven‘t created the post pages yet.
Rendering Post Pages
To render the individual post pages, create a new file at pages/posts/[slug].js and add the following:
import fs from "fs"
import matter from "gray-matter"
import ReactMarkdown from "react-markdown"
export default function PostPage({ frontmatter, content }) {
return (
<div>
<p>Posted on {frontmatter.date}</p>
<ReactMarkdown>
{content}
</ReactMarkdown>
</div>
)
}
export async function getStaticPaths() {
const files = fs.readdirSync("posts")
const paths = files.map(file => ({
params: {
slug: file.replace(/\.mdx$/, "")
}
}))
return {
paths,
fallback: false
}
}
export async function getStaticProps({ params: { slug } }) {
const post = fs.readFileSync(`posts/${slug}.mdx`, "utf-8")
const { data: frontmatter, content } = matter(post)
return {
props: {
frontmatter,
content
}
}
}
The bracketed [slug].js filename tells Next to use this component to dynamically render pages based on the slug parameter.
getStaticPaths is another special Next function that defines the list of paths to statically render. Here we get the list of MDX files and return their slugs as the path parameters.
The getStaticProps function loads the MDX file that matches the requested slug, parses it into frontmatter data and content, and returns it as props.
The PostPage component renders the post title, date, and content. We use react-markdown to convert the MDX content to HTML. Frontmatter data is rendered as regular text.
That‘s the basic structure of our blog done! If you restart the dev server, you should now be able to click a post on the index page and see it render.
Adding Features and Optimizations
There are plenty of improvements we can make to our basic blog. Here are few ideas:
-
Syntax Highlighting – To make code blocks look nicer, we can add a syntax highlighter. react-syntax-highlighter is a good option that can be integrated with react-markdown. Be sure to include the necessary CSS too.
-
SEO – Adding meta tags for title, description, Open Graph images etc can help boost the search rankings for your content. The next/head component makes this easy. You can also look into the next-seo package for more advanced options.
-
Categories and Tags – Organize your posts by category or tag to help readers find related content. This data can be added to the frontmatter and used to generate pages that list posts by category.
-
Author Pages – Add a bio page for each post author. You can extract author info from frontmatter or from a separate file/database.
-
RSS Feed – Generate an RSS feed for your blog so readers can subscribe for updates. The rss npm package can help with this.
-
Pagination – If you have many posts, it‘s a good idea to split the index page into multiple pages. Luckily Next has a built-in API for pagination.
Deployment
When you‘re ready to share your new blog with the world, deploying it is a breeze thanks to Next‘s first-class support for Vercel (the creators of Next).
Make sure your project is pushed to GitHub, GitLab, or Bitbucket. Then sign up for a free Vercel account and import your blog repo. Vercel will automatically detect that it‘s a Next.js project and configure the build settings for you.
Click deploy and within a minute or two your blog will be live on a Vercel domain! You can also configure a custom domain if you have one.
Other hosting options include:
- Netlify
- AWS Amplify
- Digital Ocean Apps
- Render
All have similar easy setup for Next projects.
Conclusion
Congratulations, you now have a fully functional Next.js blog enhanced with MDX!
To recap, we covered:
- The benefits of using Next.js and MDX together for blogging
- How to set up a new Next project from scratch
- Configuring Next to work with the MDX format
- Creating pages and extracting data from MDX files
- Rendering lists of posts and individual post pages
- Extending the blog with extra features like syntax highlighting and SEO
- Deploying a Next.js app to production using Vercel
Next Steps
There‘s so much more you can do to customize and expand your blog. A few ideas to consider:
- Create a custom theme with styled-components or TailwindCSS
- Add commenting functionality using Disqus or Utterances
- Integrate analytics to track your page views
- Build a newsletter signup form
- Experiment with interactive post elements like quizzes or polls
- Set up automated social media posting for new articles
I hope this guide has inspired you to build an awesome blog with the power of Next.js and MDX. Happy blogging!