How to handle slugs for singleton pages in Sanity navigation?

5 replies
Last updated: Nov 29, 2025
I have a singleton Homepage and multiple Page type for all other pages. Each page has a slug which works great when creating an navigation array for the website. But my biggest problem is how can I set a menu Title + Link for the singleton using a slug? Same story for the Blog overview this is a singleton type too and have no slug.
I was thinking to have a slug field with a default fixed slug like "frontpage" and set it read only, so this way I can select it from a reference?

Any tips please
🙂 I am stuck at this pretty confusing.. on how to deal with this.
Home & Blog => Singleton no slugs.
Pages: About, Contact, Team etc with slugs.
AI Update

Your approach of adding a slug field with a fixed default value to singletons is actually a solid pattern! This is a common and practical solution that many Sanity developers use. Let me break down a few approaches:

Add a slug field to your singleton documents with a fixed, read-only value:

// homepage.js (singleton)
{
  name: 'homepage',
  type: 'document',
  fields: [
    {
      name: 'slug',
      type: 'slug',
      initialValue: {
        current: '/'
      },
      readOnly: true,
      hidden: true // Optional: hide it from editors since it never changes
    },
    // ... other fields
  ]
}

// blogOverview.js (singleton)
{
  name: 'blogOverview',
  type: 'document',
  fields: [
    {
      name: 'slug',
      type: 'slug',
      initialValue: {
        current: '/blog'
      },
      readOnly: true,
      hidden: true
    },
    // ... other fields
  ]
}

This way, when you create navigation arrays using references, all documents (singletons and regular pages) have a consistent slug field you can query.

Approach 2: Virtual Slug in Your Navigation Query

Instead of storing slugs on singletons, handle them in your GROQ query:

*[_type == "navigation"][0] {
  items[] {
    title,
    "slug": select(
      reference->_type == "homepage" => "/",
      reference->_type == "blogOverview" => "/blog",
      reference->slug.current
    ),
    reference-> {
      _type,
      title
    }
  }
}

This keeps your schema cleaner but puts the logic in your queries.

Approach 3: Custom Navigation Object

Create a dedicated navigation schema where you can set custom paths for singletons:

{
  name: 'navigation',
  type: 'document',
  fields: [
    {
      name: 'items',
      type: 'array',
      of: [{
        type: 'object',
        fields: [
          {name: 'title', type: 'string'},
          {name: 'reference', type: 'reference', to: [{type: 'homepage'}, {type: 'page'}, {type: 'blogOverview'}]},
          {
            name: 'customPath',
            type: 'string',
            description: 'Override path for singletons (e.g., "/" for homepage)'
          }
        ]
      }]
    }
  ]
}

Then in your frontend, use customPath if it exists, otherwise fall back to reference.slug.current.

My Recommendation

Go with Approach 1 (fixed slugs on singletons). It's the most straightforward and keeps your data consistent. The slug field type supports this perfectly with initialValue and readOnly options. This pattern allows you to:

  • Use the same reference-based navigation structure everywhere
  • Query all navigable documents consistently
  • Keep your frontend logic simple
  • Still maintain the singleton pattern for content management

The slight "weirdness" of having a slug on a singleton is worth the consistency it brings to your navigation system. Many Sanity projects use this exact pattern successfully!

Show original thread
5 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?