[bug?] Preview not working in v0 when using Astro

I wanted to try out v0 for an astro project but couldnt get the preview to work. The only message shown is Cross-origin request blocked. I tried serveral settings in the astro config (see below) to disable CORS and make it work but its still not possible to view the page in the browser.
Funnily, I am able to see the page preview in the mobile app.

Any help or pointer are much appreciated!

My astro config:

// @ts-check
import { defineConfig } from "astro/config"
import tailwindcss from "@tailwindcss/vite"

// https://astro.build/config
export default defineConfig({
  site: "https://friva.at",
  i18n: {
    defaultLocale: "en",
    locales: ["en", "de"],
    routing: {
      prefixDefaultLocale: false,
      redirectToDefaultLocale: false,
    },
  },
  security: {
    checkOrigin: false,
    csp: false,
    // The v0 preview embeds the dev server in a cross-origin iframe, so the
    // proxy requests the page with `Sec-Fetch-Mode: cors` /
    // `Sec-Fetch-Site: cross-site`. Astro's dev router blocks those with a
    // 403 "Cross-origin request blocked" unless the request's Origin matches
    // an entry here. An entry with no `hostname` matches every origin, which
    // is safe because this dev-only check is not present in production builds.
    allowedDomains: [{ hostname: "v0.app" }, {}],
  },
  server: {
    host: true,
  },
  vite: {
    plugins: [tailwindcss()],
    server: {
      // Allow any Host header (Vite's separate host-validation gate) so the
      // proxied preview hostname is accepted, and reflect CORS for assets.
      allowedHosts: true,
      cors: true,
      hmr: { clientPort: 443 },
    },
  },
})

While a member of our team prepares to jump in, you might find your answer even faster in our community resources.

Hi Benjamin,

One thing I’d try is adding Astro’s own server.allowedHosts, not only Vite’s vite.server.allowedHosts.

In your config you currently have:

server: {
  host: true,
},
vite: {
  server: {
    allowedHosts: true,
    cors: true,
  },
}

but Astro also has a top-level server.allowedHosts option. If the v0 web preview request is being rejected before it reaches the Vite asset/HMR layer, the Vite setting alone may not change the result.

As a temporary isolation test, I’d try:

export default defineConfig({
  site: "https://friva.at",
  server: {
    host: true,
    allowedHosts: true,
  },
  security: {
    checkOrigin: false,
    csp: false,
    allowedDomains: [{}],
  },
  vite: {
    plugins: [tailwindcss()],
    server: {
      allowedHosts: true,
      cors: true,
      hmr: { clientPort: 443 },
    },
  },
})

If that makes the v0 web preview load, I’d narrow the broad settings back down instead of leaving them like that permanently. The browser Network tab should show the actual Host / Origin being used by the v0 preview, and then you can allow only that preview hostname/pattern.

If it still fails, I’d check which request is blocked: the document /, an /_astro/... asset, or the HMR websocket. That will tell you whether this is Astro host/origin validation, Vite asset CORS, or HMR.

Since the mobile preview works but the web preview fails, this may also be specific to the v0 web preview wrapper rather than your Astro production build. The most useful detail to share next would be the failed Network row with cookies/auth headers removed.