How to reference nested objects with slugs in Sanity Table of Contents?

9 replies
Last updated: Aug 7, 2020
I've made a ToC similar to https://www.knutmelvaer.no/blog/2020/04/a-practical-application-of-the-web-project-book/#5792a4ffe753 . But I've also added slug field to the children, so I can build Gatsby pages from the ToC instead of from other documents. But I want to be able to reference these in other objects (
toc.link
in
user Y
's example) so I can link to it, but they are objects and not documents. If I change the type of
toc.link
to
document
they still can't be found in a reference. Any ideas?
AI Update

The issue you're encountering is a fundamental limitation of Sanity's reference system: references can only point to documents, not to objects. This is by design in Sanity's content architecture.

Why References Only Work with Documents

In Sanity, the reference field type creates relationships between documents by storing a _ref field that points to another document's _id. Objects (nested content within documents) don't have top-level _id values that can be referenced in this way—they only exist as part of their parent document.

Solutions for Your Table of Contents

You have a few options to work around this limitation:

1. Convert ToC Items to Documents

If you need to reference individual ToC items, make them proper documents instead of nested objects:

{
  name: 'tocItem',
  type: 'document',
  fields: [
    {name: 'title', type: 'string'},
    {name: 'slug', type: 'slug'},
    // other fields
  ]
}

Then your main ToC document can reference these:

{
  name: 'tableOfContents',
  type: 'document',
  fields: [
    {
      name: 'items',
      type: 'array',
      of: [{type: 'reference', to: [{type: 'tocItem'}]}]
    }
  ]
}

2. Use Path-Based Linking

Instead of references, store the path or identifier as a string and resolve it in your frontend:

{
  name: 'link',
  type: 'object',
  fields: [
    {name: 'tocPath', type: 'string'}, // e.g., "toc.items.0"
    {name: 'slug', type: 'slug'}
  ]
}

3. Query-Based Approach

Keep your ToC as nested objects and use GROQ queries to find and link to them by slug or other identifying properties. In your frontend, you'd query the ToC document and find the matching item by its slug.

4. Hybrid: Generate Pages from Documents

If you're generating Gatsby pages, consider whether you actually need the ToC items as separate entities. You might create a document type specifically for pages that also maintains the ToC structure:

{
  name: 'page',
  type: 'document',
  fields: [
    {name: 'title', type: 'string'},
    {name: 'slug', type: 'slug'},
    {name: 'tocPosition', type: 'number'}, // for ordering
    {name: 'parent', type: 'reference', to: [{type: 'page'}]} // for hierarchy
  ]
}

Key Takeaway

The Sanity documentation is clear on this: references work with documents only. As stated in the reference type docs, the to property must point to document types, and the system uses document _id values for the relationship. There's no way to make references point to nested objects because they lack the necessary _id infrastructure.

Choose the approach that best fits your content model—typically converting to documents if you need true referential relationships, or using path/slug-based linking if you want to keep the nested structure.

Show original thread
9 replies
If I change them to a
document
and create one from the main folder in the studio it works, but if I create one as a child of
toc.section
it doesn't show up in the reference list
Creating documents inside other documents (e.g. adding references in place) is not possible yet, unfortunately. It’s a popular feature request and definitely something we want to add support for, but it’s not quite there yet.
At the moment, creating these from the main folder in a different browser tab might be the easiest option, unless you’re willing to venture into unknown territory and try to get this to work in a custom input component
🙂
custom input component it is then, gonna look into that 🙂
Or is there any way I could help build this for you?
Appreciate this! The reason we haven't done this yet, is because of the way we do drafts at the moment, which complicates things. We want to fix that first. It’s high on our list, because obviously, being able to create and edit references in place makes total sense.
Here’s part of the discovery:
https://github.com/sanity-io/sanity/pull/1420
Yeah, that looks like a logical first step 🙂
But yeah, I'm a bit hesitant to set you out on this course, because it might be a potential rabbit hole, and then suddenly we solved it anyways
yeah, I'll do a temporary solution for now and change it when you solved it
that's totally fine

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?