next.jsmdxjs

How to get exports form mdx in nextjs


My Problem

The nextjs documentation on mdx states that it does not support frontmatter. Instead it is suggested to create a constant and export it [1]. However I can't seem to get at data exported in such a way. For instance using the following

/* -- ./pages/example.mdx -- */
export const meta = {
    title: 'some example title'
}
/* -- ./pages/index.js -- */
import Example from './example.mdx';

export default function Index ({ ... props }) {
   return <Example />
}

It seems that what gets imported can be used as a react component, but there does not seem to be a reference to the meta property anywhere.

What I wanted to do

I have a list of markdown files and want to create an overview page that lists all of them, using the metadata defined in every file. Something akin to the following

import fs from 'fs/promises';
import path from 'path';

export async function getStaticProps () {
    const root = path.join (process.cwd (), 'pages/items');
    const listing = await fs.readdir(root);
    const items = listing
        .filter (item => item.endsWith ('.mdx'))
        .map (item => {
            const meta = require (`./items/${item}`).meta;
            const id = item.replace (/\.md$/, '');
            return { id, ... meta }
        });

    return { props: { items } };
}

export default function Overview ({ items, ... props }) {
    /* ... use items */
}

Edit

It seems like there is a big difference between using .md and .mdx. In the examples I gave here I used .mdx, but locally I had used .md. Switching extensions makes everything work.

It is strange that the extension makes such a difference even though both of them are configured in next.config.js

const withMDX = require ('@next/mdx') ({
    extension: /\.mdx?$/
});
module.exports = withMDX ({ /* ... */ });

[1] https://nextjs.org/docs/advanced-features/using-mdx#frontmatter


Solution

  • Use .mdx extension instead of a .md extension.