How to resolve references in resolveProductionUrl for preview iframe?

11 replies
Last updated: Mar 4, 2022
Hi!
I'm setting up a preview iframe pane, and creating a
resolveProductionUrl
function, like in many of the guides suggests. I have done it before, and it works great. Usually.
However, now I want to construct the URL from a referenced field. I have an
article
schema type, that has a reference to a
category
type. The URL is basically
${article.category.slug.current}/${article.slug.current}
. However, the doc passed by the
S.view.options({ url: resolveProductionUrl })
function (where S is the structure builder) doesn't resolve references (so
article.category
is just a regular ref object.
How can I resolve that doc?
AI Update

The document passed to resolveProductionUrl doesn't include resolved references by default - you're absolutely right. You need to fetch the full document data yourself using Sanity's client within the resolveProductionUrl function.

The key is making resolveProductionUrl an async function and using a GROQ query with the reference operator (->) to dereference the category:

import { client } from './sanityClient' // Your configured client

export const resolveProductionUrl = async (doc) => {
  if (doc._type !== 'article') return undefined
  
  // Fetch the document with the resolved category reference
  const article = await client.fetch(
    `*[_id == $id][0]{
      "categorySlug": category->slug.current,
      "articleSlug": slug.current
    }`,
    { id: doc._id }
  )
  
  if (!article?.categorySlug || !article?.articleSlug) return undefined
  
  const baseUrl = 'https://your-site.com' // or process.env.NEXT_PUBLIC_SITE_URL
  return `${baseUrl}/${article.categorySlug}/${article.articleSlug}`
}

The category-> syntax in the GROQ query tells Sanity to resolve the reference and fetch the actual category document. Then category->slug.current gets the slug from that resolved document.

A few things to note:

  1. Make it async: The function needs to be async since you're fetching data
  2. Use the document's _id: The doc parameter has the _id, which is stable and works even for drafts
  3. Handle missing data: Always check that both slugs exist before constructing the URL
  4. Consider drafts: If you want preview URLs for draft documents, you might need to query *[_id in [$id, "drafts." + $id]] to handle both published and draft versions

If you're using the sanity-plugin-iframe-pane, the same approach works - just pass your async resolveProductionUrl function to the plugin's url option.

Show original thread
11 replies
Anyone know how to resolve references in the structure builder?
What does your
resolveProductionUrl
function look like?
It's pretty basic

export const resolveProductionUrl = (doc: any) => {
  const host = window.location.href.includes("localhost")
    ? "<http://localhost:3000>"
    : "<https://production.domain>";

  return `${host}/${doc.category.slug?.current}/${doc.slug.current}?preview=${process.env.SANITY_PREVIEW_SECRET}`;
};
However,
doc.category
is just an object containing a
_ref
to the category ID
Ah got it! So, set up that way, your function has no way to resolve the category reference. You'll have to import the client:
import client from "part:@sanity/base/client"

const sanityClient = client.withConfig({apiVersion: '2021-03-25'})
Then fetch the category values before returning the url.
Ah got it! So, set up that way, your function has no way to resolve the category reference. You'll have to import the client:
import client from "part:@sanity/base/client"

const sanityClient = client.withConfig({apiVersion: '2021-03-25'})
Then fetch the category values before returning the url.
Oh that’s how that’s done within the studio. Are there docs about the studio client I missed somehow?
Thanks!
I know it exists in the docs, but I can't remember where. I'll look around for it.
I know it exists in the docs, but I can't remember where. I'll look around for it.
Well, don’t spent your time doing that. I’ll find it myself. Thanks for showing me though 😍
Well, don’t spent your time doing that. I’ll find it myself. Thanks for showing me though 😍

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?