Skip to content

Commit 76e66ad

Browse files
fix: use same-origin API for all Vercel deployments and extract getVercelOrigins helper
Change VITE_SERVER_URL from hardcoded 'https://play.objectstack.ai' to '' (empty string / same-origin) so each Vercel deployment — including previews — calls its own serverless function instead of the production API cross-origin. Extract getVercelOrigins() helper to deduplicate Vercel env-var origin collection between the CORS middleware and better-auth trustedOrigins. Agent-Logs-Url: https://github.com/objectstack-ai/framework/sessions/bffd519d-cf16-402d-a1de-3bdaadfdd5d2 Co-authored-by: xuyushun441-sys <255036401+xuyushun441-sys@users.noreply.github.com>
1 parent 399f602 commit 76e66ad

3 files changed

Lines changed: 40 additions & 29 deletions

File tree

CHANGELOG.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1515
functions. Removed the `functions` block (the in-code `export const config`
1616
in `server/index.ts` already configures memory/maxDuration without pre-build
1717
file-pattern validation errors).
18-
- **Studio CORS error on Vercel temporary/preview domains** — Added Hono CORS
19-
middleware to `apps/studio/server/index.ts` so the serverless function returns
20-
correct `Access-Control-Allow-Origin` headers for cross-origin requests.
21-
Dynamically allows all `*.vercel.app` subdomains, explicitly listed Vercel
22-
deployment URLs (`VERCEL_URL`, `VERCEL_BRANCH_URL`,
23-
`VERCEL_PROJECT_PRODUCTION_URL`), and localhost for development. Preflight
24-
(OPTIONS) requests are answered immediately without waiting for kernel boot.
18+
- **Studio CORS error on Vercel temporary/preview domains** — Changed
19+
`VITE_SERVER_URL` from hardcoded `https://play.objectstack.ai` to `""`
20+
(empty string / same-origin) in `vercel.json` so each deployment — including
21+
previews — calls its own serverless function instead of the production API
22+
cross-origin. Also added Hono CORS middleware to `apps/studio/server/index.ts`
23+
as a safety net for any remaining cross-origin scenarios; dynamically allows
24+
all `*.vercel.app` subdomains, explicitly listed Vercel deployment URLs, and
25+
localhost. Extracted `getVercelOrigins()` helper to keep CORS and
26+
better-auth `trustedOrigins` allowlists in sync.
2527
- **Client test aligned with removed `ai.chat` method** — Updated
2628
`@objectstack/client` test suite to match the current API surface where
2729
`ai.chat()` was removed in favour of the Vercel AI SDK `useChat()` hook.

apps/studio/server/index.ts

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,33 @@ import { cors } from 'hono/cors';
4040
import { createBrokerShim } from '../src/lib/create-broker-shim.js';
4141
import studioConfig from '../objectstack.config.js';
4242

43+
// ---------------------------------------------------------------------------
44+
// Vercel origin helpers
45+
// ---------------------------------------------------------------------------
46+
47+
/**
48+
* Collect all Vercel deployment origins from environment variables.
49+
*
50+
* Reused for both:
51+
* - better-auth `trustedOrigins` (CSRF)
52+
* - Hono CORS middleware `origin` allowlist
53+
*
54+
* Centralised to avoid drift between the two allowlists.
55+
*/
56+
function getVercelOrigins(): string[] {
57+
const origins: string[] = [];
58+
if (process.env.VERCEL_URL) {
59+
origins.push(`https://${process.env.VERCEL_URL}`);
60+
}
61+
if (process.env.VERCEL_BRANCH_URL) {
62+
origins.push(`https://${process.env.VERCEL_BRANCH_URL}`);
63+
}
64+
if (process.env.VERCEL_PROJECT_PRODUCTION_URL) {
65+
origins.push(`https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}`);
66+
}
67+
return origins;
68+
}
69+
4370
// ---------------------------------------------------------------------------
4471
// Singleton state — persists across warm Vercel invocations
4572
// ---------------------------------------------------------------------------
@@ -86,17 +113,8 @@ async function ensureKernel(): Promise<ObjectKernel> {
86113
? `https://${process.env.VERCEL_URL}`
87114
: 'http://localhost:3000';
88115

89-
// Collect all Vercel URL variants so better-auth trusts each one
90-
const trustedOrigins: string[] = [];
91-
if (process.env.VERCEL_URL) {
92-
trustedOrigins.push(`https://${process.env.VERCEL_URL}`);
93-
}
94-
if (process.env.VERCEL_BRANCH_URL) {
95-
trustedOrigins.push(`https://${process.env.VERCEL_BRANCH_URL}`);
96-
}
97-
if (process.env.VERCEL_PROJECT_PRODUCTION_URL) {
98-
trustedOrigins.push(`https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}`);
99-
}
116+
// Reuse the shared helper so CORS and CSRF allowlists stay in sync
117+
const trustedOrigins = getVercelOrigins();
100118

101119
await kernel.use(new AuthPlugin({
102120
secret: process.env.AUTH_SECRET || 'dev-secret-please-change-in-production-min-32-chars',
@@ -233,16 +251,7 @@ const app = new Hono();
233251
// 3. localhost (local development)
234252
// ---------------------------------------------------------------------------
235253

236-
const vercelOrigins: string[] = [];
237-
if (process.env.VERCEL_URL) {
238-
vercelOrigins.push(`https://${process.env.VERCEL_URL}`);
239-
}
240-
if (process.env.VERCEL_BRANCH_URL) {
241-
vercelOrigins.push(`https://${process.env.VERCEL_BRANCH_URL}`);
242-
}
243-
if (process.env.VERCEL_PROJECT_PRODUCTION_URL) {
244-
vercelOrigins.push(`https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}`);
245-
}
254+
const vercelOrigins = getVercelOrigins();
246255

247256
app.use('*', cors({
248257
origin: (origin) => {

apps/studio/vercel.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"build": {
88
"env": {
99
"VITE_RUNTIME_MODE": "server",
10-
"VITE_SERVER_URL": "https://play.objectstack.ai"
10+
"VITE_SERVER_URL": ""
1111
}
1212
},
1313
"headers": [

0 commit comments

Comments
 (0)