Astro and Keystatic make a good pair: a generator built for fast sites and a CMS that stores content as Markdown files in your repository. The result is a static, fast website with a comfortable editing panel and no database.
If you are still deciding between frameworks, the comparison of Astro vs Next.js for landing pages may help first. Here we get straight to the integration, following the official Keystatic documentation.
What you need
- An Astro project (new with
npm create astro@latestor an existing one). - Node.js and the project in a Git repository.
- The Keystatic panel renders on the server, so to deploy it you will need an SSR adapter (for example
@astrojs/nodeor the Vercel one).
Step 1: Install the dependencies
npx astro add react markdoc
npm install @keystatic/core @keystatic/astronpx astro add react markdoc installs and configures the React integrations (the Keystatic panel uses React) and Markdoc; then we add the Keystatic packages.
Step 2: Configure Astro
Add the Keystatic integration in astro.config.mjs, next to React and Markdoc.
import { defineConfig } from 'astro/config';
import react from '@astrojs/react';
import markdoc from '@astrojs/markdoc';
import keystatic from '@keystatic/astro';
export default defineConfig({
integrations: [react(), markdoc(), keystatic()],
});Step 3: Create the Keystatic configuration
In the project root create keystatic.config.ts with your storage and your collections. It is the same configuration as in Next.js: here we define a posts collection in src/content/posts.
import { config, fields, collection } from '@keystatic/core';
export default config({
storage: {
kind: 'local',
},
collections: {
posts: collection({
label: 'Posts',
slugField: 'title',
path: 'src/content/posts/*',
format: { contentField: 'content' },
schema: {
title: fields.slug({ name: { label: 'Title' } }),
content: fields.markdoc({ label: 'Content' }),
},
}),
},
});Step 4: Open the panel
The Keystatic integration already exposes the panel. Start the project with npm run dev and open http://127.0.0.1:4321/keystatic: from there you create and edit your entries, which are saved as files in src/content/posts. Remember that, since the panel is dynamic, when deploying you need an SSR adapter configured.
Step 5: Show the content
Since the content lives in src/content, you can read it with Astro's native content collections and its getCollection function.
---
import { getCollection } from 'astro:content';
const posts = await getCollection('posts');
---
<ul>
{posts.map((post) => (
<li><a href={`/posts/${post.slug}`}>{post.data.title}</a></li>
))}
</ul>For a single entry you use getEntry and the <Content /> component that Astro generates from the Markdown. That closes the loop: you edit in the panel and Astro renders the final HTML.
What decides whether it works in production
In Astro the Keystatic panel is dynamic, and that is the difference from a purely static site: even if the public pages are generated as HTML, the editing panel needs a server to run it. That is why the SSR adapter is not a detail at the end, it is an architecture decision.
It pays to test the deployment with the adapter from the start, even before you have content. That way you find out early whether your hosting supports it and what it costs. After that: local mode to develop, GitHub for production, and the client editing without touching code.
If your team does not want to maintain a server for the panel, the honest alternative is something else: a managed CMS or editing directly in the repository. Keystatic shines when you want a friendly panel on top of files, not when you want zero infrastructure.
Do you need a fast Astro website that is easy to edit? At Codegea we build it with the right CMS for your case. See the CMS integration service or tell us about your project from the contact page.
Written by
Derian Pinto
Founder & Full Stack Developer
Founder of Codegea. Builds custom websites, stores and platforms, and integrates and supports Arc XP for media companies.
