managarten/packages/shared-nestjs-cors/README.md
Wuesteon 4c44764838 1. Brevo email integration (API key, sender settings)
2. URL configuration fix (BASE_URL, FRONTEND_URL)
  3. Password reset URL pointing to frontend instead of API
2025-12-17 18:11:13 +01:00

4.5 KiB

@manacore/shared-nestjs-cors

Centralized CORS configuration utility for all ManaCore NestJS backends.

Problem

Every deployed app was encountering CORS errors because:

  1. Each backend had different CORS configuration patterns
  2. Missing CORS_ORIGINS environment variable in staging/production
  3. No consistent way to handle development vs production origins

Solution

This package provides a standardized CORS configuration that:

  • Works in development without configuration
  • Supports staging/production via CORS_ORIGINS env var
  • Handles mobile app origins (exp://, myapp://)
  • Prevents duplicate origin definitions
  • Provides consistent security settings

Usage

import { NestFactory } from '@nestjs/core';
import { createCorsConfig } from '@manacore/shared-nestjs-cors';
import { AppModule } from './app.module';

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

  // Enable CORS with automatic origin detection
  app.enableCors(createCorsConfig({
    corsOriginsEnv: process.env.CORS_ORIGINS
  }));

  await app.listen(3000);
}
bootstrap();

With Custom Development Origins

app.enableCors(createCorsConfig({
  corsOriginsEnv: process.env.CORS_ORIGINS,
  developmentOrigins: [
    'http://localhost:3000',
    'http://localhost:5173'
  ]
}));

With Mobile App Support

app.enableCors(createCorsConfig({
  corsOriginsEnv: process.env.CORS_ORIGINS,
  additionalOrigins: [
    'exp://localhost:8081',  // Expo development
    'myapp://',              // Custom mobile scheme
  ]
}));

Advanced: Callback-based CORS

For advanced scenarios (e.g., allowing server-to-server calls):

import { createCorsConfigWithCallback } from '@manacore/shared-nestjs-cors';

app.enableCors(createCorsConfigWithCallback({
  corsOriginsEnv: process.env.CORS_ORIGINS
}));

Environment Variables

Development (.env.development)

No configuration needed! Default origins cover common ports:

  • http://localhost:3000-3020 (backends)
  • http://localhost:5173-5190 (web apps)
  • http://localhost:8081 (mobile)
  • exp://localhost:8081 (Expo)

Staging/Production

Set CORS_ORIGINS environment variable in your docker-compose.yml:

chat-backend:
  environment:
    CORS_ORIGINS: https://chat.staging.manacore.ai,https://chat-api.staging.manacore.ai,https://staging.manacore.ai

Default Configuration

The utility applies these NestJS CORS settings:

{
  origin: [...], // From corsOriginsEnv + developmentOrigins + additionalOrigins
  methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
  credentials: true,
  allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With']
}

Migration Guide

Before (Manual CORS)

// ❌ Old way - different in every backend
const corsOrigins = process.env.CORS_ORIGINS?.split(',').map(o => o.trim()) || [
  'http://localhost:3000',
  'http://localhost:5173',
  // ... different defaults in each app
];

app.enableCors({
  origin: corsOrigins,
  methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
  credentials: true,
});

After (Centralized)

// ✅ New way - consistent everywhere
import { createCorsConfig } from '@manacore/shared-nestjs-cors';

app.enableCors(createCorsConfig({
  corsOriginsEnv: process.env.CORS_ORIGINS
}));

Troubleshooting

CORS error in staging/production

Symptom: "Access to fetch has been blocked by CORS policy"

Solution: Ensure CORS_ORIGINS is set in docker-compose:

environment:
  CORS_ORIGINS: https://your-app.staging.manacore.ai,https://staging.manacore.ai

Mobile app not connecting

Symptom: Mobile app fails to connect to backend

Solution: Add mobile origins:

app.enableCors(createCorsConfig({
  corsOriginsEnv: process.env.CORS_ORIGINS,
  additionalOrigins: ['exp://localhost:8081']
}));

API Reference

createCorsConfig(options?)

Creates standard CORS configuration.

Parameters:

  • options.corsOriginsEnv (string, optional): Comma-separated origins from env
  • options.developmentOrigins (string[], optional): Custom dev origins
  • options.additionalOrigins (string[], optional): Additional origins to allow

Returns: NestJS CorsOptions object

createCorsConfigWithCallback(options?)

Creates CORS configuration with callback for advanced use cases.

Parameters: Same as createCorsConfig

Returns: NestJS CorsOptions object with origin callback

License

Private - ManaCore Monorepo