How to reference a schema from a schema in Sanity.io
Yes, exactly! The approach you're showing in your second example is the correct way to handle self-referencing schemas in Sanity. You reference the schema type by its name as a string.
Your code is spot-on:
defineArrayMember({
name: "section",
title: "Section",
type: "section", // <-- This string reference prevents circular dependency issues
})This works because Sanity's schema system resolves type references by name at runtime, not at definition time. When you use type: "section" as a string, you're telling Sanity "look up the type named 'section' when you need it" rather than trying to import and nest the actual schema object directly.
Why this works
The key difference is:
- Importing the schema object directly (like
defineArrayMember(section)) would create a circular JavaScript module dependency - Referencing by type name (like
type: "section") lets Sanity's schema registry handle the lookup after all schemas are loaded
This pattern works for any self-referencing or mutually-referencing schemas. You can have deeply nested structures like sections within sections within sections, and Sanity will handle it gracefully.
Additional tips
- Make sure your
nameproperty in the top-leveldefineTypematches what you reference in thetypeproperty - Each array item will automatically get a
_keyproperty that Sanity uses to track items, which is especially important for recursive structures - You can mix self-references with other types in the same array's
ofarray, just like you're doing withcodeBlock
This is a common pattern for building flexible, nested content structures like navigation menus, nested comments, organizational hierarchies, or in your case, nested sections with blocks. The array fields documentation covers more about how arrays work with multiple member types, which applies to recursive structures as well.
Sanity – Build the way you think, not the way your CMS thinks
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.