How to Fix the Vercel Rewrite Rules for Sanity

4 replies
Last updated: May 5, 2021
Hi, how do you fix the Vercel rewrite rules for Sanity? I lifted this line from their blog, but it doesn’t actually work:
"rewrites": [{ "source": "/(.*)", "destination": "/index.html" }]
AI Update

The rewrite rule you've got is actually correct for a basic SPA setup, but there's a key detail: Vercel automatically serves static files before applying rewrites. So the issue likely isn't the rewrite rule itself—it's probably something else in your configuration.

Here's what you need for a standalone Sanity Studio deployment to Vercel:

{
  "rewrites": [
    { "source": "/(.*)", "destination": "/index.html" }
  ]
}

But wait—if this isn't working, here's what's likely wrong:

1. Wrong Output Directory

Make sure your vercel.json specifies where your built Studio files are. Sanity Studio builds to dist/ by default:

{
  "buildCommand": "npm run build",
  "outputDirectory": "dist",
  "rewrites": [
    { "source": "/(.*)", "destination": "/index.html" }
  ]
}

2. Studio at a Subpath (like /studio)

If your Studio lives at a route like /studio instead of the root, you need to:

a) Configure the basePath in your Sanity config:

// sanity.config.js
export default defineConfig({
  basePath: '/studio',
  // ... rest of config
})

b) Update your rewrite to match:

{
  "rewrites": [
    { "source": "/studio/(.*)", "destination": "/studio/index.html" }
  ]
}

3. Deploying Studio with a Next.js App

If you're embedding Studio in a Next.js app, you don't need rewrites at all—Next.js handles client-side routing automatically. The rewrite rule is only for standalone Studio deployments as SPAs.

4. Build Not Producing index.html

Check your Vercel build logs to confirm that dist/index.html actually exists after the build runs. Run sanity build locally and verify the output.

Common Gotcha: Vercel's Order of Operations

Vercel checks for static files first, then applies rewrites. So your rewrite won't break CSS/JS files—those will be served directly. The rewrite only kicks in for paths that don't match actual files, which is exactly what you want for client-side routing in a single-page application.

If you're still stuck, double-check that your CORS origins are configured correctly in sanity.io/manage for both your Vercel deployment URL and localhost (for development). Also verify that your Vercel integration is set up properly if you're using visual editing features.

this works for me in vercel.json

{
  "routes": [
    { "handle": "filesystem" },
    { "src": "/(.*)", "dest": "/index.html" }
  ]
}
or when hosting the sanity spa inside a next project I use this in next.config.js


async rewrites() {
  return [
    { source: "/cms", destination: "/cms/index.html" },
    { source: "/cms/:path*", destination: "/cms/index.html" },
  ];
},
Thanks, for some reason I can’t seem to get
routes
to work either. I’m thinking maybe I’ll try wrapping it in a next app if the next few deploys don’t take.
Some thoughts: Is the sanity index.html there at all (the file is created with
sanity build
and in the right directory)? No conflicting routes (now.json / vercel.json, next.config)? Have you tried using the vercel cli locally?
Those are good ideas. After I came back with fresh eyes, I realized
"cleanUrls": true
was the culprit. Though I’m really not sure how that could get in the way of
/desk
. Anyway, thanks again for the help! 🙂

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?