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.
-
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
.mdx
documents with astro and next.js.1. simple example
this example collection has a single
title
frontmatter field, and mdx content which allows a<RedText>
custom component.keystatic.config.tsx
src/content/posts/test.mdx
1.1 approach 1: import
.mdx
documents directlythis relies on bundler integrations, which are provided by
@astrojs/mdx
and@next/mdx
.1.1.1
@astrojs/mdx
with the
@astrojs/mdx
integration, mdx files can be directly imported. custom components can be provided via props. frontmatter is available as a named import.astro.config.ts
src/pages/index.astro
1.1.2
@next/mdx
with the
@next/mdx
integration, 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-frontmatter
plugin.next.config.mjs
src/mdx-components.tsx
src/app/page.tsx
Note
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.mjs
Tip
when using typescript, the
frontmatter
import can be typed:src/types/mdx.d.ts
1.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.ts
src/pages/index.astro
1.3 approach 3: use keystatic reader, and compile with
@mdx-js/mdx
this uses the keystatic
reader
to get document content, and the@mdx-js/mdx
processor to transform mdx into javascript. custom components can be passed directly to the processor.src/lib/content/reader.ts
1.3.1 with astro jsx runtime
src/lib/content/mdx.ts
src/pages/index.astro
1.3.2 with react jsx runtime
src/lib/content/mdx.ts
src/app/page.tsx
1.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.tsx
an example entry will consist of a json file, and multiple mdx files (one for each card):
src/content/my-test-post.json
src/content/my-test-post/blocks/1/value/cards/0/content.mdx
src/content/my-test-post/blocks/1/value/cards/1/content.mdx
2.1 approach 1: import
.mdx
documents 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/mdx
works (although without HMR)
2.3.1 astro
content must not live in
src/content
because this will throw a content collection error, but otherwise works.src/pages/index.astro
2.3.2 next.js
src/app/page.tsx
2.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
.mdx
documents 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/mdx
works, just need to use
@keystatic/core/reader/github
instead of@keystatic/core/reader
3.4 approach 4: pre-compile mdx
TODO
Beta Was this translation helpful? Give feedback.
All reactions