Understanding and implementing productionURL in Sanity v3 using the sanity-plugin-iframe-pane plugin.

10 replies
Last updated: Dec 19, 2022
Is there an easier way to do the productionURL? dont quite understand what i need from the guide or not.
Dec 9, 2022, 12:30 PM
As far as I can recall, you need to replace:
const { client, dataset, document } = context
with:

const { getClient, dataset, document } = context
Dec 9, 2022, 1:50 PM
Guess theres an typo in the docs then? Will try later
Dec 9, 2022, 1:51 PM
user E
could you help me some more? did you also mean
context
and not
content
?
Dec 9, 2022, 1:58 PM
Yes
user U
, apologies for the typo - fixed.
If it helps, here’s my config using Sanity v3 and the
sanity-plugin-iframe-pane
plugin.

// sanity.config.js 

import { defineConfig } from 'sanity'
import { deskTool } from 'sanity/desk'
import { schemaTypes } from './schemas'
import { structure } from './studio-config/structure'
import { defaultDocumentNode } from './studio-config/views'

export default defineConfig({
    name: 'default',
    title: <title>,
    projectId: <projectId>,
    dataset: <dataset>,
    plugins: [
        deskTool({
            structure,
            defaultDocumentNode
        }),
        visionTool()
    ],
    schema: {
        types: schemaTypes
    },
})

// ./studio-config/views

import Iframe from 'sanity-plugin-iframe-pane'

// Specify document types
const previewSchemaTypes = ['page', 'post']

export const defaultDocumentNode = (S, { schemaType }) => {
    // Add previews for specified schema types
    if (previewSchemaTypes.includes(schemaType)) {
        return S.document().views([
            S.view.form(),
            S.view
                .component(Iframe)
                .title('Preview')
                .options({
                    url: (doc) => resolveProductionUrl(doc, S.context),
                    defaultSize: 'desktop',
                    reload: {
                        button: true,
                        revision: true
                    },
                    attributes: {
                        allow: 'fullscreen' // string, optional
                    }
                })
        ])
    }
}

const resolveProductionUrl = async (doc, context) => {
    const { getClient } = context

    if (previewSchemaTypes.includes(doc._type)) {
        const client = await getClient({ apiVersion: '2022-06-07' })
        const slug = await client.fetch(`*[_id == $id][0].slug.current`, { id: doc._id })

        // Build preview url
        const url = new URL(<your_base_preview_url_goes_here>)

        // Switch for resolving doc type urls
        switch (doc._type) {
            case 'page':
                url.pathname = `/${slug}/`
                break
            case 'post':
                url.pathname = `/posts${slug}`
                break
            default:
                break
        }

        // Add preview url params
        url.searchParams.set('preview', 'true')

        return url.toString()
    }

    return doc
}
You will probably need to tweak the preview pathnames to fit your own needs here.
Dec 9, 2022, 1:59 PM
As per the above code snippet, here’s how I do the fetch:
const client = await getClient({ apiVersion: '2022-06-07' })
const slug = await client.fetch(`*[_id == $id][0].slug.current`, { id: doc._id })
Note I await the
getClient
before I do the fetch.
Dec 9, 2022, 2:12 PM
Thanks for the help
user E
! Trying to implement this later tonight
Dec 9, 2022, 5:15 PM
Hope all goes well
user U
- let me know how you get on 😃
Dec 12, 2022, 2:43 PM
Is there anything you have on each document inside deskTool to enable this preview?
Dec 19, 2022, 12:02 PM
And how does your imports looks like inside the
defaultDocumentNode
Dec 19, 2022, 12:03 PM
Currently not working, but i imagine im missing a few imports. A
Dec 19, 2022, 12:20 PM

Sanity– build remarkable experiences at scale

Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.

Was this answer helpful?