Issue with live preview in Remix and Sanity integration.

11 replies
Last updated: Jul 10, 2023
Hello everyone!I am trying to figure out the live preview for drafts working with Remix and Sanity following these instructions:

https://www.sanity.io/guides/remix-run-live-preview
I got to the point where the website runs all good and connected to my Sanity content lake but I don't get a preview page when I try to go to the
localhost:3000/ resource/preview.in the end I copied the code exactly from the guide example yet I'm just being constantly redirected to the _index page.
I have checked that my SANITY_API_READ_TOKEN is correct and that it rightly gets to the resource.preview.tsx route yet I never see the preview page itself on the localhost

Anyone tried that before?
Cheers!
AI Update

I can see you're hitting a redirect issue with the Remix live preview guide! The good news is that the guide you're following has actually been updated since it was first published, and the resource.preview.tsx route approach is no longer the recommended pattern.

Looking at the official guide you linked, the modern implementation uses the Presentation Tool with Visual Editing, which works completely differently and doesn't require a resource.preview.tsx route at all.

The Modern Approach (No resource.preview.tsx needed!)

The current guide shows that live preview now works through:

  1. @sanity/react-loader - Handles loading data with live updates
  2. @sanity/visual-editing - Provides the clickable overlays and communication with Presentation
  3. The Presentation Tool - Embeds your Remix app in an iframe inside the Studio

The magic happens when your Remix app is loaded inside the Presentation Tool's iframe. The LiveVisualEditing component (which imports VisualEditing from @sanity/visual-editing/remix) handles all the communication between the Studio and your app automatically.

Why You're Seeing Redirects

If you're following an older version of the guide or mixing old and new patterns, you might be creating a resource.preview.tsx file that's trying to set session cookies. But the modern approach doesn't use sessions at all - it uses "stega" (Content Source Maps) encoded directly in the data.

What You Should Check

1. Verify your setup matches the current guide:

  • You should have SANITY_STUDIO_STEGA_ENABLED="true" in your .env
  • Your routes should use useQuery from @sanity/react-loader
  • You should have the LiveVisualEditing component in your root route

2. Remove any resource.preview.tsx file - you don't need it with the modern approach

3. Make sure you're viewing through Presentation:

  • Open your Studio at http://localhost:3333/presentation
  • The preview should load your Remix app at http://localhost:3000 inside an iframe
  • Changes should update in real-time as you edit

4. Check your CORS settings in sanity.io/manage - you need http://localhost:3000 added with "Allow credentials" checked

Quick Debugging Steps

  1. Open your browser console when viewing through Presentation - look for any errors
  2. Verify SANITY_STUDIO_STEGA_ENABLED is actually "true" (as a string)
  3. Check that the LiveVisualEditing component is rendering (it should only render when SANITY_STUDIO_STEGA_ENABLED is true)
  4. Make sure you're using the useQuery hook in your routes, not just the raw data from the loader

Fresh Start Option

If you want to start with a working example, the official Remix + Sanity clean template implements all these patterns correctly and might help you spot what's different in your setup.

The key insight: modern Remix + Sanity live preview doesn't use resource routes or session cookies - it uses stega-encoded data and the Visual Editing component to enable real-time updates when viewed through the Presentation Tool!

Getting redirected to the home page after visiting the preview route is intended – but you should be seeing the site in “preview mode” then.
Are you able to console log that the preview session has been correctly set?
Yeah I thought so but I don't get the button at the bottom for exiting preview mode and when I do any changes in my sanity data (without commiting) I don't see any change.I've tried to make a console log when the preview is being triggered but never saw it
**correction: I see the console log in the terminal once the loader function is being triggered, and it sees the token
And your _index route is updated with the loader checking for the session?
yesexport const loader: LoaderFunction = async ({ request }: LoaderArgs) => {
const session = await getSession(request.headers.get("Cookie"));
const token = session.get("preview");
const preview = token ? { token } : undefined;
const posts = await getClient(preview).fetch(postsQuery);
Can you paste the whole route?
import { useLoaderData } from "@remix-run/react";
import { getClient } from "~/lib/sanity";
import Posts from "~/components/Posts";
import type { LoaderArgs, LoaderFunction } from "@remix-run/node";
import { getSession } from "~/sessions";
import { postsQuery } from "~/lib/queries";
import PostsPreview from "~/components/PostsPreview";

export const loader: LoaderFunction = async ({ request }: LoaderArgs) => {
const session = await getSession(request.headers.get("Cookie"));
const token = session.get("preview");
const preview = token ? { token } : undefined;
const posts = await getClient(preview).fetch(postsQuery);

return {
posts,
preview,
};
};

export default function Index() {
const { posts, preview } = useLoaderData();

return preview?.token ? (
<PostsPreview posts={posts} />
) : (
<Posts posts={posts} />
);
}
Can you try updating the loader in your
root.tsx
file to:

export const loader: LoaderFunction = async ({ request }: LoaderArgs) => {
  const session = await getSession(request.headers.get("Cookie"));
  const token = session.get("preview");
  const preview = token ? { token } : undefined;

  return { preview };
};
Legend Simeon!thank you very much, that did the trick.

I think that line in the root.tsx is not mentioned at any point in the guide.

Thanks again for this great support!
Yeah I’m updating it now, thanks for reporting the issue!
🙏

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?