Destiner's Notes

Using Components in Markdown with Astro

14 February 2022

Astro makes it possible to write components using any frontend framework and then use those components inside Markdown pages. Let’s try it.

MDX

Instead of using plain Markdown (.md) files, we will have to use MDX (.mdx) files. Before we move further, we will have to install MDX integration:

npm i @astrojs/mdx

Update your Astro config to include the integration:

import mdx from '@astrojs/mdx';

export default defineConfig({
  integrations: [mdx()], // Add other integrations if needed
  // ...
});

Also, you will have to change the extension of your Markdown files to MDX (.md -> .mdx). Don’t forget to update the glob pattern as well:

const allPosts = await Astro.glob('./post/*.mdx');

With that, let’s finally create and use our component.

Astro component

First, let’s create an Astro component:

---
const { message } = Astro.props;
---

<div>{message}</div>

<style>
  div {
    border: 1px solid #999;
    padding: 8px;
  }
</style>

Now we can use that component inside an MDX document by using import syntax:

import Banner from '../component/banner.astro';

<Banner message="Some text" />

Frontend framework component

We can also use a frontend framework to write components. Here’s an example using Vue:

<template>
  <div>{{ message }}</div>
</template>

<script
  setup
  lang="ts"
>
  defineProps({
    message: {
      type: String,
      required: true,
    },
  });
</script>

<style scoped>
  div {
    border: 1px solid #999;
    padding: 8px;
  }
</style>

We can use this component the same way as we did for an Astro component:

import Banner from '../component/Banner.vue';

<Banner message="Some text" />

List/object component prop

Let’s say you have a component that takes a list of elements:

---
const { items } = Astro.props;
---

<div class="list">
  {items.map((item) => <div class="item">{item}</div>)}
</div>

It might be tricky to pass an array to a component inside an MDX document. You can use the frontmatter to store it:

---
list: ['Item 1', 'Item 2']
---

import List from '../component/list.astro';

<List items={frontmatter.list} />