May 22, 2024 A layman's guide to setting up an MDX blog with Next.js and Tailwind CSS Background
This blog is written from the perspective of a hardcore Android and IoT engineer who is entering the land of web and
browsers while creating my personal website.
So, why not write a blog about setting up the blog?
I have taken most of the content from the Next.js MDX
setup guide. The aim if this blog is to cut down the noise and provide the minimal steps for the setup. I have also
addressed some configuration problems the documentation for which may require some digging.
The stack
TypeScript
Next.js using app router
Tailwind CSS
The basics
I have assumed that the base project has been set up. Once done, the following files are the ones that we need to
create or edit:
project/
├── src/
│ ├── app/
│ │ ├── blog/
│ │ │ └── (content)/
│ │ │ ├── test-blog/
│ │ │ │ └── page.mdx
│ │ │ └── layout.tsx
│ │ └── globals.css
│ └── mdx-components.tsx
├── next.config.mjs
└── tailwind.config.ts
Start by installing the required basic MDX packages:
npm install @next/mdx @mdx-js/loader @mdx-js/react @types/mdx
Update the next.config.mjs
file to use MDX in the project:
import createMDX from "@next/mdx" ;
/** @type {import('next').NextConfig} */
const nextConfig = {
pageExtensions: [ "js" , "jsx" , "md" , "mdx" , "ts" , "tsx" ],
};
const withMDX = createMDX ();
export default withMDX ( nextConfig ) ;
Create the mdx-components.tsx
file with the following content:
import type { MDXComponents } from 'mdx/types'
export function useMDXComponents ( components : MDXComponents ) : MDXComponents {
return {
... components,
}
}
Now we can create the page.mdx
file in the test-blog
directory and let the app router do its magic.
Layout and styling
After completing the basic MDX setup, we can notice that even though the content is being rendered, the styling is not
does not look good.
To fix this, install the tailwind typography plugin:
npm install -D @tailwindcss/typography
Update the tailwind.config.ts
file to include the mdx files and add the typography plugin:
import type { Config } from "tailwindcss" ;
const config = {
// ...
content: [
"./pages/**/*.{js,jsx,md,mdx,ts,tsx}" ,
"./components/**/*.{js,jsx,md,mdx,ts,tsx}" ,
"./app/**/*.{js,jsx,md,mdx,ts,tsx}" ,
"./src/**/*.{js,jsx,md,mdx,ts,tsx}" ,
],
plugins: [ require ( '@tailwindcss/typography' )],
} satisfies Config ;
export default config;
Now create the layout.tsx
file with the following content for the common blog layout:
export default function BlogLayout ({
children,
} : {
children : React.ReactNode;
}) {
return < div className ={ "prose m-4 sm:m-8 sm:mx-auto" }>{children} </ div > ;
}
This fixes the rendering of the different sections, but the text color is still a problem.
To fix this, let's edit tailwind.config.ts
again to configure the typography plugin using the colors defined in
globals.css
:
import type { Config } from "tailwindcss" ;
const config = {
// ...
content: [
"./pages/**/*.{js,jsx,md,mdx,ts,tsx}" ,
"./components/**/*.{js,jsx,md,mdx,ts,tsx}" ,
"./app/**/*.{js,jsx,md,mdx,ts,tsx}" ,
"./src/**/*.{js,jsx,md,mdx,ts,tsx}" ,
],
plugins: [ require ( '@tailwindcss/typography' )],
theme: {
extend: {
typography: {
DEFAULT: {
css: {
"--tw-prose-body" : "hsl(var(--foreground))" ,
"--tw-prose-headings" : "hsl(var(--foreground))" ,
"--tw-prose-lead" : "hsl(var(--foreground))" ,
"--tw-prose-links" : "hsl(var(--foreground))" ,
"--tw-prose-bold" : "hsl(var(--foreground))" ,
"--tw-prose-counters" : "hsl(var(--foreground))" ,
"--tw-prose-bullets" : "hsl(var(--foreground))" ,
"--tw-prose-hr" : "hsl(var(--foreground))" ,
"--tw-prose-quotes" : "hsl(var(--foreground))" ,
"--tw-prose-quote-borders" : "hsl(var(--foreground))" ,
"--tw-prose-captions" : "hsl(var(--foreground))" ,
"--tw-prose-kbd" : "hsl(var(--foreground))" ,
"--tw-prose-kbd-shadows" : "hsl(var(--foreground))" ,
"--tw-prose-code" : "hsl(var(--foreground))" ,
"--tw-prose-pre-code" : "hsl(var(--foreground))" ,
"--tw-prose-pre-bg" : "hsl(var(--secondary))" ,
"--tw-prose-th-borders" : "hsl(var(--foreground))" ,
"--tw-prose-td-borders" : "hsl(var(--foreground))" ,
},
},
},
},
},
} satisfies Config ;
export default config;
Code block syntax highlighting
To add syntax highlighting to the code blocks, we will use the remark-gfm
and rehype-pretty-code
plugins:
npm install remark-gfm rehype-pretty-code
Finally, update the next.config.mjs
file to include the plugins:
import createMDX from "@next/mdx" ;
import remarkGfm from "remark-gfm" ;
import rehypePrettyCode from "rehype-pretty-code" ;
/** @type {import('next').NextConfig} */
const nextConfig = {
pageExtensions: [ "js" , "jsx" , "md" , "mdx" , "ts" , "tsx" ],
};
const withMDX = createMDX ({
options: {
remarkPlugins: [remarkGfm],
rehypePlugins: [[rehypePrettyCode, { keepBackground: false }]],
},
});
export default withMDX ( nextConfig ) ;
Useful links