# Use Sanity with Astro

> Decide when Sanity beats markdown, connect it to your Astro site with the official integration, and rebuild the site automatically when editors publish.

Source: https://viralistic.nl/help/astro/sanity-for-astro

Sanity is a hosted content platform with an editing app called Sanity Studio. This guide is for developers who want editors to manage content in a friendly interface while the website stays a fast, static Astro site. You will create a Sanity project, connect it with the official `@sanity/astro` integration, fetch content with GROQ, render images and rebuild the site on every publish.

## Sanity or markdown?

Most Viralistic sites keep content as markdown in the repository. Choose Sanity only when it solves a real problem.

| Keep markdown in the repo                                       | Choose Sanity                                        |
| --------------------------------------------------------------- | ---------------------------------------------------- |
| A few people edit, and they are fine with GitHub or Claude Code | Many editors who need a visual editor and roles      |
| Content changes weekly or less                                  | Content changes daily, such as news or listings      |
| Pages follow fixed layouts                                      | Content is reused across sites, apps or newsletters  |
| No extra service to pay for or maintain                         | Editors need drafts, scheduling and media management |

## Create a Sanity project and Studio

1. In a separate folder or repository, run:

```bash
pnpm create sanity@latest
```

2. Log in, create a new project and keep the default `production` dataset.
3. Pick a clean template, then describe your content types (for example `post` with `title`, `slug`, `description`, `mainImage` and `body`) in the Studio's schema files.
4. Start the Studio locally with `pnpm dev` and add a test document.
5. Deploy the Studio so editors can reach it on a `sanity.studio` address:

```bash
pnpm dlx sanity@latest deploy
```

### Standalone or embedded Studio

Sanity recommends deploying the Studio on its own, as above. You can also embed it in the Astro site at a path like `/admin` with the `studioBasePath` option. That requires `@astrojs/react`, a `sanity.config.ts` file, your site's addresses in the project's CORS origins (with credentials allowed) and a rewrite so Studio sub-pages do not return a 404 on a static host:

```toml
[[redirects]]
  from = "/admin/*"
  to = "/admin"
  status = 200
```

> **Tip:** Viralistic sites ship no React. A standalone Studio keeps it that way and keeps editor traffic away from your website.

## Connect Astro to Sanity

1. In the Astro project, add the integration:

```bash
pnpm astro add @sanity/astro
```

2. Configure it in `astro.config.ts`, next to `fulldevIntegration()`:

```ts
import sanity from "@sanity/astro"

export default defineConfig({
  integrations: [
    fulldevIntegration({/* site, name, favicon, i18n */}),
    sanity({
      projectId: "your-project-id",
      dataset: "production",
      apiVersion: "2026-03-01",
      useCdn: false,
    }),
  ],
})
```

3. Add the type reference to `src/env.d.ts`:

```ts
/// <reference types="astro/client" />
/// <reference types="@sanity/astro/module" />
```

Use `useCdn: false` for static builds: queries run once at build time, and you want the freshest content.

> **Warning:** If you need a token (for drafts or private datasets), store it in an environment variable without the `PUBLIC_` prefix. Anything prefixed `PUBLIC_` can end up in the browser.

## Fetch content with GROQ

The integration exposes a ready-made client:

```astro
---
import { sanityClient } from "sanity:client"

const posts = await sanityClient.fetch(
  `*[_type == "post" && defined(slug.current)] | order(publishedAt desc){
    title, description, "slug": slug.current, mainImage
  }`
)
---
```

To keep the Viralistic architecture, do not scatter queries through components. Fetch whole page sets in one place, give each entry a `type` and validate it with a strict schema, so the single catch-all route and the layout renderer handle Sanity pages exactly like markdown pages.

## Render images

Use `@sanity/image-url` so Sanity's image CDN resizes and converts images for you:

```ts
import { createImageUrlBuilder } from "@sanity/image-url"
import { sanityClient } from "sanity:client"

const builder = createImageUrlBuilder(sanityClient)

export const urlFor = (source: Parameters<typeof builder.image>[0]) =>
  builder.image(source)
```

In a block, request the size you display: `urlFor(image).width(1280).auto("format").url()`. Add a required `alt` field to every image type in your Sanity schema, because every image on a Viralistic site needs alt text. Do not pass Sanity image URLs through Astro's `<Image>` component; that processes them twice.

## Rebuild the site when editors publish

A static site only shows new content after a new build. Connect the two with a build hook:

1. In Netlify, open the project configuration, find **Build hooks** under the continuous deployment settings and add a hook for your main branch.
2. Copy the hook URL.
3. At sanity.io/manage, open your project, go to **API**, then **Webhooks**, and create a webhook that posts to the hook URL for the `production` dataset on create, update and delete.
4. Leave any option to fire on drafts switched off, so only published changes trigger a build.
5. Publish a test change and watch a new deploy start in Netlify.

> **Note:** Every publish starts a full build, which counts towards your Netlify build usage. For sites with many small edits a day, consider batching or server rendering instead.

If you would rather have Sanity set up for you, book a strategic call: https://calendly.com/marrallisa/30min

## Next steps

- [Edit text and pages](https://viralistic.nl/help/astro/edit-content)
- [Images and media](https://viralistic.nl/help/astro/images-and-media)
- [Deploy to Netlify](https://viralistic.nl/help/astro/deploy-to-netlify)
