Deploy to Vercel as a TanStack Start app via Nitro

Vercel served 404s: with Hydrogen gone it treated the app as a static
Vite site, but TanStack Start's build has no index.html; pages come from
its server. Add the hosting adapter TanStack documents for Vercel:

- nitro() in vite.config, for 'vite build' only (dev and the nodesandbox
  runtime never load it); on Vercel it writes .vercel/output with the
  static assets and one Node.js function running Start + Hono
- vercel.json: tanstack-start preset, Yarn 4 via Corepack
- 'yarn start' runs the Node build; canonical URLs use the Vercel domain

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Rami Bitar
2026-10-03 15:47:53 -04:00
co-authored by Claude Opus 5.5
parent 7ec0029b08
commit 55423c7204
6 changed files with 182 additions and 7 deletions
+14 -4
View File
@@ -5,14 +5,24 @@ import tailwindcss from '@tailwindcss/vite';
import { fileURLToPath, URL } from 'node:url';
// Absolute origin for canonical and Open Graph URLs. Inlined at build time so
// the server render and the client agree on it; set VITE_SITE_URL in production.
const siteUrl = process.env.VITE_SITE_URL ?? 'http://localhost:3000';
// the server render and the client agree on it. On Vercel the production domain
// is used automatically; VITE_SITE_URL overrides it anywhere.
const siteUrl =
process.env.VITE_SITE_URL ??
(process.env.VERCEL_PROJECT_PRODUCTION_URL
? `https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}`
: 'http://localhost:3000');
export default defineConfig({
export default defineConfig(async ({ command }) => ({
server: { port: 3000 },
plugins: [
// Start must come before the React plugin.
tanstackStart(),
// Hosting adapter for `vite build`: Nitro packages Start's server for the
// host (a Vercel Function when building on Vercel, a Node server in
// .output/ elsewhere). Dev never loads it, so `vite dev` — and the
// nodesandbox runtime — run plain Vite + TanStack Start + Hono.
...(command === 'build' ? [(await import('nitro/vite')).nitro()] : []),
react(),
tailwindcss(),
],
@@ -24,4 +34,4 @@ export default defineConfig({
'@': fileURLToPath(new URL('./src', import.meta.url)),
},
},
});
}));