diff --git a/.changeset/fix-vercel-api-html-response.md b/.changeset/fix-vercel-api-html-response.md
index 1f3bdc260c..7d9d2f2820 100644
--- a/.changeset/fix-vercel-api-html-response.md
+++ b/.changeset/fix-vercel-api-html-response.md
@@ -4,15 +4,14 @@
Fix Vercel deployment API endpoints returning HTML instead of JSON.
-Replace the custom `getRequestListener` export in `server/index.ts` with the
-standard `handle()` adapter from `@hono/node-server/vercel` and the
-outer→inner Hono delegation pattern (`inner.fetch(c.req.raw)`).
+The `bundle-api.mjs` script was emitting the serverless function to `api/index.js`
+at the project root, but `vercel.json` sets `outputDirectory: "dist"` — causing
+Vercel to never find the function entrypoint and fall back to the SPA HTML route
+for all `/api/*` requests.
-- The `handle()` adapter correctly wraps the Hono app with the
- `(IncomingMessage, ServerResponse) => Promise` signature that
- Vercel's Node.js runtime expects for serverless functions in `api/`.
-- `@hono/node-server/vercel`'s `getRequestListener()` already handles
- Vercel's pre-buffered `rawBody` natively, removing the need for the
- custom body-extraction helper.
-- The outer→inner delegation pattern matches the documented ObjectStack
- Vercel deployment guide and the `@objectstack/hono` adapter test suite.
+- Change esbuild `outfile` from `api/index.js` to `dist/api/index.js` so the
+ bundled serverless function lands inside the Vercel output directory.
+- Add explicit `functions` config in `vercel.json` pointing to `api/index.js`
+ (relative to `outputDirectory`) with `@vercel/node@3` runtime.
+- Remove obsolete `.gitignore` entries for `api/index.js` and `api/index.js.map`
+ (now emitted under `dist/` which is already git-ignored).
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8214fc56b1..9e48383b4b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -39,6 +39,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
to `:memory:` (ephemeral SQLite). This ensures data persistence across serverless function
invocations on Vercel. The browser MSW mock kernel remains unchanged (InMemoryDriver).
+### Fixed
+- **Vercel API always returns HTML — serverless function entrypoint not found** — The `bundle-api.mjs`
+ script was emitting `api/index.js` at the project root, but `vercel.json` sets `outputDirectory: "dist"`,
+ so Vercel could not discover the serverless function and fell back to the SPA HTML route for all
+ `/api/*` requests. Changed esbuild `outfile` to `dist/api/index.js` and added explicit `functions`
+ config in `vercel.json` with `@vercel/node@3` runtime.
+
### Added
- **Batch schema sync for remote DDL in kernel bootstrap** — `ObjectQLPlugin.syncRegisteredSchemas()`
now groups objects by driver and uses `syncSchemasBatch()` when the driver advertises
diff --git a/apps/studio/.gitignore b/apps/studio/.gitignore
index c1815957c7..5aa73bd33b 100644
--- a/apps/studio/.gitignore
+++ b/apps/studio/.gitignore
@@ -6,8 +6,6 @@ pnpm-lock.yaml
dist
build
*.tsbuildinfo
-api/index.js
-api/index.js.map
# Development
.vite
diff --git a/apps/studio/scripts/bundle-api.mjs b/apps/studio/scripts/bundle-api.mjs
index 565e729d52..1c3225f60d 100644
--- a/apps/studio/scripts/bundle-api.mjs
+++ b/apps/studio/scripts/bundle-api.mjs
@@ -37,11 +37,11 @@ await build({
platform: 'node',
format: 'esm',
target: 'es2020',
- outfile: 'api/index.js',
+ outfile: 'dist/api/index.js',
sourcemap: true,
external: EXTERNAL,
// Silence warnings about optional/unused require() calls in knex drivers
logOverride: { 'require-resolve-not-external': 'silent' },
});
-console.log('[bundle-api] Bundled server/index.ts → api/index.js');
+console.log('[bundle-api] Bundled server/index.ts → dist/api/index.js');
diff --git a/apps/studio/vercel.json b/apps/studio/vercel.json
index 472393881d..f7671887d5 100644
--- a/apps/studio/vercel.json
+++ b/apps/studio/vercel.json
@@ -4,6 +4,11 @@
"installCommand": "cd ../.. && pnpm install",
"buildCommand": "cd ../.. && pnpm turbo run build --filter=@objectstack/studio && cd apps/studio && node scripts/bundle-api.mjs",
"outputDirectory": "dist",
+ "functions": {
+ "api/index.js": {
+ "runtime": "@vercel/node@3"
+ }
+ },
"build": {
"env": {
"VITE_RUNTIME_MODE": "server",