From 340055647bf39fe20974f208c278de1b1ecb5264 Mon Sep 17 00:00:00 2001 From: Sy Bohy Date: Mon, 26 Oct 2026 17:01:32 -0700 Subject: [PATCH] fix: proxy hosted device catalog reads through the embed origin --- README.md | 7 +++++++ examples/supported-devices/src/App.tsx | 6 +++++- examples/vite.config.ts | 5 +++++ vercel.json | 10 +++++++++- 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1aefead01..1c971866e 100644 --- a/README.md +++ b/README.md @@ -241,6 +241,13 @@ hosts such as Mintlify that cannot import an npm component. It composes `EcosystemProvider` and `SupportedDevices`, reads the public production Ecosystem catalog without an embed key, and never uses Storybook fixtures or Strapi. +The hosted page reads `/ecosystem/v1/device_models/summaries/list` and +`/ecosystem/v1/manufacturers/list` on its own origin. Vercel forwards these two +public routes to the production Ecosystem API, preserving query parameters. +This avoids browser local-network restrictions when a visitor's VPN or split DNS +resolves `ecosystem.seam.co` to a private address. Vite proxies the same paths +during local development. These routes do not expose admin or write endpoints. + Query parameters are `manufacturer`, `provider` (Ecosystem slugs, not Seam Connect provider keys), `device_type`, `capability`, and `theme` (`light`, `dark`, `auto`). For example, use `?manufacturer=dormakaba&provider=oracode` to avoid listing other diff --git a/examples/supported-devices/src/App.tsx b/examples/supported-devices/src/App.tsx index a6f8f4c0c..fda0c1b44 100644 --- a/examples/supported-devices/src/App.tsx +++ b/examples/supported-devices/src/App.tsx @@ -55,7 +55,11 @@ export function App(): JSX.Element { : `https://www.seam.co/manufacturers/${encodeURIComponent(config.manufacturer)}` return ( - +

diff --git a/examples/vite.config.ts b/examples/vite.config.ts index 4811e7335..2eaa7ddaa 100644 --- a/examples/vite.config.ts +++ b/examples/vite.config.ts @@ -51,6 +51,11 @@ export default defineConfig(async ({ command, mode }) => { server: { port: 8080, proxy: { + '/ecosystem/v1': { + target: 'https://ecosystem.seam.co', + rewrite: (path: string) => path.replace(/^\/ecosystem/, ''), + changeOrigin: true, + }, '/api': { target, rewrite: (path: string) => path.replace(/^\/api/, ''), diff --git a/vercel.json b/vercel.json index 49575e38b..c32173724 100644 --- a/vercel.json +++ b/vercel.json @@ -7,6 +7,14 @@ }, "cleanUrls": true, "rewrites": [ + { + "source": "/ecosystem/v1/device_models/summaries/list", + "destination": "https://ecosystem.seam.co/v1/device_models/summaries/list" + }, + { + "source": "/ecosystem/v1/manufacturers/list", + "destination": "https://ecosystem.seam.co/v1/manufacturers/list" + }, { "source": "/v/:version/:asset*", "destination": "https://react.seam.net/v/:version/:asset" @@ -165,7 +173,7 @@ "headers": [ { "key": "Content-Security-Policy", - "value": "default-src 'self'; script-src 'self'; connect-src 'self' https://ecosystem.seam.co; img-src 'self' data: https://seam-ecosystem-media.fly.storage.tigris.dev https://strapi-media-bucket.fly.storage.tigris.dev; style-src 'self'; frame-ancestors 'self' https://www.seam.co https://seam.co https://docs.seam.co https://*.mintlify.app http://localhost:* http://127.0.0.1:*" + "value": "default-src 'self'; script-src 'self'; connect-src 'self'; img-src 'self' data: https://seam-ecosystem-media.fly.storage.tigris.dev https://strapi-media-bucket.fly.storage.tigris.dev; style-src 'self'; frame-ancestors 'self' https://www.seam.co https://seam.co https://docs.seam.co https://*.mintlify.app http://localhost:* http://127.0.0.1:*" }, { "key": "X-Robots-Tag",