Skip to content

Commit 18b0a7b

Browse files
Claudehotlong
andauthored
feat: serve studio at /_studio in Vercel deployment
- Modified build-vercel.sh to copy studio to api/_studio instead of public/ - Updated vercel.json to include api/_studio in includeFiles - Configured static file serving at /_studio in server/index.ts - Removed SPA rewrite from vercel.json Agent-Logs-Url: https://github.com/objectstack-ai/framework/sessions/0d153df4-77aa-4de3-8c31-388b75929c38 Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent 98abb94 commit 18b0a7b

3 files changed

Lines changed: 41 additions & 12 deletions

File tree

apps/server/scripts/build-vercel.sh

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ set -euo pipefail
77
# - api/[[...route]].js is committed to the repo (Vercel detects it pre-build)
88
# - esbuild bundles server/index.ts → api/_handler.js (self-contained bundle)
99
# - The committed .js wrapper re-exports from _handler.js at runtime
10-
# - Studio SPA is built and copied to public/ for serving the UI
10+
# - Studio SPA is built and copied to api/_studio/ for serving at /_studio
1111
# - External dependencies installed in api/node_modules/ (no symlinks)
1212
#
1313
# Steps:
1414
# 1. Build the project with turbo (includes studio)
1515
# 2. Bundle the API serverless function (→ api/_handler.js)
16-
# 3. Copy studio dist files to public/ for UI serving
16+
# 3. Copy studio dist files to api/_studio/ for UI serving at /_studio
1717
# 4. Install external deps in api/node_modules/ (resolve pnpm symlinks)
1818

1919
echo "[build-vercel] Starting server build..."
@@ -27,13 +27,13 @@ cd apps/server
2727
# 2. Bundle API serverless function
2828
node scripts/bundle-api.mjs
2929

30-
# 3. Copy studio dist files to public/ for UI serving
31-
echo "[build-vercel] Copying studio dist to public/..."
32-
rm -rf public
33-
mkdir -p public
30+
# 3. Copy studio dist files to api/_studio/ for UI serving at /_studio
31+
echo "[build-vercel] Copying studio dist to api/_studio/..."
32+
rm -rf api/_studio
33+
mkdir -p api/_studio
3434
if [ -d "../studio/dist" ]; then
35-
cp -r ../studio/dist/* public/
36-
echo "[build-vercel] ✓ Copied studio dist to public/"
35+
cp -r ../studio/dist/* api/_studio/
36+
echo "[build-vercel] ✓ Copied studio dist to api/_studio/"
3737
else
3838
echo "[build-vercel] ⚠ Studio dist not found (skipped)"
3939
fi
@@ -60,4 +60,4 @@ rm package.json
6060
cd ..
6161
echo "[build-vercel] ✓ External dependencies installed in api/node_modules/"
6262

63-
echo "[build-vercel] Done. Static files in public/, serverless function in api/[[...route]].js → api/_handler.js"
63+
echo "[build-vercel] Done. Studio files in api/_studio/, serverless function in api/[[...route]].js → api/_handler.js"

apps/server/server/index.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@
1010
import { ObjectKernel } from '@objectstack/runtime';
1111
import { createHonoApp } from '@objectstack/hono';
1212
import { getRequestListener } from '@hono/node-server';
13+
import { serveStatic } from '@hono/node-server/serve-static';
1314
import type { Hono } from 'hono';
1415
import stackConfig from '../objectstack.config';
16+
import { fileURLToPath } from 'node:url';
17+
import { dirname, join } from 'node:path';
1518

1619
// ---------------------------------------------------------------------------
1720
// Singleton state — persists across warm Vercel invocations
@@ -69,6 +72,33 @@ async function ensureApp(): Promise<Hono> {
6972

7073
const kernel = await ensureKernel();
7174
_app = createHonoApp({ kernel, prefix: '/api/v1' });
75+
76+
// Serve studio at /_studio
77+
const __filename = fileURLToPath(import.meta.url);
78+
const __dirname = dirname(__filename);
79+
const studioPath = join(__dirname, '_studio');
80+
81+
// Serve static files from /_studio
82+
_app.get('/_studio/*', serveStatic({
83+
root: __dirname,
84+
rewriteRequestPath: (path) => {
85+
// Rewrite /_studio/assets/x.js -> /_studio/assets/x.js
86+
return path;
87+
}
88+
}));
89+
90+
// SPA fallback for studio
91+
_app.get('/_studio/*', serveStatic({
92+
root: __dirname,
93+
rewriteRequestPath: () => '/_studio/index.html'
94+
}));
95+
96+
// Serve studio index at /_studio root
97+
_app.get('/_studio', serveStatic({
98+
root: __dirname,
99+
rewriteRequestPath: () => '/_studio/index.html'
100+
}));
101+
72102
return _app;
73103
}
74104

apps/server/vercel.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"functions": {
1313
"api/**/*.js": {
1414
"maxDuration": 60,
15-
"includeFiles": "api/node_modules/**"
15+
"includeFiles": "api/{node_modules,_studio}/**"
1616
}
1717
},
1818
"headers": [
@@ -24,7 +24,6 @@
2424
}
2525
],
2626
"rewrites": [
27-
{ "source": "/api/:path*", "destination": "/api/[[...route]]" },
28-
{ "source": "/((?!api/).*)", "destination": "/index.html" }
27+
{ "source": "/api/:path*", "destination": "/api/[[...route]]" }
2928
]
3029
}

0 commit comments

Comments
 (0)