Vercel
Deploy to Vercel using NestJS di-only mode
The recommended way to deploy a newt app to Vercel is with NestJS di-only mode (--nest-di-only). In this mode, NestJS runs as an application context (no HTTP server) so your entire app is a single Next.js project that deploys to Vercel without any extra infrastructure.
How it works
When you scaffold with --nest-di-only, NestJS is initialized via NestFactory.createApplicationContext, with no HTTP server. NestJS services are accessed directly from Next.js API routes using the inject helper in apps/web/lib/nest.ts:
import { NextResponse } from 'next/server';
import { inject } from '@/lib/nest';
import { AppService } from '@my-app/api';
export async function GET() {
const appService = await inject(AppService);
return NextResponse.json({ message: appService.getHello() });
}The context is lazily initialized on the first request and cached for the lifetime of the function container:
import { NestFactory } from '@nestjs/core';
import { AppModule } from '@my-app/api';
import type { INestApplicationContext, Type, Abstract } from '@nestjs/common';
let context: INestApplicationContext | null = null;
export async function getContext(): Promise<INestApplicationContext> {
if (!context) {
context = await NestFactory.createApplicationContext(AppModule, { logger: false });
}
return context;
}
export async function inject<T>(token: Type<T> | Abstract<T> | string | symbol): Promise<T> {
const ctx = await getContext();
return ctx.get<T>(token);
}Deploying to Vercel
- Push your repo to GitHub
- Import the project at vercel.com/new
- Set the root directory to
apps/web - Add your environment variables (see below)
- Deploy
Vercel auto-detects Next.js. No build configuration needed.
Environment variables
Set these in the Vercel dashboard under Settings → Environment Variables:
DATABASE_URL= # your database connection string
BETTER_AUTH_SECRET= # generate with: openssl rand -base64 32
NEXT_PUBLIC_APP_URL= # your Vercel deployment URL, e.g. https://my-app.vercel.appDatabase
Scaffold with --database postgres. SQLite writes to a local file, which doesn't persist on Vercel's serverless filesystem. Vercel doesn't include a database, so use any Postgres provider: Neon, Supabase, or Railway.
Run migrations before your first deploy:
pnpm db:migrate