Markdown + Astro = ❤️
Markdown is a great invention that lets us write less markup. It also handles typographical matters like converting straight apostrophes (‘) to opening or closing quotes (‘ or ‘) for us.
Although Astro has built-in support for Markdown via .md files, I’d argue that your Markdown experience can be enhanced in two ways:
I’ve cover these in depth in Practical Astro: Content Systems.
We’re going to focus on MDX today.
MDX
MDX is a superset of Markdown. It lets you use components in Markdown and simple JSX in addition to all other Markdown features.
For Astro, you can also use components from any frontend framework that you have installed. So you can do something like:
—
# Frontmatter…
—
import AstroComp from ‘@/components/AstroComp.astro’
import SvelteComp from ‘@/components/AstroComp.astro’
…
…
It can be a great substitute for content-heavy stuff because it lets you write markup like the following.
### Card Title
Content goes here
– List
– Of
– Items
Second paragraph
Astro will convert the MDX into the following HTML:
Card Title
Content goes here
Second paragraph
Notice what I did above:
- I used ## instead of a full h2 tag.
- I used – instead of and to denote lists.
- I didn’t need any paragraph tags.
Writing the whole thing in HTML directly would have been somewhat of a pain.
Installing MDX
Astro folks have built an integration for MDX so it’s easy-peasy to add it to your project. Just follow these instructions.
Three Main Ways to Use MDX
These methods also work with standard Markdown files.
Import it Directly
The first way is simply to import your MDX file and use it directly as a component.
—
import MDXComp from ‘../components/MDXComp.mdx’
—
Because of this, MDX can kinda function like a partial.
Through Content Collections
First, you feed your MDX into a content collection. Note that you have to add the mdx pattern to your glob here.
Import it directly
The first way is simply to import your MDX file and use it directly as a component.
// src/content.config.js
import { defineCollection } from ‘astro:content’;
import { glob } from ‘astro/loaders’;
const blog = defineCollection({
loader: glob({ pattern: “**/*.{md,mdx}”, base: “./src/blog” }),
});
export const collections = { blog };
Then you retrieve the MDX file from the content collection.
—
import { getEntry, render } from ‘astro:content’
const { slug } = Astro.props
const post = await getEntry(‘blog’, slug)
const { Content } = await render(post)
—
As you’re doing this, you can pass components into the MDX files so you don’t have to import them individually in every file.
For example, here’s how I would pass the Image component from Splendid Labz into each of my MDX files.
—
import { Image } from ‘@splendidlabz/astro’
// …
const { Content } = await render(post)
const components = { Image }
—
In my MDX files, I can now use Image without importing it.
Use a Layout
Finally, you can add a layout frontmatter in the MDX file.
—
title: Blog Post Title
layout: @/layouts/MDX.astro
—
This layout frontmatter should point to an Astro file.
In that file:
- You can extract frontmatter properties from Astro.props.content.
- The MDX content can be rendered with .
—
import Base from ‘./Base.astro’
const props = Astro.props.content
const { title } = props
—
Caveats
Formatting and Linting Fails
ESLint and Prettier don’t format MDX files well, so you’ll end up manually indenting most of your markup.
This is fine for small amounts of markup. But if you have lots of them… then the Markdown Component will be a much better choice.
More on that in another upcoming post.
The Astro RSS integration doesn’t support MDX files out of the box.
Thankfully, this can be handled easily with Astro containers. I’ll show you how to do this in Practical Astro.
Taking it Further
I’ve been building with Astro for 3+ years, and I kept running into the same friction points on content-heavy sites: blog pages, tag pages, pagination, and folder structures that get messy over time.
So I built Practical Astro: Content Systems, 7 ready-to-use solutions for Astro content workflows (MDX is just one of them). You get both the code and the thinking behind it.
If you want a cleaner, calmer content workflow, check it out.
I also write about Astro Patterns and Using Tailwind + CSS together on my blog. Come by and say hi!
