How to use PagesCMS with Astro
Learn how to integrate PagesCMS with Astro for a complete headless CMS solution. Step-by-step guide with code examples.
Introduction
Managing content for Astro websites can be a pain—editing files, dealing with frontmatter, and keeping everything working together. PagesCMS gives you a nice solution: a Git-based visual editor that works well with GitHub and plays nicely with Astro static sites.
In this Astro CMS tutorial, you’ll learn how to set up PagesCMS with Astro using the .pages.yml
file and connect it with Astro’s content collections. The result? A simple content workflow with type checking, IDE help, and an easy commit-to-build process for your Astro blog or website.
Set up PagesCMS for Astro projects via .pages.yml
PagesCMS requires a .pages.yml
file in your project repository. If it’s missing, PagesCMS prompts you to add one in its UI.
The file supports three main sections:
media
: Defines where uploads like images and videos livecontent
: Configures your content types (collections, files, etc.)components
: Optionally defines reusable field sets
Example .pages.yml
media:
- name: media
label: Media
input: src/media
output: /media
path: /media
content:
- name: blog
label: Blog Posts
type: collection
path: src/content/blog
fields:
- name: title
label: Title
type: string
- name: pubDate
label: Publication Date
type: date
- name: description
label: Description
type: string
- name: tags
label: Tags
type: list
items:
type: string
- name: body
label: Body
type: rich-text
Important things to know:
- The
media
section makes sure your rich-text editor can handle media uploads properly - The
content
section creates a collection that goes tosrc/content/blog
- Field types should match what you’ll set up in your Astro content setup
Set up Astro content collections
Astro content collections give you type checking, editor help, and better ways to work with your content in Astro websites.
Create Astro content schema (src/content/config.ts
)
import { defineCollection, z } from 'astro:content';
const blog = defineCollection({
type: 'content',
schema: z.object({
title: z.string(),
pubDate: z.date(),
description: z.string().optional(),
tags: z.array(z.string()).optional(),
}),
});
export const collections = { blog };
This Astro schema will check your frontmatter and give you IDE help when working with your Astro blog posts.
Directory structure alignment
Make sure both systems write and read from the same places:
project-root/
├── .pages.yml
├── astro.config.mjs
└── src/
├── content/
│ ├── config.ts
│ └── blog/
│ ├── my-first-post.md
│ └── another-post.md
├── media/
│ └── (uploaded images)
└── pages/
├── blog/
│ ├── index.astro
│ └── [slug].astro
└── index.astro
When you edit content via PagesCMS, it commits new or updated .md
files (with YAML frontmatter and content) into src/content/blog
.
Create Astro blog pages
List all blog posts with Astro (src/pages/blog/index.astro
)
---
import { getCollection } from 'astro:content';
const posts = await getCollection('blog');
const sortedPosts = posts.sort((a, b) =>
new Date(b.data.pubDate).getTime() - new Date(a.data.pubDate).getTime()
);
---
<html>
<head>
<title>Blog</title>
</head>
<body>
<h1>Blog Posts</h1>
<ul>
{sortedPosts.map(post => (
<li>
<a href={`/blog/${post.slug}`}>
<h2>{post.data.title}</h2>
{post.data.description && <p>{post.data.description}</p>}
<time>{post.data.pubDate.toLocaleDateString()}</time>
</a>
</li>
))}
</ul>
</body>
</html>
Individual Astro blog post page (src/pages/blog/[slug].astro
)
---
import { getCollection } from 'astro:content';
export async function getStaticPaths() {
const posts = await getCollection('blog');
return posts.map(post => ({
params: { slug: post.slug },
props: { post },
}));
}
const { post } = Astro.props;
const { Content } = await post.render();
---
<html>
<head>
<title>{post.data.title}</title>
<meta name="description" content={post.data.description} />
</head>
<body>
<article>
<h1>{post.data.title}</h1>
<time>{post.data.pubDate.toLocaleDateString()}</time>
{post.data.tags && (
<div>
{post.data.tags.map(tag => (
<span class="tag">{tag}</span>
))}
</div>
)}
<Content />
</article>
</body>
</html>
Astro PagesCMS simple workflow
Here’s how the Astro CMS workflow works:
- Create content: Use PagesCMS to create and edit Astro blog posts
- Git magic: PagesCMS saves changes to your Astro project GitHub repo
- Type checking: Astro content collections make sure content follows your rules
- Build and deploy: Your build process (GitHub Actions, Netlify, etc.) builds your Astro site and puts it live
- Live site: New content shows up on your Astro website
Conclusion
By putting PagesCMS and Astro together, you get:
- Easy editing: Rich-text editor with media support for Astro content
- Git workflow: Version control for all your Astro blog content changes
- Auto publishing: Easy publish process for Astro websites
This Astro CMS setup works great for Astro blogs, documentation sites, or any Astro project where you want an free, OpenSource and easy CMS with the speed of a static site.
You get the best of both worlds: content creators get a friendly interface, while developers keep full control over the Astro codebase and how it gets published.
/Michael Andreuzza