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.

VercelNext.jsAPI routesNestJSapp context

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:

apps/web/app/api/hello/route.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:

apps/web/lib/nest.ts
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

  1. Push your repo to GitHub
  2. Import the project at vercel.com/new
  3. Set the root directory to apps/web
  4. Add your environment variables (see below)
  5. 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.app

Database

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