DEV Community

Cover image for Rendering External Markdown in Astro
James 'Dante' Midzi
James 'Dante' Midzi

Posted on • Edited on • Originally published at dantedecodes.vercel.app

Rendering External Markdown in Astro

It seems like I'm always writing the same article... 😂

I enjoy Astro, it's a good framework, but there is one thing about it or rather the docs that irks me.

Astro is pitched as a content first framework with native markdown support. That's what they say. However, this isn't completely the case.

When it comes to markdown that is local to your project, Astro does absolute wonders with the rendering and parsing. Your problems arise when you have your markdown from an external source i.e. a CMS. The docs have been structured in such a way that they want you to use local markdown and Content Collections.

But sometimes, your markdown is somewhere else. What is one to do then?

Let's go on a journey shall we? ...

The Scenario

You use Hygraph as your CMS for your articles. You write your articles in markdown, and you can fetch them and all their data. What you want to do is have your articles rendered on your newly created Astro site.

The requirements for this task are as follows:

  • It needs to be one thing - a package or whatever - that you import and use.
  • You don't want to have to configure any additional things.

Before I give you the solutions that I think are best, I challenge you to find the solution within the Astro docs. I'll wait...


The Solution(s)

Markdown Component (deprecated)

I fought with this a while back when Astro was still in v1, and in those times, there was a package called @astrojs/markdown-components. That package has long since been deprecated, as such you won't be able to install it.

For reference, this is how that would look (those who read my Displaying Dev.to Post on Your Astro Site article will be familiar with this code.)

<!-- /articles/[slug].astro -->
---
import Markdown from "@astrojs/markdown-component";

export async function getStaticPaths() {
  const articles = await fetchArticles();

  return articles.map((article) => {
    return {
      params: { slug: article.slug },
      props: { article },
    };
  });
}

const {article} = Astro.props;
const {body_markdown}  = article;
---

<div>
    <Markdown content={body_markdown} />
</div>

Enter fullscreen mode Exit fullscreen mode

A wise man once said, "If it ain't broke, don't fix it."

My site has been working well with this package, and because of that, I will not upgrade it to a higher version as I am not in the mood to do the dance again.

Now, let's head on to the stuff that works with newer versions of Astro.

Astro Pub

Repository: https://github.com/astro-community/md

Installation & Usage

npm install @astropub/md
Enter fullscreen mode Exit fullscreen mode
<!-- /articles/[slug].astro -->
---
import Markdown from "@astrojs/markdown-component";

export async function getStaticPaths() {
    ...
}

const {article} = Astro.props;
const {body_markdown}  = article;
---

<div>
  <Markdown of={body_markdown} />
</div>
Enter fullscreen mode Exit fullscreen mode

NOTE: Currently as of writing this, AstroPub requires astro@^3.0.0 to work smoothly.

Thoughts

If I had no choice, but to fight this battle again, this is the method I would choose.


Markdown-it

Repository: https://github.com/markdown-it/markdown-it

Installation & Usage

npm install markdown-it
Enter fullscreen mode Exit fullscreen mode
<!-- /articles/[slug].astro -->
---
import markdownit from "markdown-it";
const md = markdownit();

export async function getStaticPaths() {
 ...
}

const {content_markdown} = Astro.props
---

<div>
    <Fragment set:html={md.render(content_markdown)} />
</div>

Enter fullscreen mode Exit fullscreen mode

NOTE: Markdown-it also requires astro ^3.0.0

Thoughts

I don't like this method. I don't like it because:

  • I have to declare a variable to store markdown-it.
  • I have to use the set:html to render the content.
  • I have to additionally call the render function and then pass my content to it.

Astro Remote

Update: 29 February 2024

After submitting an issue, Nate added the install command.

Repository: https://github.com/natemoo-re/astro-remote

Installation & Usage

npm install astro-remote
Enter fullscreen mode Exit fullscreen mode
<!-- /articles/[slug].astro -->
---
import {Markdown} from "astro-remote";

export async function getStaticPaths() {
 ...
}

const {content_markdown} = Astro.props
---

<div>
    <Markdown content={body_markdown} />
</div>

Enter fullscreen mode Exit fullscreen mode

Thoughts

Astro Remote works very similarly to Astro Pub, and I like that about it.


The Thing About Marked

If you did accept my challenge and looked in the docs, you might have found this section:

Fetching Remote Markdown

The Astro docs recommend marked, but there's some things you have to be aware of with marked.

Marked Site: https://marked.js.org/

Thoughts

Marked informs you on their site that it does not sanitise your markup. Do with that information what you will.


Wrapping Up

Astro - a brilliant little thing. A bit more care with regard to this part of their framework/documentation would be cool. At least as much care as is given to other parts of the docs.

On a steam, whitep4nth3r went on a journey of trying to find this information on stream, her goal was to use things the 'Astro way. In the end, she went with the markdown-it approach.

The stream if you are curious. It's at 3hrs 57 minutes: https://www.twitch.tv/videos/1998429304?filter=archives&sort=time


Thank you for reading, let's connect!

Thank you for visiting this little corner of mine. Let's connect on Twitter, Discord and LinkedIn

Top comments (0)