NestJS deployment

So basicly i’m trying to deploy a nestjs app and even if tweek the vercel.json file so that the deployment at least succeeds, when i try to access a swagger or any other route it gives me a 404 error. (Obs: AT DEV ENV EVERYTHING WORKS FINE)

vercel.json:

{
  "version": 2,
  "buildCommand": "npm run build",
  "devCommand": "npm run start:dev",
  "installCommand": "npm install --legacy-peer-deps",
  "outputDirectory": "dist"
}

package.json

{
  "name": "commerce-blog.api",
  "version": "0.0.1",
  "description": "",
  "author": "Gustavo Augusto",
  "private": true,
  "license": "UNLICENSED",
  "scripts": {
    "build": "nest build",
    "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
    "start": "node dist/main.js",
    "start:dev": "nest start --watch",
    "start:debug": "nest start --debug --watch",
    "start:prod": "node dist/main",
    "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
    "test": "jest",
    "test:watch": "jest --watch",
    "test:cov": "jest --coverage",
    "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
    "typeorm": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js",
    "typeorm:migration:generate": "npm run typeorm -- migration:generate -n",
    "migration:run": "npm run typeorm -- -d src/lib/database/database.providers.ts migration:run",
    "seed:run": "ts-node -r tsconfig-paths/register ./node_modules/typeorm-extension/bin/cli.cjs seed:run  -d src/lib/database/database.providers.ts",
    "seed:create": "ts-node ./node_modules/typeorm-extension/bin/cli.cjs seed:create"
  },
  "dependencies": {
    "@nestjs/bull": "^10.2.2",
    "@nestjs/common": "^10.4.6",
    "@nestjs/config": "^3.3.0",
    "@nestjs/core": "^10.4.6",
    "@nestjs/jwt": "^10.2.0",
    "@nestjs/passport": "^10.0.3",
    "@nestjs/platform-express": "^10.4.6",
    "@nestjs/platform-socket.io": "^10.4.6",
    "@nestjs/schedule": "^4.1.1",
    "@nestjs/swagger": "^8.0.1",
    "@nestjs/terminus": "^10.2.3",
    "@nestjs/typeorm": "^10.0.2",
    "@nestjs/websockets": "^10.4.6",
    "@socket.io/redis-adapter": "^8.3.0",
    "bcrypt": "^5.1.1",
    "bull": "^4.16.3",
    "cron": "^3.1.8",
    "dotenv": "^16.4.5",
    "nestjs-typeorm-paginate": "^4.0.4",
    "nestjs-zod": "^4.1.0",
    "passport": "^0.7.0",
    "passport-jwt": "^4.0.1",
    "passport-local": "^1.0.0",
    "pg": "^8.13.1",
    "redis": "^4.7.0",
    "reflect-metadata": "^0.2.2",
    "rxjs": "^7.8.1",
    "socket.io": "^4.8.1",
    "typeorm": "^0.3.20",
    "typeorm-extension": "^3.6.2",
    "zod": "^3.23.8"
  },
  "devDependencies": {
    "@jest/types": "^29.6.3",
    "@nestjs/cli": "^10.4.5",
    "@nestjs/schematics": "^10.2.3",
    "@nestjs/testing": "^10.4.6",
    "@types/bcrypt": "^5.0.2",
    "@types/express": "^5.0.0",
    "@types/jest": "^29.5.14",
    "@types/node": "^22.8.4",
    "@types/passport-jwt": "^4.0.1",
    "@types/supertest": "^6.0.2",
    "@typescript-eslint/eslint-plugin": "^8.12.2",
    "@typescript-eslint/parser": "^8.12.2",
    "eslint": "^9.13.0",
    "eslint-config-prettier": "^9.1.0",
    "eslint-plugin-prettier": "^5.2.1",
    "jest": "^29.7.0",
    "prettier": "^3.3.3",
    "source-map-support": "^0.5.21",
    "supertest": "^7.0.0",
    "ts-jest": "^29.2.5",
    "ts-loader": "^9.5.1",
    "ts-node": "^10.9.2",
    "tsconfig-paths": "^4.2.0",
    "typescript": "^5.6.3"
  }
}

main.ts

import { Logger } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';

import { AppModule } from './app.module';
import { corsConfig } from './config/cors.config';
import { ENV_VARIABLES, IS_DEV_ENV } from './config/env.config';
import { DataBaseInterceptor } from './lib/http-exceptions/errors/interceptors/database.interceptor';
import { NotFoundInterceptor } from './lib/http-exceptions/errors/interceptors/not-found.interceptor';
import { BadRequestInterceptor } from './lib/http-exceptions/errors/interceptors/bad-request.interceptor';
import { UnauthorizedInterceptor } from './lib/http-exceptions/errors/interceptors/unauthorized.interceptor';
import { DataSourceInterceptor } from './lib/http-exceptions/errors/interceptors/conction-data-source.interceptor';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  try {
    app.enableCors({
      origin: corsConfig.allowedDomains,
    });
    app.enableShutdownHooks();
    app.setGlobalPrefix('server');

    /**
     * -----------------------------------------------------------------------------
     * HTTP Interceptor
     * -----------------------------------------------------------------------------
     */
    app.useGlobalInterceptors(
      new UnauthorizedInterceptor(),
      new DataSourceInterceptor(),
      new BadRequestInterceptor(),
      new NotFoundInterceptor(),
      new DataBaseInterceptor(),
    );

    if (IS_DEV_ENV) {
      const [{ SwaggerModule }, { swaggerConfig }, { writeFileSync }] =
        await Promise.all([
          import('@nestjs/swagger'),
          import('./config/swagger.config'),
          import('fs'),
        ]);

      const document = SwaggerModule.createDocument(app, swaggerConfig);

      writeFileSync('swagger-document.json', JSON.stringify(document, null, 2));

      SwaggerModule.setup('server', app, document);
    }

    await app.listen(ENV_VARIABLES.PORT);
  } catch (err) {
    Logger.debug(JSON.stringify({ err }, null, 2));
    process.exit(1);
  }
}
bootstrap();

env.config.ts:

import 'dotenv/config';
import { z } from 'zod';

import {
  stringSchema,
  optionalStringSchema,
  optionalUrlStringSchema,
  optionalStringToIntegerSchema,
} from 'src/shared/schemas.shared';

export const envSchema = z.object({
  DATABASE_ROOT_PASSWORD: stringSchema,
  DATABASE_DATABASE_NAME: stringSchema,
  DB_PORT: optionalStringToIntegerSchema.default('5432'),
  DATABASE_HOST: optionalStringSchema.default('localhost'),
  // REDIS_HOST: optionalStringSchema.default('localhost'),
  // REDIS_PASSWORD: stringSchema,
  // REDIS_PORT: stringToIntegerSchema,
  DB_USER: stringSchema,
  JWT_SECRET: stringSchema,
  JWT_REFRESH_SECRET: stringSchema,
  JWT_REFRESH_EXPIRES_IN: stringSchema,
  JWT_ISSUER: optionalUrlStringSchema,
  JWT_AUDIENCE: optionalUrlStringSchema,
  JWT_EXPIRES_IN: stringSchema,
  PORT: optionalStringToIntegerSchema.default('5000'),
  ENV: z.enum(['prod', 'dev']).default('dev'),
});

export type EnvType = z.infer<typeof envSchema>;

export const ENV_VARIABLES = envSchema.parse(process.env);

export const IS_DEV_ENV = ENV_VARIABLES.ENV === 'dev';

Hi, @marcellosamura-gmail!

We have this community thread about how to debug these types of errors. Might be helpful!