A minimal yet extensible setup for writing and rendering MDX in Next.js.
Includes a feature-rich editor powered by @mdxeditor/editor and a viewer powered by next-mdx-remote. Perfect for blogs, documentation, and interactive content.
- Full MDX Support: Markdown + React components in one file
- Rich Editor: Toolbar, lists, tables, images, code blocks, JSX embedding
- Custom Components: Callouts, badges, confetti buttons, etc.
- Syntax Highlighting: Powered by
rehype-highlightwith GitHub themes - Accessible Output: Slugs + autolinked headings for navigation
- Next.js Native: Works with App Router, server actions, and RSC
Make sure you have a Next.js 13+ project:
npx create-next-app@latest mdx-editor-nextjs
cd mdx-editor-nextjsInstall dependencies:
npm install @mdxeditor/editor next-mdx-remote
npm install remark-gfm remark-math
npm install rehype-highlight rehype-slug rehype-autolink-headings(Optionally add shadcn/ui for UI components.)
src/components/mdx/mdx-editor.tsx
<MDXEditor
markdown={value}
onChange={setNewContent}
contentEditableClassName="prose max-w-none p-4 focus:outline-none"
plugins={[
headingsPlugin(),
listsPlugin(),
codeBlockPlugin(),
codeMirrorPlugin(),
toolbarPlugin({ toolbarContents: () => <UndoRedo /> }),
]}
/>src/components/mdx/mdx-viewer.tsx
<MDXRemote
source={content}
options={{
mdxOptions: {
remarkPlugins: [remarkGfm, remarkMath],
rehypePlugins: [rehypeHighlight, rehypeSlug, rehypeAutolinkHeadings],
},
}}
components={mdxComponents}
/>src/app/page.tsx
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
<MdxEditor value={content} height={600} />
<div className="border rounded-md p-4 h-[600px] overflow-y-auto">
<MdxViewer content={content} />
</div>
</div>- Callout – info/warning/success/error banners
- Badge – styled text badge
- ConfettiButton – interactive button with confetti 🎉
- Table / Code / Blockquote – styled markdown overrides
- Extend
mdxComponentsinmdx-components.tsxto override default markdown elements (h1,p,a,table, etc.) - Add your own JSX components for interactive content.
- Swap out highlight.js themes by importing a different CSS file.
- Remark plugins: Markdown-level (e.g., tables, math, GFM)
- Rehype plugins: HTML-level (e.g., syntax highlighting, slugs, autolinks)
- MDXEditor plugins: UI/UX features inside the editor (toolbar, lists, code blocks)
- Start with minimal plugins; add complexity as needed
- Use
prosestyles from Tailwind for readable output - Define custom components for reusable blog elements
- Keep plugins in the correct order (
rehype-slugbeforerehype-autolink-headings) - Separate editor and viewer responsibilities cleanly