The Nextra Blog Theme turns any Next.js + MDX project into a fully-featured blog. It provides a ready-madeDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/shuding/nextra/llms.txt
Use this file to discover all available pages before exploring further.
<Layout>, <Navbar>, and <Footer>, auto-generates a post listing from your MDX files, supports tag filtering, computes reading-time estimates, and ships with dark mode out of the box. Posts are written as plain MDX files with YAML frontmatter — no database or CMS required.
A live demo is available at demo.vercel.blog. The full source code for that demo lives in the
examples/blog directory of the Nextra repository.What You Get
- Post listing page built automatically from all MDX files in your posts directory
- Tag pages that filter posts by topic
- RSS feed generation helpers
- Reading-time estimates calculated from post content
- Dark mode and a
<ThemeSwitch>component - Comments support via the
<Comments>component - Custom MDX components — override any element (headings, dates, code blocks) per-site
Manual Setup
import nextra from 'nextra'
const withNextra = nextra({
// Show copy-code buttons on all code blocks by default
defaultShowCopyCode: true,
// Compute reading time for every post
readingTime: true,
})
export default withNextra({
reactStrictMode: true,
})
Setting
readingTime: true makes Nextra inject a readingTime object into every MDX page’s metadata, which the blog theme surfaces automatically in post cards and post headers.Create
app/layout.jsx (or app/layout.tsx). The blog theme exposes <Layout>, <Navbar>, <Footer>, and <ThemeSwitch> from nextra-theme-blog, plus <Banner>, <Head>, and <Search> from nextra/components:import { Footer, Layout, Navbar, ThemeSwitch } from 'nextra-theme-blog'
import { Banner, Head, Search } from 'nextra/components'
import { getPageMap } from 'nextra/page-map'
import 'nextra-theme-blog/style.css'
export const metadata = {
title: 'My Blog',
}
export default async function RootLayout({ children }) {
const banner = (
<Banner storageKey="v1-launch">
🎉 Welcome to my new blog!{' '}
<a href="/posts/hello-world" style={{ textDecoration: 'underline' }}>
Read the first post →
</a>
</Banner>
)
return (
<html lang="en" suppressHydrationWarning>
<Head backgroundColor={{ dark: '#0f172a', light: '#fefce8' }} />
<body>
<Layout banner={banner}>
<Navbar pageMap={await getPageMap()}>
<Search />
<ThemeSwitch />
</Navbar>
{children}
<Footer>
{new Date().getFullYear()} © My Blog.{' '}
<a href="/rss.xml" style={{ float: 'right' }}>
RSS
</a>
</Footer>
</Layout>
</body>
</html>
)
}
Pass a
backgroundColor object to <Head> to set the browser UI color in supported mobile browsers — separately for dark and light mode.The blog theme exports a
useMDXComponents helper that registers its built-in overrides. Merge them with any custom components you want:import { useMDXComponents as getBlogMDXComponents } from 'nextra-theme-blog'
const blogComponents = getBlogMDXComponents({
// Override individual HTML elements or add custom ones:
h1: ({ children }) => (
<h1 style={{ color: 'hotpink' }}>{children}</h1>
),
// Customise how post dates are rendered:
DateFormatter: ({ date }) =>
date.toLocaleDateString('en', {
day: 'numeric',
month: 'long',
year: 'numeric',
}),
})
export function useMDXComponents(components) {
return {
...blogComponents,
...components,
}
}
---
title: Hello, World!
date: 2024-01-15
description: My very first post on this Nextra-powered blog.
author: Your Name
tags: [announcement, meta]
---
Welcome to my blog! This is the first post. Nextra reads the frontmatter
above and uses it to build the post listing, tag pages, and RSS feed.
titlestring<h1>datestring (ISO 8601)descriptionstringauthorstringtagsstring[]/tags/<tag> pagesreadingTimeReadingTimereadingTime: trueVisit http://localhost:3000 to see your blog home page, and http://localhost:3000/posts/hello-world to read your first post.
Post Frontmatter Fields
Nextra’s blog theme reads the following fields from each MDX page’s YAML frontmatter. All fields are optional, buttitle and date are strongly recommended so the post listing sorts and renders correctly.
The
readingTime field is injected automatically by Nextra when you set readingTime: true in next.config.mjs. You do not need to add it manually to your frontmatter.Content Directory Structure
A typical Nextra blog project looks like this:Exported Components
Thenextra-theme-blog package exports the following components for use in your layout and pages:
Layout components
Layout components
| Export | Description |
|---|---|
Layout | Root wrapper; accepts banner prop |
Navbar | Top navigation bar; accepts pageMap and child components |
Footer | Bottom footer bar |
ThemeSwitch | Dark/light/system mode toggle button |
Post components
Post components
| Export | Description |
|---|---|
PostCard | Card component for rendering post previews in a listing |
Comments | Comment section component for individual post pages |
Hooks & utilities
Hooks & utilities
| Export | Description |
|---|---|
useMDXComponents | Returns the theme’s default MDX element map; accepts overrides |
useTheme | Re-exported from next-themes; returns the active theme and setter |
Next Steps
Docs Theme
Switch to the docs theme for a full sidebar, TOC, and search experience.
Custom Theme
Roll your own layout component with complete control over the UI.
Blog Example Source
Browse the full example source code on GitHub.
Live Blog Demo
See the blog theme running live on Vercel.