Astro does not force a choice between keeping every word in a repository and going back to WordPress. There is a useful third option when the frontend needs close technical control and the person publishing content needs a dashboard: Astro for the site and Sanity as a headless CMS.
I would not choose it for every project. It adds another platform, a data model, queries and a publishing workflow that someone needs to own. In return, it avoids handing a non-technical editor a fast website they can only update by asking a developer.
This portfolio does not need Sanity
The content on this site lives in MDX and Content Collections. That works because I write the posts, manage the repository and treat publishing as part of the development workflow. Bilingual copy, routes and metadata are reviewed alongside the code.
That choice does not fit every case. The services page makes clear that the websites I currently deliver do not include an editing dashboard. If a business needs to change services, publish news or update copy every week without touching a repository, that workflow becomes awkward very quickly.
That is where I would consider Sanity. Not to make Astro look more complete, but because there is a specific editorial need to meet.
What Sanity changes
A CMS is a system for managing content from a dashboard. Calling one headless means that dashboard does not include the public website a visitor sees. It stores and organises copy, images and other data, while another application decides how to present them. Here, Sanity would be where content is edited and Astro would build the pages delivered to the browser.
Sanity is a headless CMS. Content is edited in Sanity Studio and Astro queries the data to render the website. The dashboard and the public presentation do not share a theme or templates in the way a typical WordPress setup does.
That separation lets a team define what can be edited. A post can have a title, summary, slug, date, image, body and SEO fields. A service page can expose the sections and calls to action it needs without becoming an unrestricted rich-text document.
This is what I find valuable in the approach. A CMS does more than provide a place to write. It forces you to decide what information exists and how it relates. With a good model, an editor does not need HTML or component knowledge to publish. With a poor model, the result is a dashboard full of fields nobody understands.
Sanity has an official Astro integration and uses GROQ to query documents. GROQ is Sanity’s query language. It lets a page ask for exactly the documents and fields it needs, such as the three latest posts with their title, date and URL. It is closer to describing the data you want back than iterating through documents one by one in the frontend.
Astro retains control over HTML, routes, components, CSS and JavaScript. Astro describes Sanity as a CMS focused on structured content, which is the meaningful distinction here, not a promise that one tool solves every page-builder problem.
When I would choose it over WordPress
WordPress remains a sound decision when a project needs its ecosystem. WooCommerce, bookings, memberships, specific plugins or a team already comfortable with WordPress are enough reason not to switch tools because something newer exists.
I would choose Astro and Sanity when the main need is structured content with a custom frontend. That could be a company publishing case studies and articles, a services site that changes regularly, or a brand with several pages sharing authors, categories, images and reusable blocks.
This is not about Sanity being “more modern”. It is a different split of responsibilities:
- WordPress brings the CMS, frontend and extensions together in one application.
- Sanity stores and organises content. Astro decides how it becomes a public website.
The second option gives a developer more freedom, but it also leaves more decisions in their hands. Forms, redirects, analytics, caching and commercial features do not appear simply because Sanity has been installed. They still need to be designed, integrated and maintained.
What you gain and what you take on
Editors work from a dashboard while the frontend can remain a lightweight static site. Data can be reused across pages instead of copying the same wording into different files. Drafts, permissions and a Studio tailored to the project’s vocabulary are possible too.
The cost is not trivial:
- Schemas need to be designed and maintained.
- Someone needs to understand GROQ and check the data each component receives.
- There is another account, permissions setup and external service dependency.
- A static site needs a new build before published changes appear.
- Previews and Visual Editing add complexity and require server rendering in Astro.
Sanity documents that a static Astro site fetches data at build time and needs a webhook to trigger a deployment after publication. Server-rendered pages receive changes on the next load, but every request then depends on the API. The decision depends on how often content changes and who publishes it, not on the tool with the better marketing.
How I would approach the integration
Before installing anything, I would start with questions that are not about code. Who will edit, what kinds of content will they create, which parts should never be editable from the dashboard, and how quickly does a published change need to appear?
With those answers, a first Sanity model can be as small as a post document:
export default defineType({
name: 'post',
title: 'Post',
type: 'document',
fields: [
defineField({ name: 'title', title: 'Title', type: 'string' }),
defineField({ name: 'slug', title: 'URL', type: 'slug', options: { source: 'title' } }),
defineField({ name: 'publishedAt', title: 'Published at', type: 'datetime' }),
defineField({ name: 'body', title: 'Content', type: 'array', of: [{ type: 'block' }] }),
],
})Then I would add the official integration. For a static site, Sanity recommends useCdn: false during the build so it fetches the latest published content:
import { defineConfig } from 'astro/config'
import sanity from '@sanity/astro'
export default defineConfig({
integrations: [sanity({
projectId: 'your-project-id',
dataset: 'production',
apiVersion: '2026-03-01',
useCdn: false,
})],
})The integration exposes a client to Astro pages. A list should request only the fields its card needs, rather than full documents by default:
---
import { sanityClient } from 'sanity:client'
const posts = await sanityClient.fetch(`
*[_type == "post" && defined(slug.current)] | order(publishedAt desc){
title, "slug": slug.current, publishedAt
}
`)
---For static routes, getStaticPaths() fetches documents and creates one page for each slug during the build. If a query receives a slug or other variable data, I would use GROQ parameters instead of interpolating strings. The client sanitises them and avoids building queries from uncontrolled data.
The final step is essential. I would configure a Sanity webhook to the hosting provider’s build hook and test the full sequence: publish, receive the webhook, build the site, then verify the public URL. Without that test, the dashboard can say something is published while the website still serves the previous version.
The decision is still about maintenance
For a landing page that changes twice a year, Sanity is probably more system than the work requires. For this portfolio, MDX remains the most direct route. For a business with frequent publishing and non-technical editors, Sanity can remove a daily dependency on the developer without forcing WordPress to be the frontend.
I would not use the combination because “Astro CMS” happens to be a useful keyword. I would use it when a project needs a content dashboard and a custom interface that can still be maintained with clear performance, accessibility and SEO decisions.
If you are considering an Astro website and need to decide how it will be updated after launch, see how I approach web projects. The CMS, content owners and maintenance plan belong in the proposal before development begins.