If you're stepping into the world of web development, you might be pondering over a crucial question:
What is MDX?
MDX, short for Markdown eXtended, is a versatile markup language that combines the simplicity of Markdown with the power of React components. This amalgamation empowers developers to create dynamic and interactive content, such as engaging blog posts.
With MDX, you can craft blog posts in Markdown while seamlessly embedding React components within them. This flexibility opens the door to rendering charts, images, videos, interactive forms, and custom styling within your content. Notably, MDX is supported by popular static site generators like Next.js and Gatsby, making it an excellent choice for building aesthetically pleasing and functional blogs.
Now that we've clarified MDX, let's dive into our comparison!
Installation
Next MDX
Next Contentlayer
Configuration
Next MDX
To enable MDX compilation with @next/mdx, we need to tweak our next.config.js file as below:
Next, we create a new MDX page within the /pages directory:
After that, we can import a React component directly into our MDX page:
Next Contentlayer
To compile MDX using next-contentlayer, we make adjustments to our next.config.js file like so:
Unlike @next/mdx, we don't need to specify extensions in next.config.js because next-contentlayer intelligently detects them. However, next-contentlayer requires a dedicated configuration file, like this:
Next, we create a new MDX document within the /posts directory. For example, let's consider the file posts/hello-world.mdx:
Upon starting or building the server, contentlayer generates a .contentlayer directory in the root of our project. The directory structure looks like this:
Now, we can import the generated types and posts in our page component, as shown below:
NOTE: It's advisable to add .contentlayer to .gitignore since it's generated during the build.
Remote MDX
Next MDX
If your Markdown or MDX files aren't stored within your application, you can dynamically fetch them from a server. This is particularly useful for obtaining content from a Content Management System (CMS) or other data sources.
Next Contentlayer (Experimental)
The remote file source in next-contentlayer is currently in an experimental phase and not recommended for production usage. It operates similarly to the static file source but allows content files to reside outside the website folder. Contentlayer automatically syncs these remote content files to your local website folder and processes them using the standard file source.
Common remote file sources include other Git repositories, databases, APIs, or any location where your content originates.
NOTE: You can combine static source files with remote source files by using the same root contentDirPath and storing content in different subdirectories.
Layouts
Next MDX
To add a layout or custom styles to our top-level MDX page, we can create a new component and import it into the MDX page. We can wrap the MDX page with the layout component like this:
Next Contentlayer
When using next-contentlayer, we don't create an MDX page directly under the pages directory as with @next/mdx. Instead, we create a page component and import the generated types and posts, like this:
Remark & Rehype Plugins
Next MDX
To transform MDX content using remark and rehype plugins, we can use the options object in the createMDX function. Since the remark and rehype ecosystem is ESM only, use next.config.mjs for configuration, as shown in this example:
Next Contentlayer
Achieving the same behavior in next-contentlayer is straightforward. Use the remarkPlugins and rehypePlugins options in the makeSource function, like this:
Frontmatter Or Metadata
Next MDX
@next/mdx doesn't natively support frontmatter. To include it, you can use external solutions like gray-matter.
Although we can achieve the same behavior using @next/mdx by exporting a meta object from within the MDX file as given in the example below:
Next Contentlayer
next-contentlayer provides built-in support for frontmatter. You can define your fields in the contentlayer.config.ts file, as demonstrated earlier in this article.
With this configuration, next-contentlayer will automatically extract frontmatter data from your MDX files and make it available in the generated types.
Custom Elements
An advantage of using Markdown is that it maps to native HTML elements, making it faster and more intuitive to write HTML in Markdown format. For instance, the following Markdown:
Compiles to the following HTML:
However, when you want to style your own elements to give a custom feel to your website or application, you can introduce custom components known as "shortcodes." These shortcodes map to HTML elements and can be included in your Markdown or MDX content to achieve custom styling and functionality.
Next MDX
To enable the use of custom elements in Next MDX, you need to set up the MDXProvider and pass a components object as a prop. Each key in the components object maps to an HTML element name.
Here's an example of how to set up custom elements in Next MDX:
In this example, the components object maps custom component names (p, pre, h1, h2, code, img) to their respective components, allowing you to style and customize these elements in your MDX content.
NOTE: If we have to use it across the site then we should add the provider to _app.ts.
Next Contentlayer
Using custom components with Next Contentlayer is similar to Next MDX. You can define a components object and pass it to your MDX content.
Here's an example of how to set up custom elements with Next Contentlayer:
In this example, the mdxComponents object maps custom component names (a, MyComponent) to their respective components. You can also override default HTML elements, such as the <a> element, to use custom behavior, like the Next.js Link component.
Handling Markdown
Natively React does not understand Markdown. We need to transform the markdown plain text into HTML.
It can be achieved using remark and rehype. Remark is an ecosystem of tools around markdown. Rehype is the same, but for HTML. For example, the following code snippet transforms markdown into HTML:
Next MDX
With @next/mdx we don't need to use remark or rehype directly, as it is handled for us by the package itself. Although you'd still need a utility to parse markdown as below:
By default next-contentlayer treats your document as markdown so to handle markdown files instead of MDX with it all we need to do it update the contentlayer.config.ts file as below:
And for syntax highlighting when using markdown we can use rehype-highlight as below:
Bonus
Next MDX
Next.js now supports a new MDX compiler in Rust. It is not recommended to use it in production yet since it is still in experimental stage. To use the Rust compiler, we need to configure next.config.js when we pass it to withMDX as below:
Next Contentlayer
next-contentlayer is working towards supporting various CMS out there like notion, contentful, sanity as well as the platform like stackbit. All the mentioned integrations are still in the experimental stage and not recommended to use in production yet. But since contentlayer is still in it's early stage, it's a good sign that it's working towards supporting various CMS and platforms.
Conclusion
Next Contentlayer Pros Over Next MDX
Typesafe content support out of the box
Reduces the line of code with a dedicated configuration file
Next MDX Pros Over Next Contentlayer
Supports remote files source
Ultimately, the choice between Next MDX and Next Contentlayer will depend on your familiarity and ease of use with the tools. Both options empower you to create dynamic and engaging MDX-powered websites with Next.js.