A List of Techniques To Render MDX in Astro and Next.js #1074
Replies: 3 comments
-
|
This is a great collection of approaches, thanks for sharing this Stefan! 🤙 |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
|
So far, I've been loving keystatic. Easy to implement and flexible. I was having challenges rendering custom components with markdoc using the new markdoc fields and content components. I ended up switching to mdx for those. The strategies above did not work for me in next.js because my content is dynamic. File: mdx-remote.tsx |
Beta Was this translation helpful? Give feedback.

Uh oh!
There was an error while loading. Please reload this page.
-
hi, i have compiled a list of different approaches to rendering mdx for myself, but maybe someone else finds it useful as well. still need to play a bit more with approach 4 (
contentlayer/velite) - will update when i know more.rendering mdx in astro and next.js
while the old rich-text widget (
fields.document()) provided a way to render its content with thebuilt-in
<DocumentRenderer>, this is no longer the case with the new mdx field (fields.mdx()).the following tries to list different approaches for rendering
.mdxdocuments with astro and next.js.1. simple example
this example collection has a single
titlefrontmatter field, and mdx content which allows a<RedText>custom component.keystatic.config.tsxsrc/content/posts/test.mdx1.1 approach 1: import
.mdxdocuments directlythis relies on bundler integrations, which are provided by
@astrojs/mdxand@next/mdx.1.1.1
@astrojs/mdxwith the
@astrojs/mdxintegration, mdx files can be directly imported. custom components can be provided via props. frontmatter is available as a named import.astro.config.tssrc/pages/index.astro1.1.2
@next/mdxwith the
@next/mdxintegration, mdx files can be directly imported. custom components can be provided viamdx-components.tsx, or via props. frontmatter is available as a named import with theremark-mdx-frontmatterplugin.next.config.mjssrc/mdx-components.tsxsrc/app/page.tsxNote
while the astro mdx integration by default adds a couple of plugins to support syntax highlighting in code blocks, typographic quotes, and headings ids, the next.js plugin does not add any plugins by default.
to match the default astro behavior:
next.config.mjsTip
when using typescript, the
frontmatterimport can be typed:src/types/mdx.d.ts1.2 approach 2: astro content collections
with astro content collections, use
getCollection()andgetEntry()utilities to get mdx content and frontmatter. optionally, frontmatter can be validated with a schema provided viasrc/content/content.config.ts. custom components are provided via props.astro.config.tssrc/pages/index.astro1.3 approach 3: use keystatic reader, and compile with
@mdx-js/mdxthis uses the keystatic
readerto get document content, and the@mdx-js/mdxprocessor to transform mdx into javascript. custom components can be passed directly to the processor.src/lib/content/reader.ts1.3.1 with astro jsx runtime
src/lib/content/mdx.tssrc/pages/index.astro1.3.2 with react jsx runtime
src/lib/content/mdx.tssrc/app/page.tsx1.4 approach 4: pre-compile mdx
TODO
2. complex example
this example collection uses
fields.blocks()andfield.array()with potentially multiple mdx fields per entry.keystatic.config.tsxan example entry will consist of a json file, and multiple mdx files (one for each card):
src/content/my-test-post.json{ "title": "My test post", "blocks": [ { "discriminant": "imageSection", "value": { "title": "The image section", "image": "/assets/content/blocks/my-test-post/blocks/0/value/image.jpg" } }, { "discriminant": "cardsSection", "value": { "title": "The cards section", "cards": [ { "title": "The first card" }, { "title": "The second card" } ] } } ] }src/content/my-test-post/blocks/1/value/cards/0/content.mdxsrc/content/my-test-post/blocks/1/value/cards/1/content.mdx2.1 approach 1: import
.mdxdocuments directlynot really viable, because you would need to know how content is saved by keystatic:
import "../content/blocks/my-test-post/blocks/1/value/cards/0/content.mdx"2.2 approach 2: astro content collections
astro content collections do not allow this kind of collection schema.
2.3 approach 3: use keystatic reader, and compile with
@mdx-js/mdxworks (although without HMR)
2.3.1 astro
content must not live in
src/contentbecause this will throw a content collection error, but otherwise works.src/pages/index.astro2.3.2 next.js
src/app/page.tsx2.4 approach 4: pre-compile mdx
TODO
3. previews with draft mode (next.js only)
in draft mode, use the keystatic github reader to get a mdx string.
3.1 approach 1: import
.mdxdocuments directlydoes not work, nothing to import.
3.2 approach 2: astro content collections
does not work with mdx strings.
3.3 approach 3: use keystatic reader, and compile with
@mdx-js/mdxworks, just need to use
@keystatic/core/reader/githubinstead of@keystatic/core/reader3.4 approach 4: pre-compile mdx
TODO
Beta Was this translation helpful? Give feedback.
All reactions