Best way to model recursively nested documents in Sanity?
You're right, this is a common question! For your nested region structure (UK → England → Oxfordshire), the most straightforward approach is to use self-referencing documents with a parent reference field.
Here's how to model it:
export default defineType({
name: 'region',
type: 'document',
fields: [
{
name: 'name',
type: 'string',
title: 'Region Name'
},
{
name: 'parent',
type: 'reference',
title: 'Parent Region',
to: [{type: 'region'}],
// Optional: helps prevent circular references
validation: Rule => Rule.custom((parent, context) => {
if (parent?._ref === context.document?._id) {
return 'A region cannot be its own parent'
}
return true
})
}
]
})With this structure:
- UK would have no parent (top-level)
- England would reference UK as its parent
- Oxfordshire would reference England as its parent
- Gibraltar would reference UK as its parent
- Washington would reference USA as its parent
Querying the hierarchy
To fetch a region with all its children, you can use GROQ:
*[_type == "region" && _id == $regionId][0]{
_id,
name,
"children": *[_type == "region" && parent._ref == ^._id]{
_id,
name
}
}For the full tree from a root region, you'd need to query recursively or fetch all regions and build the tree client-side.
Alternative: Array of children
You could also model this top-down with an array of child references:
{
name: 'children',
type: 'array',
of: [{type: 'reference', to: [{type: 'region'}]}]
}However, the parent reference approach is generally better because:
- The reference field appears where editors naturally work (on the child document)
- It's easier to prevent orphaned documents
- References are bidirectional when querying, so you can traverse both directions even though the UI only shows the field on the child
The parent reference approach scales well for unlimited nesting depth. Just be mindful that very deep hierarchies might require multiple queries or client-side tree building for full traversal. Sanity naturally supports these graph-like content structures through its reference system, making it flexible for complex hierarchical relationships.
Show original thread6 replies
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.