Configuration
Vercube provides a powerful, type-safe configuration system that lets you customize every aspect of your application. Configuration is defined in a vercube.config.ts file at the root of your project, and can be accessed at runtime throughout your application.
Creating Configuration
Create a vercube.config.ts file in your project root:
import { defineConfig } from '@vercube/core';
export default defineConfig({
server: {
port: 3000,
host: 'localhost'
},
logLevel: 'info'
});
The defineConfig function provides TypeScript autocomplete and type checking for all configuration options.
defineConfig function is a helper that provides type safety and IDE autocomple. It doesn't do anything at runtime - it just returns your configuration object with proper types.Configuration Options
Server Configuration
Controls how your HTTP server runs:
export default defineConfig({
server: {
// Network settings
host: 'localhost',
port: 3000,
// HTTPS configuration
https: false,
// Or with certificates:
https: {
key: './certs/key.pem',
cert: './certs/cert.pem'
},
// Static file serving
static: {
dirs: ['public'], // Directories to serve
maxAge: 3600, // Cache time in seconds
immutable: false, // Set immutable cache header
etag: true // Enable ETags
}
}
});
Runtime Configuration
Configuration that's accessible at runtime in your application:
export default defineConfig({
runtime: {
// Built-in session configuration
session: {
secret: process.env.SESSION_SECRET || 'change-me-in-production',
name: 'vercube_session',
duration: 60 * 60 * 24 * 7 // 7 days in seconds
},
// Your custom runtime config (more on this below)
database: {
host: 'localhost',
port: 5432,
name: 'myapp'
},
api: {
baseUrl: 'https://api.example.com',
timeout: 5000
}
}
});
Build Configuration
Configuration for the Vercube CLI build process:
export default defineConfig({
build: {
// Project root directory
root: process.cwd(),
// Entry point(s)
entry: 'src/index.ts',
// Or multiple entries:
entry: ['src/index.ts', 'src/worker.ts'],
// Build output
output: {
dir: 'dist', // Output directory
publicDir: 'public' // Public assets directory
},
// TypeScript configuration
tsconfig: './tsconfig.json',
dts: true, // Generate .d.ts files
// Build-time defines (injected into code)
define: {
'process.env.API_URL': JSON.stringify('https://api.example.com')
},
// Bundler to use
bundler: 'rolldown',
// Custom bundler plugins
plugins: [
// Your rolldown plugins here
]
}
});
Logging Configuration
export default defineConfig({
// Log level for the application
logLevel: 'debug' // 'debug' | 'info' | 'warn' | 'error' | 'silent'
});
Environment Flags
export default defineConfig({
// Automatically set based on NODE_ENV, but you can override
production: process.env.NODE_ENV === 'production',
dev: process.env.NODE_ENV !== 'production'
});
Accessing Configuration at Runtime
Use the RuntimeConfig class to access your configuration in controllers, services, and other parts of your application:
import { Controller, Get, Inject } from '@vercube/core';
import { RuntimeConfig } from '@vercube/core';
@Controller('/users')
export class UserController {
@Inject(RuntimeConfig)
private config!: RuntimeConfig;
@Get('/session-info')
getSessionInfo() {
// Access built-in runtime config
return {
sessionName: this.config.runtimeConfig?.session?.name,
sessionDuration: this.config.runtimeConfig?.session?.duration
};
}
}
RuntimeConfig.runtimeConfig is always optional (undefined until the app initializes), so always use optional chaining (?.) when accessing it.Custom Runtime Configuration
You can add your own runtime configuration with full type safety:
Step 1: Define Your Config Type
export interface AppConfig {
database: {
host: string;
port: number;
name: string;
};
api: {
baseUrl: string;
timeout: number;
};
}
Step 2: Use Type Parameter in defineConfig
import { defineConfig } from '@vercube/core';
import type { AppConfig } from './src/types/AppConfig';
export default defineConfig<AppConfig>({
runtime: {
// Built-in session config still works
session: {
secret: process.env.SESSION_SECRET!,
duration: 60 * 60 * 24 * 7
},
// Your custom configuration with full autocomplete
database: {
host: process.env.DB_HOST || 'localhost',
port: parseInt(process.env.DB_PORT || '5432'),
name: process.env.DB_NAME || 'myapp'
},
api: {
baseUrl: process.env.API_URL || 'https://api.example.com',
timeout: 5000
}
}
});
Step 3: Access Your Config with Type Safety
import { RuntimeConfig } from '@vercube/core';
import type { AppConfig } from '../types/AppConfig';
export class DatabaseService {
@Inject(RuntimeConfig)
private config!: RuntimeConfig<AppConfig>;
async connect() {
const dbConfig = this.config.runtimeConfig?.database;
if (!dbConfig) {
throw new Error('Database configuration not found');
}
// Full autocomplete for your config!
console.log(`Connecting to ${dbConfig.host}:${dbConfig.port}/${dbConfig.name}`);
}
}
Environment Variables
Vercube automatically loads environment variables from .env files using c12.
Basic Usage
Create a .env file in your project root:
NODE_ENV=development
SESSION_SECRET=my-secret-key
DB_HOST=localhost
DB_PORT=5432
API_URL=https://api.example.com
Access in your config:
export default defineConfig({
runtime: {
session: {
secret: process.env.SESSION_SECRET || 'fallback-secret'
},
database: {
host: process.env.DB_HOST || 'localhost',
port: parseInt(process.env.DB_PORT || '5432')
}
}
});
Customizing .env Loading
export default defineConfig({
c12: {
dotenv: {
// Custom .env file path
fileName: '.env.local',
// Load from specific directory
cwd: process.cwd()
}
}
});
Disabling .env Loading
export default defineConfig({
c12: {
dotenv: false // Disable automatic .env loading
}
});
Default Configuration
If you don't provide a vercube.config.ts file, Vercube uses these defaults:
{
logLevel: 'debug',
production: process.env.NODE_ENV === 'production',
dev: process.env.NODE_ENV !== 'production',
build: {
root: process.cwd(),
entry: 'src/index.ts',
output: {
dir: 'dist',
publicDir: 'public'
},
bundler: 'rolldown'
},
server: {
runtime: 'node',
host: 'localhost',
port: 3000,
https: false,
static: {
dirs: ['public']
}
},
runtime: {
session: {
secret: '<randomly-generated>',
name: 'vercube_session',
duration: 60 * 60 * 24 * 7 // 7 days
}
},
experimental: {}
}
You only need to override the values you want to change.
Configuration by Environment
export default defineConfig({
logLevel: 'debug',
dev: true,
server: {
port: 3000,
host: 'localhost'
}
});
export default defineConfig({
logLevel: 'warn',
production: true,
server: {
port: parseInt(process.env.PORT || '8080'),
host: '0.0.0.0' // Listen on all interfaces
},
runtime: {
session: {
secret: process.env.SESSION_SECRET!,
duration: 60 * 60 * 24 * 30 // 30 days
}
}
});
const isDev = process.env.NODE_ENV !== 'production';
export default defineConfig({
logLevel: isDev ? 'debug' : 'warn',
production: !isDev,
dev: isDev,
server: {
port: isDev ? 3000 : parseInt(process.env.PORT || '8080'),
host: isDev ? 'localhost' : '0.0.0.0'
}
});
Complete Example
Here's a real-world configuration example:
import { defineConfig } from '@vercube/core';
import type { AppConfig } from './src/types/AppConfig';
const isDev = process.env.NODE_ENV !== 'production';
export default defineConfig<AppConfig>({
// Environment
production: !isDev,
dev: isDev,
logLevel: isDev ? 'debug' : 'info',
// Server
server: {
runtime: 'node',
host: isDev ? 'localhost' : '0.0.0.0',
port: parseInt(process.env.PORT || '3000'),
https: isDev ? false : {
key: './certs/privkey.pem',
cert: './certs/fullchain.pem'
},
static: {
dirs: ['public', 'uploads'],
maxAge: isDev ? 0 : 86400, // No cache in dev, 1 day in prod
immutable: !isDev,
etag: true
}
},
// Runtime configuration
runtime: {
session: {
secret: process.env.SESSION_SECRET || 'dev-secret',
name: 'app_session',
duration: 60 * 60 * 24 * (isDev ? 7 : 30) // 7 days dev, 30 days prod
},
// Custom app config
database: {
host: process.env.DB_HOST || 'localhost',
port: parseInt(process.env.DB_PORT || '5432'),
name: process.env.DB_NAME || 'myapp',
ssl: !isDev
},
redis: {
host: process.env.REDIS_HOST || 'localhost',
port: parseInt(process.env.REDIS_PORT || '6379')
},
api: {
baseUrl: process.env.API_URL || 'https://api.example.com',
timeout: 5000,
retries: 3
},
features: {
enableWebSockets: true,
enableFileUploads: true,
maxUploadSize: 10 * 1024 * 1024 // 10MB
}
},
// Build config (for vercube CLI)
build: {
root: process.cwd(),
entry: 'src/index.ts',
output: {
dir: 'dist',
publicDir: 'public'
},
dts: true,
define: {
'process.env.BUILD_TIME': JSON.stringify(new Date().toISOString())
}
}
});
Troubleshooting
Config is undefined at runtime
Make sure you're injecting RuntimeConfig, not trying to import the config file directly:
// ❌ Wrong - config file can't be imported
import config from './vercube.config';
// ✅ Correct - inject RuntimeConfig
@Inject(RuntimeConfig)
private config!: RuntimeConfig;
TypeScript errors with custom config
Make sure you're passing your type to defineConfig:
// ❌ Missing type parameter
export default defineConfig({
runtime: {
myCustomConfig: { ... } // TypeScript error!
}
});
// ✅ With type parameter
export default defineConfig<MyConfig>({
runtime: {
myCustomConfig: { ... } // Works!
}
});
Environment variables not loading
Check that your .env file is in the project root and that dotenv loading is enabled (it is by default).