The wider ecosystem seems to have a need for multiple MDX components sourced from a single file. Consider the following examples.
mdx-deck uses multiple MDX components from a single file to render a slide deck.
# This is the title of my deck
---
# About Me
---
```jsx
<CodeSnippet />
```
---
import Demo from './components/Demo'
<Demo />
---
# The end

There is a common use case in websites to have multiple blobs of smaller content. I've used some mock content from the Gatsbyjs.org site here to illustrate the point, but pretty much all product sites do this somewhere including
Next

React

Terraform

# Modern web tech without the headache
Enjoy the power of the latest web technologies – React.js , Webpack , modern JavaScript and CSS and more — all set up and waiting for you to start building.
---
# Bring your own data
Gatsby’s rich data plugin ecosystem lets you build sites with the data you want — from one or many sources: Pull data from headless CMSs, SaaS services, APIs, databases, your file system, and more directly into your pages using GraphQL .
---
# Scale to the entire internet
Gatsby.js is Internet Scale. Forget complicated deploys with databases and servers and their expensive, time-consuming setup costs, maintenance, and scaling fears. Gatsby.js builds your site as “static” files which can be deployed easily on dozens of services.

MDX is a viable replacement for Storybook story files, but writing a new story example in a new file is a lot of overhead. Additionally, writing a set of examples with code blocks in a single file can result in documented dynamic examples.
The behavior I'm proposing is to define a way to load multiple MDX components from a single file. the following small example:
some content
---
more b content
---
ccccccccccc
would (conceptually) result in an array of MDX components
[
function MDXContent({ components, ...props }) {
return (
<div name="wrapper" components={components}>
<p>{`some content`}</p>
</div>
);
},
function MDXContent({ components, ...props }) {
return (
<div name="wrapper" components={components}>
<p>{`more b content`}</p>
</div>
);
},
function MDXContent({ components, ...props }) {
return (
<div name="wrapper" components={components}>
<p>{`ccccccccccc`}</p>
</div>
);
}
];
This output can then be rendered directly in place of a normal MDX component
comment: this output will probably be a function that returns an array. This allows us to access the result (the array) and use it as a component directly.
import AFewMDXs from './small-content.mdxs'
export default props => <div>
<AFewMDXs {...props} />
</div>
The full suite of MDX functionality should be supported, including layouts, props, exports, etc.
layout is a default export. While it is possible to replace wrapper to achieve similar behavior, there are frameworks that don't fully support page-level wrapping components so wrapper is hard to use on a per-component or page-level basis. For this reason, each component should come with it's own layout. This behaves the same as a regular MDX file.
export default props => <section {...props} />
some content
---
more b content
---
ccccccccccc
So we end up with the following:
/* @jsx mdx */
const layoutProps1 = {};
const MDXLayout1 = props => <section {...props} />;
function MDXContent1({ components, ...props }) {
return (
<div name="wrapper" components={components}>
<MDXLayout1 {...layoutProps} {...props}>
<p>{`some content`}</p>
</MDXLayout1>
</div>
);
}
MDXContent1.isMDXComponent = true;
const layoutProps2 = {};
function MDXContent2({ components, ...props }) {
return (
<div name="wrapper" components={components}>
<p>{`more b content`}</p>
</div>
);
}
MDXContent2.isMDXComponent = true;
const layoutProps3 = {};
function MDXContent3({ components, ...props }) {
return (
<div name="wrapper" components={components}>
<p>{`ccccccccccc`}</p>
</div>
);
}
MDXContent3.isMDXComponent = true;
const MDXMulti = props => [
<MDXContent1 {...props} />,
<MDXContent2 {...props} />,
<MDXContent3 {...props} />,
];
export default MDXMulti
Note that each "default" export is allocated to it's own MDX Component, just like a regular file would be. We can include an extension that allows setting the default layout for a group of MDX content by specially processing the first MDX "file" if it only includes imports and exports.
export default props => <section {...props} />
---
some content
---
more b content
---
ccccccccccc
Exports can exist at the global level as usual, but what happens to local exports? They would be set as properties on the MDX component
export const a = 2;
some content
---
export const b = 4;
more b content
---
ccccccccccc
example output:
// mdx 1, etc are in this file before this
const layoutProps2 = {};
function MDXContent2({ components, ...props }) {
return (
<div name="wrapper" components={components}>
<p>{`more b content`}</p>
</div>
);
}
MDXContent2.isMDXComponent = true;
MDXContent2.b = 4
// rest of file
MDX components can take props. So can the multi-mdx. The difference is that props given to a multi-mdx component apply to all MDX content. This is clearly illustrated by the proposed result component:
const MDXMulti = props => [
<MDXContent1 {...props} />,
<MDXContent2 {...props} />,
<MDXContent3 {...props} />,
];
Would love to have some more options like this. Related to this, I attempted to create a plugin to handle this better in mdx-deck v2 by checking for the actual node type instead of using regex/string manipulation, and I ended up having to duplicate a lot of mdx's internals: https://github.com/jxnblk/mdx-deck/blob/1986c65eea267a5edbb51842fac3d126cb162413/packages/mdx-plugin/index.js
I think this is a really cool idea, but it feels to me like the type of thing that belongs in an extension/plugin/etc rather than in the core. It's a specialized use case, and a dramatic break from normal markdown syntax, where --- would be expected to render a horizontal rule.
It's a specialized use case, and a dramatic break from normal markdown syntax, where
---would be expected to render a horizontal rule.
This was my immediate first reaction too.
That said, I wouldn’t be opposed to something like /---.
Also, neat thing about MDX is how we can use MD frontmatter. Would a MDX break allow for additional “frontmatter” for the next component?
Frontmatter wouldn't be affected because in platforms that support it, it's a pre-process step on the input string before the MDX is processed by mdx-js/mdx, so the frontmatter won't hit the mdx parser.
Interesting, but using --- as a separator would conflict with the usual markdown behaviour, choosing another selector that doesn't conflict with existing markdown would be more appropriate, and avoid a big breaking change.
Most helpful comment
I think this is a really cool idea, but it feels to me like the type of thing that belongs in an extension/plugin/etc rather than in the core. It's a specialized use case, and a dramatic break from normal markdown syntax, where
---would be expected to render a horizontal rule.