Why Sanity Over a Traditional CMS for Your Astro Site
Traditional CMSes couple your content to their rendering layer. Sanity treats content as structured data you query with GROQ and render however you want, whether that's an Astro site, a mobile app, or an API response.
April 13, 2026
Content as data, not pages
Traditional CMSes organize content around pages and templates. Your content structure mirrors your current website layout, which works fine until you need that same content somewhere else: a mobile app, an email campaign, a different site.
Sanity takes a different approach. Every piece of content is structured data with a schema you define in code. A blog post isn't a page with HTML in a database. It's a document with typed fields that you can query and render in any context.
This matters for Portable Text especially. Instead of storing rich text as HTML strings, Sanity stores it as a structured JSON tree. You can render Portable Text into Astro components, React elements, plain HTML, Markdown, or any other format. The content isn't locked into one presentation layer.
The practical result: the same product description can power a web page, an API response, a mobile screen, and an email template without duplication or reformatting.
GROQ replaces rigid REST endpoints
Traditional CMSes typically give you fixed API responses. You either get every field on a document or you write custom endpoints to get a subset. Need related content? That's another API call. Need a specific projection? Another custom endpoint.
GROQ is Sanity's query language, and it lets you ask for exactly the data you need in a single expression. Filter, join references, reshape the response, all in one query.
For example, fetching blog posts with their resolved author names and category titles is one GROQ query, not three chained REST calls:
*[_type == "post"]{
title,
"author": author->name,
"categories": categories[]->title
} You define the exact shape of the response, so there's no overfetching and no underfetching. This is valuable with Astro, where you want to fetch exactly the data a page needs at build time or request time.
Real-time collaboration that actually works
Traditional CMSes use record locking: one editor at a time per document, everyone else waits. This makes sense when your CMS stores content as mutable rows in a database, but it creates bottlenecks for teams.
Sanity supports real-time multiplayer editing. Multiple editors can work on the same document simultaneously, and changes sync across all connected sessions without conflicts. The underlying architecture handles merging automatically.
Draft and published states are separate, so editors can iterate freely without affecting the live site. When a document is ready, publishing is an explicit action. And because every change is tracked, you can always see who changed what and roll back if needed.
A developer-controlled schema
With traditional CMSes, you typically define your content model through an admin interface, clicking through forms to add fields, configure validation, and set up relationships. The content model lives in the CMS, not in your codebase.
Sanity flips this. Your content schema lives in your repository, defined with defineType and defineField in TypeScript:
defineType({
name: "post",
type: "document",
fields: [
defineField({ name: "title", type: "string" }),
defineField({
name: "slug",
type: "slug",
options: { source: "title" }
}),
defineField({ name: "body", type: "blockContent" })
]
}) It's versioned in git alongside your Astro components. Schema changes go through code review, are tested in CI, and are deployed just like any other code change.
The Studio UI is generated from your schema definition and is fully customizable: custom input components, validation rules, conditional fields, and preview configurations, all in code.
This means your content model and your frontend stay in sync naturally. When you add a field to the schema, your TypeScript types update, your queries update, and your components update, all in the same pull request.
Getting started
This template ships with Sanity and Astro pre-configured so you can evaluate the workflow without setup overhead. Clone the repository, add your Sanity project ID, and deploy to see structured content, GROQ queries, and visual editing working together.
For a detailed look at what Astro brings to this stack, including islands architecture, server-side rendering, and view transitions, see Build Faster Websites with Astro and Sanity. For setup details, see the project README.
Example: Querying Content with GROQ
import { sanityClient } from "sanity:client";
import groq from "groq";
export async function getPosts() {
return await sanityClient.fetch(
groq`*[_type == "post"] | order(_createdAt desc) {
_id,
title,
slug,
excerpt,
mainImage {
...,
"alt": coalesce(alt, "")
}
}`
);
}