Load .astro
files with the Astro Content Layer API, just as you would other formats (e.g., Markdown, MDX). Makes use of Vite's import.meta.glob
to dynamically import .astro
files as modules.
Caution
This is very janky, so be prepared to troubleshoot. Please file an issue if you encounter a problem not mentioned in this README.
npm install astro-content-loader
.astro
files offer better type safety and code completion compared to Markdown and similar formats. This loader allows you to treat .astro
files as content files, which means:
- You can provide metadata and schemas for your content, similar to Markdown or MDX files.
- Files can be located anywhere in your project, not just in
src/pages/
.
In your content.config.ts
file, define and export your collection:
import { defineCollection, z } from "astro:content";
import astro from "astro-content-loader";
const posts = defineCollection({
loader: astro({
/*
* Specify the path to your .astro content files
*
* IMPORTANT:
* - Glob path is evaluated relative to the src/ directory
* - When running in dev mode, `eager` must be `false`
* - When building, `eager` must be true
*/
modules: import.meta.glob("./content/posts/**/*.astro", { eager: false }),
}),
// Optional: Define a schema for your content
schema: z.object({
title: z.string(),
tags: z.array(z.string()).optional(),
}),
});
export const collections = { posts };
Content files are standard .astro
files, but you can also include metadata in the frontmatter by exporting a meta
object:
---
// NOTE: Metadata must not reference external variables or imports
export const meta = {
title: "My first post",
tags: ["astro", "content-loader"],
}
---
<article>
<p>This is my first post using the Astro Content Loader!</p>
</article>
Content files can be queried and rendered just like other content types. For example, to generate static routes for each page in a collection:
---
import Base from "../layouts/Base.astro";
import { getCollection, render } from "astro:content";
export function getStaticPaths() {
const posts = await getCollection("posts");
return posts.map((post) => ({
params: { id: post.id },
props: { entry: post },
}));
}
const { entry } = Astro.props;
const { Content } = await render(entry);
---
<Base>
<h1>{entry.data.title}</h1>
<Content />
</Base>
See the Astro content collection documentation for more details.
- The content collections schema
image()
helper is not (yet) supported. - The
eager
option onimport.meta.glob
must be manually switched when building.
Note
Unfortunately, the following code won't work, because all parameters passed to import.meta.glob
must be static:
import.meta.glob("./content/posts/**/*.astro", { eager: import.meta.env.PROD }
- Architecture based on Astro's built-in
glob
loader (source).