All skills
sanity-io avatar

/sanity-best-practices

@fc8116b official
by Sanitysanity-io/agent-toolkit187 stars
30

Sanity development best practices for schema design, GROQ queries, TypeGen, Visual Editing, images, Portable Text, Studio structure, localization, migrations, Sanity Functions, webhooks, Blueprints, and framework integrations such as Next.js, Nuxt, Astro, Remix, SvelteKit, Angular, Hydrogen, and the App SDK. Use this skill whenever working with Sanity schemas, defineType or defineField, GROQ or defineQuery, content modeling, Presentation or preview setups, Sanity-powered frontend integrations, event-driven content automation, documentEventHandler, defineDocumentFunction, defineMediaLibraryAssetFunction, @sanity/functions, @sanity/blueprints, sanity.blueprint.ts, event-driven content automation, or when reviewing and fixing a Sanity codebase.

Use this Skill: https://skilld.dev/gh/sanity-io/agent-toolkit/sanity-best-practices

This session only. Nothing lands on disk.

referencesastro.md

≈1.3k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Astro & Sanity Integration Rules

1. Setup & Configuration

Scaffold a new Astro app

npm create astro@latest my-app -- --template with-tailwindcss --install --git --yes
cd my-app

--yes accepts defaults non-interactively. --install runs npm install for you, --git initializes a repo.

Installation

Add the @sanity/astro integration and the renderer/helper packages used by the examples below.

npx astro add @sanity/astro
npm install astro-portabletext @sanity/image-url groq

@sanity/astro provides the sanity:client virtual module. astro-portabletext renders Portable Text. @sanity/image-url builds image URLs. groq exports defineQuery for typed queries.

Configuration (astro.config.mjs)

Use the official @sanity/astro integration. astro.config.mjs runs at config time before Astro's env loading, so import.meta.env.PUBLIC_* is not available there — use Vite's loadEnv to read the same PUBLIC_ variables your pages will use.

import { defineConfig } from "astro/config";
import { loadEnv } from "vite";
import sanity from "@sanity/astro";

const { PUBLIC_SANITY_PROJECT_ID, PUBLIC_SANITY_DATASET } = loadEnv(
  process.env.NODE_ENV ?? "development",
  process.cwd(),
  ""
);

export default defineConfig({
  integrations: [
    sanity({
      projectId: PUBLIC_SANITY_PROJECT_ID,
      dataset: PUBLIC_SANITY_DATASET,
      useCdn: false, // False for static builds
      studioBasePath: "/admin", // Optional — only if embedding the Studio
    }),
  ],
});

Inside .astro files and components you can keep using import.meta.env.PUBLIC_SANITY_* directly; the loadEnv shim above is config-only.

Client Type Safety

Enable types in tsconfig.json.

{
  "compilerOptions": {
    "types": ["@sanity/astro/module"]
  }
}

2. Data Fetching

Basic Fetching

Use sanityClient from sanity:client in the frontmatter of your .astro files.

---
import { sanityClient } from "sanity:client";
import { defineQuery } from "groq";

const POSTS_QUERY = defineQuery(`*[_type == "post"]{title, slug}`);
const posts = await sanityClient.fetch(POSTS_QUERY);
---
<ul>
  {posts.map(post => <li>{post.title}</li>)}
</ul>

Helper Functions

It's best practice to abstract queries into a utility file (e.g., src/utils/sanity.ts).

import { sanityClient } from "sanity:client";
import { defineQuery } from "groq";

const POSTS_QUERY = defineQuery(`*[_type == "post" && defined(slug.current)]`);

export async function getPosts() {
  return await sanityClient.fetch(POSTS_QUERY);
}

Dynamic Routes ([slug].astro)

Astro hoists getStaticPaths() into a separate module context. Module-scope const declarations in the frontmatter are NOT accessible inside it — referencing them throws ReferenceError: <NAME> is not defined at request time. Define queries used by getStaticPaths inside the function, or import them from a utility module.

---
import { sanityClient } from "sanity:client";
import { defineQuery } from "groq";
import { PortableText } from "astro-portabletext";

// Module-scope queries are fine for module-scope code…
const POST_QUERY = defineQuery(`*[_type == "post" && slug.current == $slug][0]{ title, body }`);

// …but anything used inside getStaticPaths must live inside it.
export async function getStaticPaths() {
  const SLUGS_QUERY = defineQuery(
    `*[_type == "post" && defined(slug.current)]{ "params": { "slug": slug.current } }`
  );
  return await sanityClient.fetch(SLUGS_QUERY);
}

const { slug } = Astro.params;
const post = await sanityClient.fetch(POST_QUERY, { slug });
---
<article>
  <h1>{post?.title}</h1>
  {post?.body && <PortableText value={post.body} />}
</article>

3. Portable Text

Use astro-portabletext for rendering rich text.

---
import { PortableText } from "astro-portabletext";
const { body } = Astro.props;
---
<div class="prose">
  <PortableText value={body} />
</div>

4. Image Handling

Use @sanity/image-url to generate optimized image URLs.

import imageUrlBuilder from "@sanity/image-url";
import { sanityClient } from "sanity:client";

const builder = imageUrlBuilder(sanityClient);

export function urlFor(source) {
  return builder.image(source);
}

5. Visual Editing (Live Preview)

Astro handles visual editing slightly differently depending on if you are using Hybrid or Static mode.

Setup

Ensure stega is enabled in your client configuration if you want clickable overlays.

For real-time updates in the presentation tool, you typically need a React component wrapper (since Astro components don't re-render on the client) or use the View Transitions API with a loader.

Note: The @sanity/astro integration is evolving. Check the latest docs for "Visual Editing" support.

Source: SKILL.md on GitHub

2 warnings14d5 checks · Risk SAFE
  • Gen Agent Trust Hub14d

    This skill provides comprehensive Sanity.io development best practices, covering schema design, GROQ queries, and integration with major frontend frameworks. It promotes secure development habits, such as proper management of API tokens and environment variables.

  • Socket14d

    1 alert: gptAnomaly

  • Snyk14d

    Risk: LOW · No issues

  • Runlayer6mo

    8/24 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at fc8116b. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 weeks ago.

Activeupdated 2 months ago
  • Next.js
  • Nuxt
  • sanity
  • groq
  • schema
  • typegen
  • portable-text
  • visual-editing
  • astro
  • remix
  • sveltekit
  • migrations
  • localization
  • cms

README badge

README badge for sanity-io/agent-toolkit/sanity-best-practices

Provides guidelines and reference materials for Sanity schema design, GROQ queries, TypeGen, Visual Editing, Portable Text, Studio structure, localization, migrations, Sanity Functions, and framework integrations including Next.js, Nuxt, Astro, Remix, SvelteKit, Angular, and Hydrogen. Use this skill when setting up Sanity projects, designing content models, writing queries, implementing live preview, or integrating Sanity with a frontend framework.

Generated from the current SKILL.md.

Does this skill cover framework integrations like Next.js, Nuxt, and Astro?
Yes. The skill includes integration guides for Next.js, Nuxt, Astro, Remix, SvelteKit, Angular, Hydrogen, and standalone Studio patterns.
What does this skill cover for GROQ queries?
The skill provides GROQ query patterns, type safety approaches, and performance optimization guidelines, with reference materials for detailed examples.
Does this skill include guidance on Sanity Functions and event automation?
Yes. The skill covers Sanity Functions for automating content workflows, including documentEventHandler and defineDocumentFunction patterns.
Can I use this skill for schema design and content modeling?
Yes. The skill provides schema design best practices, field definitions, validation patterns, and content modeling guidance for different use cases.
Does this cover Visual Editing and live preview setup?
Yes. The skill includes guidance on the Presentation Tool, Stega, overlays, and live preview configuration for frontend frameworks.

Generated from the current SKILL.md. These answers refresh after source changes.