Add MDX support to Next.js 13 and format them with tailwind typography

Introduction

MDX is a superset of markdown that lets you write JSX directly in your markdown files. It is a powerful way to add dynamic interactivity and embed React components within your content.

Next.js can support both local MDX content inside your application, as well as remote MDX files fetched dynamically on the server. The Next.js plugin handles tranforming Markdown and React components into HTML, including support for usage in Server Components (default in app).

Create next.js app

Run the following command to create the next.js app.

npx create-next-app@latest nextjs-mdx-tailwind --typescript --eslint
✔ Would you like to use `src/` directory with this project? … No / Yes
✔ Would you like to use experimental `app/` directory with this project? … No / Yes
✔ What import alias would you like configured? … @/*
Creating a new Next.js app in /home/siavash/code/blog/articles/nextjs13-mdx-tailwind-typography/nextjs-mdx-tailwind.

Using npm.

Initializing project with template: app


Installing dependencies:
- react
- react-dom
- next
- typescript
- @types/react
- @types/node
- @types/react-dom
- eslint
- eslint-config-next


added 272 packages, and audited 273 packages in 14s

103 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
Success! Created nextjs-mdx-tailwind at /home/siavash/code/blog/articles/nextjs13-mdx-tailwind-typography/nextjs-mdx-tailwind

Install tailwind and tailwind typography

Install tailwind and tailwind typography using npm.

cd nextjs-mdx-tailwind
npm install -D tailwindcss postcss autoprefixer @tailwindcss/typography

Configure tailwind.config.js for next.js

Initialize tailwind and open the configuration file.

npx tailwindcss init -p
code tailwind.config.js

Add the following content.

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    './app/**/*.{js,ts,jsx,tsx}',
    './pages/**/*.{js,ts,jsx,tsx}',
    './components/**/*.{js,ts,jsx,tsx}',

    // Or if using `src` directory:
    './src/**/*.{js,ts,jsx,tsx}',
  ],
  theme: {
    extend: {},
  },
  plugins: [require('@tailwindcss/typography')],
}

Add the Tailwind directives to your CSS

code globals.css

Add the following content.

@tailwind base;
@tailwind components;
@tailwind utilities;

Install and configure MDX

In this section the next.js documentation is followed to setup MDX for next.js.

Install the @next/mdx and remark-gfm packages.

npm install @next/mdx remark-gfm

Create mdx-components.jsx in the root of your application (not inside app)

// This file allows you to provide custom React components
// to be used in MDX files. You can import and use any
// React component you want, including components from
// other libraries.
function H1({ children }) {
  return <h1>{children}</h1>
}

function H2({ children }) {
  return <h2>{children}</h2>
}

function H3({ children }) {
  return <h3>{children}</h3>
}

function H4({ children }) {
  return <h4>{children}</h4>
}

function H5({ children }) {
  return <h5>{children}</h5>
}

export function useMDXComponents(components) {
  return { h1: H1, h2: H2, h3: H3, h4: H4, h5: H5, ...components }
}

Update next.config.mjs to use @next/mdx and Github flavor markdown.

import createMDX from '@next/mdx'
import remarkGfm from 'remark-gfm'

/** @type {import('next').NextConfig} */
const nextConfig = {
  pageExtensions: ['js', 'jsx', 'ts', 'tsx', 'md', 'mdx'],
  experimental: {
    appDir: true,
    mdxRs: false, // Disable this to work with remarkGfm
  },
}

const withMDX = createMDX({
  extension: /\.mdx?$/,
  options: {
    remarkPlugins: [remarkGfm],
    rehypePlugins: [],
  },
})

export default withMDX(nextConfig)

Install @types/mdx to add a type for mdx files for typescript to recognize it.

npm install -D @types/mdx

Add a app/hello.mdx file with MDX content to your app directory.

## Heading

# H1

## H2

### H3

#### H4

##### H5

###### H6

## Emphasis

_italics text_ and **bold text**.

## Lists

1. Ordered list item
2. Another item

- Unordered list item
- Second item

## Links

[google](https://www.google.com)

## Images

![alt text](https://source.unsplash.com/random 'Random pic')

## Code and Syntax Highlighting

Inline `code` has `back-ticks around` it.

```javascript
var s = 'Code block'
alert(s)
```

## Tables

| Col1 | Cl2   | Col3 |
| ---- | ----- | ---- |
| 1    | One   | 12   |
| 2    | Two   | 12   |
| 3    | Three | 1    |

## Blockquotes

> Blockquotes are done like this.
> Several line part of the same quote.
> You can put **Markdown** here also.

Import the MDX file inside a app/page.tsx to display the content.

import HelloWorld from './hello.mdx'

export default function Page() {
  return (
    <div className="container prose mx-auto mt-36">
      <HelloWorld />
    </div>
  )
}

Note: The prose class adds the styling to the mdx output.

Source code

The source code can be found here