Handling navigation for singletons in Sanity.io without slugs
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:
Approach 1: Fixed Slug on Singletons (Recommended)
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!
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.