I tried to experiment a bit with Astro. Since you can only dynamically render markdown pages. I thought it would be useful to dynamically generate astro pages. So far, the only ones I found was rendering a mdx file if you want to use React components in markdown. However, I want to be able to use astro components instead.
I did found a way to render an astro file, thanks to the Astro tutorial docs. With that, I used import.meta.glob
to dynamically import and render
astro pages from the /content
folder. I'm not sure if this is the
"best way to do it", but it works for now. Tho if you know a better
way, feel free to let me know.
Implementing the dynamic astro pages
Creating an astro content
First, I created some sample an astro file in the /content
folder.
I exported the metadata with the `meta` variable.
// src/content/2025/sample.astro
---
import { Code } from 'astro:components'
// Note: This will become the metadata of the page.
export const meta = {
title: 'Rendering Astro Pages',
description: 'My experiments in terms of dynamically rendering astro pages.',
publishedAt: new Date('2025-03-05T00:00:00.000Z'),
category: 'experiments',
author: {
name: 'Joeylene',
username: 'jorenrui',
},
}
---
<p>Hello from Astro!</p>
<Code
lang="js"
code="a = 1 + 1;\nconsole.log(a);"
/>
The content helper function
Then, I created a helper function to fetch the astro files in the
/content
folder.
// src/lib/helpers/content.ts
function formatFileName(file: string) {
return file.split('/content/')[1].replace('.astro', '')
}
export function getContent(): Content[] {
const matches = import.meta.glob('../../content/**/*.astro', {
eager: true,
})
const entries = Object.values(matches) as {
meta: Content // Note: This is the metadata of the astro file.
default: any // Note: This is the Astro component to be rendered
file: any
url: string
}[]
return entries.map((entry) => ({
...entry.meta,
id: formatFileName(entry.file),
}))
}
Rendering the links
Then I've rendered a list of links to the dynamically rendered astro pages.
// src/pages/index.astro
---
import { getContent } from '@/lib/helpers/content'
const entries = getContent()
---
<ul class="space-y-8">
{entries.map((entry) => (
<li>
<a href={entry.id}>{entry.title}</a>
</li>
))}
</ul>
Rendering the astro file
Lastly, I created a page to render the astro file:
// src/pages/[...slug].astro
---
import { getContent } from '@/lib/helpers/content'
export async function getStaticPaths() {
const entries = await getContent()
return entries.map((entry) => ({
params: { slug: entry.id },
props: entry,
}))
}
const entry = Astro.props
const Content = entry.default
---
<div class="prose">
<Content />
</div>
Afterwards, I had fun a bit with a dynamically rendered astro page that contains a React, Alpine, and Svelte component .