How to Use Sanity with Astro: Complete Guide
Step-by-step guide to integrating Sanity with your Astro website. Installation, configuration, and best practices.
Sanity is a composable content platform with real-time collaboration and a ridiculously flexible schema system. Pair it with Astro and you get a content-driven site that is fast to build, fast to load, and easy for your team to manage. Astro even has an official Sanity integration, which makes the setup straightforward.
Prerequisites
- Node.js 18+
- An Astro project (
npm create astro@latest) - A Sanity account and project (free tier available at sanity.io)
Installation
Install the official Astro Sanity integration and the Sanity client:
npx astro add @sanity/astro
npm install @sanity/image-url
The astro add command will automatically update your astro.config.mjs.
Configuration
After running the add command, update your Astro config with your Sanity project details:
// astro.config.mjs
import { defineConfig } from "astro/config";
import sanity from "@sanity/astro";
export default defineConfig({
integrations: [
sanity({
projectId: "your_project_id",
dataset: "production",
useCdn: true,
apiVersion: "2026-02-01",
}),
],
});
You can find your project ID in the Sanity dashboard at manage.sanity.io.
Basic Usage
With the integration installed, you can use the built-in sanityClient anywhere in your Astro components. Let's fetch a list of blog posts using GROQ, Sanity's query language:
---
// src/pages/blog/index.astro
import { sanityClient } from "sanity:client";
import BaseLayout from "../../layouts/BaseLayout.astro";
const posts = await sanityClient.fetch(
`*[_type == "post"] | order(publishedAt desc) {
title,
slug,
publishedAt,
excerpt,
"imageUrl": mainImage.asset->url
}`
);
---
<BaseLayout title="Blog">
<h1>Blog</h1>
<ul>
{posts.map((post) => (
<li>
<a href={`/blog/${post.slug.current}`}>
<h2>{post.title}</h2>
<p>{post.excerpt}</p>
</a>
</li>
))}
</ul>
</BaseLayout>
Fetching Data for Dynamic Pages
Generate individual post pages with getStaticPaths:
---
// src/pages/blog/[slug].astro
import { sanityClient } from "sanity:client";
import { PortableText } from "@portabletext/react";
import BaseLayout from "../../layouts/BaseLayout.astro";
export async function getStaticPaths() {
const posts = await sanityClient.fetch(
`*[_type == "post"]{ slug }`
);
return posts.map((post) => ({
params: { slug: post.slug.current },
}));
}
const { slug } = Astro.params;
const post = await sanityClient.fetch(
`*[_type == "post" && slug.current == $slug][0] {
title,
body,
publishedAt,
"imageUrl": mainImage.asset->url
}`,
{ slug }
);
---
<BaseLayout title={post.title}>
<article>
<h1>{post.title}</h1>
{post.imageUrl && <img src={post.imageUrl} alt={post.title} />}
<div set:html={toHTML(post.body)} />
</article>
</BaseLayout>
For rendering Portable Text (Sanity's rich text format), you can use @portabletext/astro or convert to HTML with a custom serializer.
npm install @portabletext/astro
Production Tips
Enable the CDN. Set
useCdn: truein your config for production builds. This serves cached responses from Sanity's edge network and is significantly faster than hitting the API directly.
Use GROQ projections. Only fetch the fields you actually need. Instead of *[_type == "post"], project specific fields. It reduces payload size and speeds up queries.
Set up on-demand revalidation. Configure a Sanity webhook to trigger rebuilds when content changes. Point it at your deploy hook URL from Vercel or Netlify.
Optimize images with the image URL builder. Use @sanity/image-url to generate responsive, optimized image URLs with width, height, and format parameters built in.
Use Sanity's Visual Editing. With the studioUrl option in the integration config, you can enable click-to-edit overlays that let editors jump from the live site straight into the Studio.
Alternatives to Consider
- Contentful if you need enterprise-grade content infrastructure with strict content modeling and approval workflows.
- TinaCMS if you want a git-backed CMS with visual editing and Markdown/MDX support. Good for developer blogs.
- Keystatic if you prefer zero external services. Content lives in your git repo.
Wrapping Up
Sanity and Astro are one of the best CMS and framework combos for content sites in 2026. The official integration handles the boring setup, GROQ makes querying intuitive, and the Studio gives your content team a great editing experience. Hard to go wrong here.
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.