Astro Loader
Use AstraCMS as a content source for Astro.js Content Collections
The @astracms/astro-loader package provides Astro Content Collection loaders for seamlessly integrating AstraCMS content into your Astro.js projects.
Installation
npm install @astracms/astro-loaderpnpm add @astracms/astro-loaderyarn add @astracms/astro-loaderbun add @astracms/astro-loaderQuick Start
Configure Environment Variables
Create a .env file in your Astro project:
ASTRACMS_API_KEY=your_api_key_hereSet Up Content Collections
Create or update your content configuration file:
import { defineCollection } from 'astro:content';
import {
postsLoader,
categoriesLoader,
tagsLoader,
authorsLoader,
} from '@astracms/astro-loader';
// v2 config (recommended) - just needs apiKey
const config = {
apiKey: import.meta.env.ASTRACMS_API_KEY,
};
// Or for v1 (legacy):
// const config = {
// apiVersion: 'v1' as const,
// workspaceId: import.meta.env.ASTRACMS_WORKSPACE_ID,
// };
const posts = defineCollection({
loader: postsLoader({
...config,
format: 'markdown', // or 'html'
}),
});
const categories = defineCollection({
loader: categoriesLoader(config),
});
const tags = defineCollection({
loader: tagsLoader(config),
});
const authors = defineCollection({
loader: authorsLoader(config),
});
export const collections = { posts, categories, tags, authors };Use Content in Your Pages
---
import { getCollection, render } from 'astro:content';
export async function getStaticPaths() {
const posts = await getCollection('posts');
return posts.map((post) => ({
params: { slug: post.id },
props: { post },
}));
}
const { post } = Astro.props;
const { Content } = await render(post);
---
<article>
<h1>{post.data.title}</h1>
<p>{post.data.description}</p>
{post.data.coverImage && (
<img src={post.data.coverImage} alt={post.data.title} />
)}
<div class="meta">
<span>Category: {post.data.category.name}</span>
<span>Published: {post.data.publishedAt.toLocaleDateString()}</span>
</div>
<div class="tags">
{post.data.tags.map((tag) => (
<a href={`/tags/${tag.slug}`}>{tag.name}</a>
))}
</div>
<div class="prose">
<Content />
</div>
<div class="authors">
{post.data.authors.map((author) => (
<div class="author">
{author.image && <img src={author.image} alt={author.name} />}
<span>{author.name}</span>
{author.role && <span>{author.role}</span>}
</div>
))}
</div>
</article>Loaders Reference
postsLoader
Loads blog posts from AstraCMS with full support for content rendering.
// v2 (recommended) - just apiKey
postsLoader({
apiKey: string, // Required for v2
format?: 'html' | 'markdown', // Content format (default: 'markdown')
categories?: string[], // Filter by category slugs
excludeCategories?: string[], // Exclude category slugs
tags?: string[], // Filter by tag slugs
excludeTags?: string[], // Exclude tag slugs
query?: string, // Search query
})
// v1 (legacy) - requires apiVersion + workspaceId
postsLoader({
apiVersion: 'v1',
workspaceId: string, // Required for v1
format?: 'html' | 'markdown',
// ... same filter options
})Post Data Schema:
| Field | Type | Description |
|---|---|---|
title | string | Post title |
description | string | Post description/excerpt |
slug | string | URL slug |
coverImage | string | null | Cover image URL |
featured | boolean | Featured post flag |
publishedAt | Date | Publication date |
updatedAt | Date | Last update date |
category | Category | Post category |
tags | Tag[] | Post tags |
authors | Author[] | Post authors |
attribution | string | null | Content attribution |
categoriesLoader
Loads categories from AstraCMS.
// v2 (recommended)
categoriesLoader({
apiKey: string,
query?: string,
})
// v1 (legacy)
categoriesLoader({
apiVersion: 'v1',
workspaceId: string,
query?: string,
})Category Data Schema:
| Field | Type | Description |
|---|---|---|
name | string | Category name |
slug | string | URL slug |
description | string | null | Category description |
tagsLoader
Loads tags from AstraCMS.
// v2 (recommended)
tagsLoader({
apiKey: string,
query?: string,
})
// v1 (legacy)
tagsLoader({
apiVersion: 'v1',
workspaceId: string,
query?: string,
})Tag Data Schema:
| Field | Type | Description |
|---|---|---|
name | string | Tag name |
slug | string | URL slug |
description | string | null | Tag description |
authorsLoader
Loads author profiles from AstraCMS.
// v2 (recommended)
authorsLoader({
apiKey: string,
query?: string,
})
// v1 (legacy)
authorsLoader({
apiVersion: 'v1',
workspaceId: string,
query?: string,
})Author Data Schema:
| Field | Type | Description |
|---|---|---|
name | string | Author name |
slug | string | URL slug |
bio | string | null | Author biography |
image | string | null | Profile image URL |
role | string | null | Author role/title |
socials | AuthorSocial[] | Social media links |
Authentication
The loader supports two authentication methods:
API Key (v2 API) - Recommended
The v2 API is the default. Just pass your API key:
postsLoader({
apiKey: import.meta.env.ASTRACMS_API_KEY,
})Workspace ID (v1 API)
For the legacy v1 API, you must specify apiVersion: 'v1':
postsLoader({
apiVersion: 'v1',
workspaceId: 'your-workspace-id',
})We recommend using API key authentication (v2 API) as it provides better security and doesn't expose your workspace ID in the URL.
Advanced Usage
Filter Posts by Category
const posts = defineCollection({
loader: postsLoader({
...config,
categories: ['technology', 'tutorials'],
}),
});Exclude Certain Tags
const posts = defineCollection({
loader: postsLoader({
...config,
excludeTags: ['internal', 'draft'],
}),
});Use HTML Format
If you prefer to use pre-rendered HTML instead of markdown:
const posts = defineCollection({
loader: postsLoader({
...config,
format: 'html',
}),
});Extend Schemas
You can import and extend the default schemas:
import { z } from 'astro:content';
import { postSchema } from '@astracms/astro-loader';
const extendedPostSchema = postSchema.extend({
customField: z.string().optional(),
});Requirements
- Astro 5.0 or later
- AstraCMS account with API access
Next Steps
Last updated on