How to construct proper URLs from Sanity references with different content types?

8 replies
Last updated: Sep 1, 2021
I am using Sanity with Nextjs.Let say that i have pages, blogPage and authorPage.
Then i want to create internalLink. I am creating references to those 3 types.
how should i use slug i am getting in correct way?
I do not want to omit /blog/ or /author/ . Page type can also be /whatever

<NextLink href={slug}>{children}</ NextLink> 
AI Update

The key to handling internal links with different document types in Sanity and Next.js is to include information about the document's type in your GROQ query, then use that to construct the appropriate path prefix.

Schema Setup

First, create a reference field for your internal links:

defineField({
  name: 'internalLink',
  type: 'reference',
  to: [
    {type: 'page'},
    {type: 'blogPage'},
    {type: 'authorPage'}
  ]
})

GROQ Query Pattern

When querying your references, fetch both the slug AND the document type:

*[_type == "yourDocType"] {
  ...,
  internalLink-> {
    _type,
    slug
  }
}

Helper Function for Path Generation

Create a helper function to map document types to their URL prefixes:

function getPathFromReference(reference: {_type: string, slug: {current: string}}) {
  if (!reference?.slug?.current) return '/';
  
  const pathMap: Record<string, string> = {
    'page': '',  // root level pages
    'blogPage': '/blog',
    'authorPage': '/author'
  };
  
  const prefix = pathMap[reference._type] || '';
  return `${prefix}/${reference.slug.current}`;
}

Usage in Your Component

import NextLink from 'next/link';

<NextLink href={getPathFromReference(internalLink)}>
  {children}
</NextLink>

Alternative: Store Path Prefix in Schema

You can also add a pathPrefix field to each document type and query it directly:

defineField({
  name: 'pathPrefix',
  type: 'string',
  initialValue: '/blog',
  hidden: true
})

Then query:

internalLink-> {
  pathPrefix,
  "slug": slug.current
}

And construct the URL:

const href = `${internalLink.pathPrefix}/${internalLink.slug}`;

This pattern ensures your internal links always maintain the correct path structure based on the document type being referenced. The helper function approach is generally cleaner since it centralizes your routing logic in one place, making it easier to maintain when your site structure changes.

For more information on working with reference fields in Sanity, check out the official documentation.

Show original thread
8 replies
Hei!Yes and no.
In simple case i just query for slug and pass it to `&lt;NextLink href={
${props.mark.slug}
}&gt;` like that.Let say that
slug = "blog-name"
Some “magic” is happening and Next takes it to
/blog/blog-name
.First i was thinking that it will be best to query for type to and do something like that
`&lt;NextLink href={
${props.mark.type}/${props.mark.slug}
}&gt;`but “magic” is happening and it takes me to
/blog/blog/blog-name
or
/author/author-name
So if i will make sure that slugs er unik thats works.

I have dose edge cases.
Where
slug = "blog"
or
slug = "author"
but i wish to navigate to
/blog
or
/author
page.
The solution i came with is to use
validation and check if slug is unik
I am looking for best practice solution. Please give me some feedback
🙂
Hei!Yes and no.
In simple case i just query for slug and pass it to `&lt;NextLink href={
${props.mark.slug}
}&gt;` like that.Let say that
slug = "blog-name"
Some “magic” is happening and Next takes it to
/blog/blog-name
.First i was thinking that it will be best to query for type to and do something like that
`&lt;NextLink href={
${props.mark.type}/${props.mark.slug}
}&gt;`but “magic” is happening and it takes me to
/blog/blog/blog-name
or
/author/author-name
So if i will make sure that slugs er unik thats works.

I have dose edge cases.
Where
slug = "blog"
or
slug = "author"
but i wish to navigate to
/blog
or
/author
page.
The solution i came with is to use
validation and check if slug is unik
I am looking for best practice solution. Please give me some feedback
🙂
Ah, interesting! What does your file structure under
/pages
look like? I think that's where it's getting that extra
/blog/.
Ah, interesting! What does your file structure under
/pages
look like? I think that's where it's getting that extra
/blog/.
The interesting ting is that i do not have any of those problems any more. And i did not do nothing.pages/blog/[slug].tsx /index.tsx is the structure.
But i hope that `&lt;NextLink href={
${props.mark.type}/${props.mark.slug}
}&gt;` is the right way to go?
Looks good! Strange that it suddenly started working, though!
Thanks Racheal
Thanks Racheal

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?