docs
docs copied to clipboard
How to render remote markdown using content layer API
📚 Subject area/topic
markdown, content layer api
📋 Suggested page
https://docs.astro.build/en/reference/configuration-reference/#experimentalcontentlayer
📋 General description or bullet points (if proposing new content)
I think that with the new content layer API, rendering remote markdown (from a server or api) is going to be a common use case.
The Astro docs currently says "Astro does not include built-in support for remote Markdown outside of experimental content collections!"
However I was unable to find any further information or examples about rendering remote (server) markdown.
So firstly, I was wondering if there already is an good example that I have missed?
If not, I have got some rough code (shown below) that renders markdown using Astros built in functions that seems to work and might help someone. But I would really like someone to review it and let me know things that can be improved.
Example Loader that renders remote markdown:
import { defineCollection, z } from 'astro:content';
import type { Loader } from "astro/loaders";
function markdownTestLoader({}):Loader {
return {
name: "markdown-test-loader",
load: async ({ config, store, parseData, generateDigest, entryTypes }) => {
store.clear();
// Would normally load this JSON data from API.
// The "content" field has the markdown I want to render
const dummyAPIData = {
id: "home",
title: "Test Markdown Data",
content: "## Markdown to Render \nTesting markdown rendering.\n- List item 1\n- List item 2"
}
const id = dummyAPIData.id;
const data = await parseData({ id, data:dummyAPIData });
const body = dummyAPIData.content; // markdown to render next
const digest = generateDigest(data);
// Render markdown to HTML using built in Astro markdown render function
let rendered;
const markdownEntryType = entryTypes.get(".md");
if( markdownEntryType?.getRenderFunction ) {
const render = await markdownEntryType.getRenderFunction(config);
rendered = await render?.({
id,
data,
body,
digest
});
}
store.set({ id, data, rendered, digest });
}
}
}
// Define collection with loader
const markdownTestCollection = defineCollection({
loader: markdownTestLoader({}),
schema: z.object({
id: z.string(),
title: z.string(),
content: z.string()
})
});
export const collections = {
'markdownTestCollection': markdownTestCollection
};
The markdown HTML can be displayed on the page using the "render" function and built in "Content" component:
---
import { getCollection, render } from 'astro:content';
export async function getStaticPaths() {
const pages = await getCollection("markdownTestCollection");
return pages.map((page) => ({
params: {
slug: page.id },
props: {
page
},
}));
}
const { page } = Astro.props;
const { Content, headings } = await render(page);
---
<h1>{page.data.title}</h1>
<Content />
As I said, I'm sure there are things above that could be done better.
🖥️ Reproduction of code samples in StackBlitz
No response