How to reference nested array objects in Sanity schema?

26 replies
Last updated: Jan 28, 2026
Hi all,
I have a bit of a convoluted question about structuring a schema to reference content within another schema's nested array. Bear with me please, I hope to make this as clear as possible!

At the highest level, within
_type == "residences"
, I have an array called
residencesData
which defines attributes associated to a given artist in residence ("person"), such as a title, slug, bio, etc. On
/residences
, I map all of the objects in this array (aka the list of artists).
Once a user navigates to a particular artist's page,
/residences/[artistName]
, I query for this given artist's info on that page using the query below:
export const residenciesPageQuery = groq`
  *[$slug in residencesData[].slug.current][0] {
    _id,
    "person": residencesData[slug.current == $slug][0] {
      _key,
      title, 
      type,
      bio,
      photoCredit,
      contributions[]->{
        "imageUrl": mainImage.asset->url,
        "lqip": mainImage.asset->metadata.lqip,
        slug,
      },
      portfolio, 
      instagram,
      "imageUrl": mainImage.asset->url,
      "lqip": mainImage.asset->metadata.lqip,
      "slug": slug.current,
    }
  }
`;
Crucially, this person (the artist in residence) also contributes to a presentation text,
texteDePresentation
, which I'll need to place on
/residences/[artistName]/[texteDePresentation]


My question is as follows: How can I create a reference to a given
person
within my
texteDePresentation
schema?

    {
      name: "associatedArtist",
      title: "Artiste en résidence associé",
      description:
        "Ceci est nécessaire pour le bouton 'retour' trouvé à la fin du texte",
      type: "array",
      of: [{ type: "reference", to: { type: " ????? " } }],
      validation: (Rule) => Rule.required(),
    },
AI Update

I understand your challenge! You have artists stored as objects within a residencesData array on a residences document, and you want to reference those nested array items from your texteDePresentation schema. Unfortunately, Sanity references can only point to top-level documents, not to objects nested within arrays.

Here are your best options:

The most Sanity-idiomatic approach is to restructure your schema so each artist is its own document:

// schemas/artist.js
{
  name: 'artist',
  type: 'document',
  fields: [
    { name: 'title', type: 'string' },
    { name: 'slug', type: 'slug' },
    { name: 'bio', type: 'text' },
    { name: 'photoCredit', type: 'string' },
    { name: 'portfolio', type: 'url' },
    { name: 'instagram', type: 'url' },
    { name: 'mainImage', type: 'image' },
    // ... other fields
  ]
}

// schemas/residences.js
{
  name: 'residences',
  type: 'document',
  fields: [
    {
      name: 'residencesData',
      type: 'array',
      of: [{ type: 'reference', to: [{ type: 'artist' }] }]
    }
  ]
}

// schemas/texteDePresentation.js
{
  name: 'texteDePresentation',
  type: 'document',
  fields: [
    {
      name: 'associatedArtist',
      title: 'Artiste en résidence associé',
      type: 'reference', // single reference, not array
      to: [{ type: 'artist' }],
      validation: (Rule) => Rule.required(),
    }
  ]
}

This gives you proper references and makes your queries cleaner.

Option 2: Store the _key Value

If restructuring isn't feasible, you can store the _key of the array item and manually join the data in your queries:

// In texteDePresentation schema
{
  name: 'associatedArtistKey',
  title: 'Artiste en résidence associé',
  type: 'string', // Store the _key as a string
  validation: (Rule) => Rule.required(),
}

Then in your GROQ query:

*[_type == "texteDePresentation" && slug.current == $slug][0] {
  ...,
  "associatedArtist": *[_type == "residences"][0]
    .residencesData[_key == ^.associatedArtistKey][0]
}

This is more fragile and harder to maintain, but it works if you can't restructure.

Option 3: Duplicate the Reference

Store a reference to the parent residences document plus the artist's slug:

{
  name: 'associatedArtist',
  type: 'object',
  fields: [
    {
      name: 'residencesDoc',
      type: 'reference',
      to: [{ type: 'residences' }]
    },
    {
      name: 'artistSlug',
      type: 'string'
    }
  ]
}

The first option is really the way to go if possible. Sanity's reference system is designed for document-to-document relationships, and fighting against that pattern usually creates more complexity down the road. Making artists top-level documents also gives you better content management, easier querying, and the ability to reference artists from anywhere in your content.

Show original thread
26 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.

Was this answer helpful?