Recommended way to pass an MDX file from getServerSideProps
as a prop to a component?
#47621
-
SummaryI have a situation where I have thousands of dynamically generated pages, each which have their own custom markdown content with the page content. Most of the page is dynamically generated, but some of the markdown content is custom to the specific page, hence a standalone
Inside the dynamic one, I would like to do something like this: function getServerSideProps({ params }) {
const INTROS = {
page1: () => (await import('~/contents/Page1.mdx')).default,
page2: () => (await import('~/contents/Page2.mdx')).default,
// ...
}
return {
props: {
intro: INTROS[String(params?.dynamic)](),
}
}
}
function DynamicPage({ intro }) {
return (
<>
{intro}
<p>Other stuff...</p>
</>
)
} What is the best way to accomplish something like this? Do I need to get lower level with rehype or remark plugins and such to accomplish this? If so, could you provide a quick snippet on how I might accomplish this? This way, I can have a mostly dynamic template with custom markdown content. The markdown content might even take some props to help render its content, hence the desire to use MDX. Also, I don't think the dynamic import of Thank you! Additional informationNo response ExampleNo response |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 2 replies
-
I asked ChatGPT-4 for help:
It gave me this code, is it along the right track? // pages/your-page.js
import fs from 'fs';
import path from 'path';
import matter from 'gray-matter';
import { serialize } from 'next-mdx-remote/serialize';
import { MDXRemote } from 'next-mdx-remote';
const YourPage = ({ mdxSource }) => {
return <MDXRemote {...mdxSource} />;
};
export async function getServerSideProps() {
// Set the path to the MDX file you want to render
const filePath = path.join(process.cwd(), 'path', 'to', 'your-mdx-file.mdx');
// Read the MDX file content
const fileContent = fs.readFileSync(filePath, 'utf-8');
// Parse the MDX file content and its front matter using gray-matter
const { content } = matter(fileContent);
// Serialize the content of the MDX file to make it compatible with MDXRemote
const mdxSource = await serialize(content);
// Return the serialized MDX content as a prop
return { props: { mdxSource } };
}
export default YourPage; Is there a better or more canonical way? |
Beta Was this translation helpful? Give feedback.
-
I do it like this: export const getStaticProps: GetStaticProps<MDXPost> = async (context) => {
try {
const { params } = context;
const { slug } = params || {};
if (typeof slug !== "string") return { notFound: true };
const client = new MeiliSearch({
host: process.env.MEILISEARCH_URL,
apiKey: process.env.MEILISEARCH_KEY,
});
const index = await client.getIndex<IcyJoseph.Post>(
process.env.MEILISEARCH_INDEX
);
const { content, ...rest } = await index.getDocument(slug);
const source = await serialize(content || "");
return { props: { ...rest, source }, revalidate: 360 };
} catch (e) {
return { notFound: true, revalidate: 360 };
}
}; And then the page component: // removed some other imports
import { MDXRemote, type MDXRemoteSerializeResult } from "next-mdx-remote";
import { serialize } from "next-mdx-remote/serialize";
import { useRouter } from "next/router";
import { components } from "components/Blog/mdx";
export const BlogEntry = ({ slug, source, summary, title, tags }: MDXPost) => {
const router = useRouter();
const views = usePostViews(slug);
if (router.isFallback) {
return <div>Loading...</div>;
}
return (
<Container mt={4} px={1}>
<Text as="header" $fontSize="2.5rem">
{title}
</Text>
<MDXRemote {...source} components={components} />
</Container>
);
}; So yeah, Chat-GPT was trained with data that most likely contained this link: https://nextjs.org/blog/markdown 😅 The general idea is that the serialize function builds this uglified, but stringified interpretation of your "content", and then you pass that to MDXRemote, which using the "components" props, renders your beautiful page. The components ought to look something like: https://github.com/icyJoseph/icyJoseph/blob/dev/src/components/Blog/mdx.tsx This is what the, beginning of, serialize output looks like (it is a string): /*@jsxRuntime automatic @jsxImportSource react*/
const {Fragment: _Fragment, jsx: _jsx, jsxs: _jsxs} = arguments[0];
const {useMDXComponents: _provideComponents} = arguments[0];
function _createMdxContent(props) {
const _components = Object.assign({
h1: "h1",
p: "p",
code: "code",
a: "a",
blockquote: "blockquote",
h2: "h2",
pre: "pre",
h3: "h3",
ul: "ul",
li: "li"
}, _provideComponents(), props.components);
return _jsxs(_Fragment, / * and it goes on, and on, and on */ |
Beta Was this translation helpful? Give feedback.
I do it like this: