How to Use Keystatic with Astro: Complete Guide
Step-by-step guide to integrating Keystatic with your Astro website.
Keystatic is a git-based CMS that stores your content directly in your repository as Markdown, MDX, JSON, or YAML files. There is no external database, no third-party API, and no monthly bill. You get a clean admin UI for editing content, and everything commits straight to your repo. For solo developers and small teams that already use Git, this is the most straightforward CMS setup you can get with Astro.
The Astro team includes Keystatic in their official integrations, so the setup is first-class.
Prerequisites
- Node.js 18+
- An Astro project (
npm create astro@latest) - A GitHub account (for the GitHub mode, optional for local development)
Installation
Add Keystatic using the Astro CLI:
npx astro add @keystatic/astro
npm install @keystatic/core
If Astro prompts you about the react integration, say yes. Keystatic's admin UI is built with React.
Configuration
Create a keystatic.config.ts file in your project root:
// keystatic.config.ts
import { config, fields, collection } from "@keystatic/core";
export default config({
storage: {
kind: "local", // Use "github" for production with GitHub
},
collections: {
posts: collection({
label: "Blog Posts",
slugField: "title",
path: "src/content/posts/*",
format: { contentField: "content" },
schema: {
title: fields.slug({ name: { label: "Title" } }),
description: fields.text({ label: "Description" }),
publishDate: fields.date({ label: "Publish Date" }),
draft: fields.checkbox({ label: "Draft", defaultValue: false }),
content: fields.markdoc({
label: "Content",
}),
},
}),
},
});
Update your astro.config.mjs to include the integration:
// astro.config.mjs
import { defineConfig } from "astro/config";
import react from "@astrojs/react";
import keystatic from "@keystatic/astro";
export default defineConfig({
integrations: [react(), keystatic()],
output: "hybrid",
});
Keystatic requires hybrid rendering because the admin UI runs server-side. Your blog pages can still be statically generated.
Basic Usage
Once configured, start your dev server and visit http://localhost:4321/keystatic to access the admin panel. You can create and edit posts through the UI, and Keystatic saves them as files in your src/content/posts/ directory.
To display posts on your site, read them using Astro's content collections:
---
// src/pages/blog/index.astro
import { getCollection } from "astro:content";
import BaseLayout from "../../layouts/BaseLayout.astro";
const posts = (await getCollection("posts"))
.filter((post) => !post.data.draft)
.sort((a, b) => new Date(b.data.publishDate).getTime() - new Date(a.data.publishDate).getTime());
---
<BaseLayout title="Blog">
<h1>Blog</h1>
<ul>
{posts.map((post) => (
<li>
<a href={`/blog/${post.slug}`}>
<h2>{post.data.title}</h2>
<time>{new Date(post.data.publishDate).toLocaleDateString()}</time>
</a>
</li>
))}
</ul>
</BaseLayout>
For individual post pages:
---
// src/pages/blog/[slug].astro
import { getCollection } from "astro:content";
import BaseLayout from "../../layouts/BaseLayout.astro";
export async function getStaticPaths() {
const posts = await getCollection("posts");
return posts.map((post) => ({
params: { slug: post.slug },
props: { post },
}));
}
const { post } = Astro.props;
const { Content } = await post.render();
---
<BaseLayout title={post.data.title}>
<article>
<h1>{post.data.title}</h1>
<Content />
</article>
</BaseLayout>
Production Tips
Switch to GitHub storage for production. Change
storage.kindto"github"and add your repo details. This way, edits made through the Keystatic admin create commits directly to your repository, triggering automated builds.
Protect the admin route. In production, the /keystatic route should only be accessible to authenticated users. Keystatic supports GitHub OAuth for this, so only collaborators on your repo can access the editor.
Use Markdoc for content. Keystatic supports both Markdown and Markdoc. Markdoc gives you custom components and variables inside your content, which is more powerful than plain Markdown for structured content.
Leverage Astro content collections. Since Keystatic writes standard files, Astro's built-in content collections handle validation, typing, and querying automatically. No extra data fetching layer needed.
Version your content with Git. Every edit is a commit. You get full history, diffs, rollbacks, and branch-based workflows for free. This is a real advantage over database-backed CMS platforms.
Alternatives to Consider
- TinaCMS if you want a similar git-based approach but with visual inline editing directly on the page.
- Strapi if you need a more traditional CMS with user roles, permissions, and a REST/GraphQL API for multiple consumers.
- Sanity if your project requires real-time collaboration and you prefer a hosted backend.
Wrapping Up
Keystatic removes the complexity of external CMS services entirely. Your content lives in your repo, your admin UI runs alongside your Astro site, and there is no API to manage or billing to track. For developers who want a clean editing experience without the overhead of a hosted CMS, Keystatic and Astro is a hard combination to beat.
Related Articles
How to Use Algolia with Astro: Complete Guide
Step-by-step guide to integrating Algolia with your Astro website.
How to Integrate Auth0 with Astro: Complete Guide
Step-by-step guide to integrating Auth0 with your Astro website. Setup, configuration, and best practices.
How to Use AWS Amplify with Astro: Complete Guide
Step-by-step guide to integrating AWS Amplify with your Astro website.