Configuration Reference
Stacks uses a convention-over-configuration approach. All configuration files live in the config/ directory and use TypeScript for full type safety.
App Configuration
// config/app.ts
export default {
// Application name
name: 'My App',
// Environment (development, staging, production)
env: process.env.APP_ENV ?? 'development',
// Debug mode (enables detailed error pages, logging)
debug: process.env.APP_DEBUG === 'true',
// Application URL
url: process.env.APP_URL ?? 'http://localhost',
// Timezone
timezone: 'UTC',
// Locale settings
locale: 'en',
fallbackLocale: 'en',
// Encryption key (auto-generated on install)
key: process.env.APP_KEY,
// Cipher for encryption
cipher: 'aes-256-gcm',
// Maintenance mode
maintenance: {
driver: 'file',
secret: process.env.MAINTENANCE_SECRET,
refresh: 60,
},
// Service providers (auto-discovered by default)
providers: [
// '@stacksjs/database',
// '@stacksjs/auth',
// '@stacksjs/queue',
],
}
Server Configuration
// config/server.ts
export default {
// Server host
host: process.env.HOST ?? 'localhost',
// Server port
port: Number(process.env.PORT ?? 3000),
// HTTPS configuration
https: {
enabled: process.env.HTTPS === 'true',
cert: process.env.SSL_CERT,
key: process.env.SSL_KEY,
// Auto-generate development certificates
autoGenerate: true,
},
// Maximum request body size
maxBodySize: '10mb',
// Request timeout (ms)
timeout: 30_000,
// Keep-alive timeout (ms)
keepAliveTimeout: 5_000,
// Headers timeout (ms)
headersTimeout: 60_000,
// Compression
compression: {
enabled: true,
threshold: 1024, // Minimum size to compress
level: 6,
},
// Static file serving
static: {
enabled: true,
path: './public',
maxAge: 86400, // 1 day cache
index: ['index.html'],
etag: true,
lastModified: true,
},
// Hot module replacement (development)
hmr: {
enabled: true,
port: 24678,
},
}
Database Configuration
// config/database.ts
export default {
// Default connection
default: process.env.DB_CONNECTION ?? 'sqlite',
// Available connections
connections: {
sqlite: {
driver: 'sqlite',
database: process.env.DB_DATABASE ?? './storage/database.sqlite',
foreignKeys: true,
busyTimeout: 5000,
journal: 'wal',
},
mysql: {
driver: 'mysql',
host: process.env.DB_HOST ?? '127.0.0.1',
port: Number(process.env.DB_PORT ?? 3306),
database: process.env.DB_DATABASE ?? 'stacks',
username: process.env.DB_USERNAME ?? 'root',
password: process.env.DB_PASSWORD ?? '',
charset: 'utf8mb4',
collation: 'utf8mb4_unicode_ci',
pool: {
min: 2,
max: 10,
acquireTimeout: 60_000,
idleTimeout: 10_000,
},
},
postgres: {
driver: 'postgres',
host: process.env.DB_HOST ?? '127.0.0.1',
port: Number(process.env.DB_PORT ?? 5432),
database: process.env.DB_DATABASE ?? 'stacks',
username: process.env.DB_USERNAME ?? 'postgres',
password: process.env.DB_PASSWORD ?? '',
schema: 'public',
sslMode: process.env.DB_SSL ?? 'prefer',
pool: {
min: 2,
max: 10,
},
},
dynamodb: {
driver: 'dynamodb',
region: process.env.AWS_REGION ?? 'us-east-1',
endpoint: process.env.DYNAMODB_ENDPOINT,
table: process.env.DYNAMODB_TABLE ?? 'stacks',
// Single Table Design enabled by default
singleTable: true,
},
},
// Migration settings
migrations: {
path: './database/migrations',
table: 'migrations',
autoRun: false,
},
// Seeder settings
seeders: {
path: './database/seeders',
},
}
Authentication Configuration
// config/auth.ts
export default {
// Default guard
defaults: {
guard: 'web',
passwords: 'users',
},
// Authentication guards
guards: {
web: {
driver: 'session',
provider: 'users',
},
api: {
driver: 'token',
provider: 'users',
hash: true,
inputKey: 'api_token',
storageKey: 'api_token',
},
sanctum: {
driver: 'sanctum',
provider: 'users',
},
},
// User providers
providers: {
users: {
driver: 'database',
model: 'User',
table: 'users',
},
},
// Password reset settings
passwords: {
users: {
provider: 'users',
table: 'password_resets',
expire: 60, // minutes
throttle: 60, // seconds
},
},
// Session configuration
session: {
driver: process.env.SESSION_DRIVER ?? 'file',
lifetime: 120, // minutes
expireOnClose: false,
encrypt: true,
cookie: 'stacks_session',
path: '/',
domain: null,
secure: process.env.NODE_ENV === 'production',
httpOnly: true,
sameSite: 'lax',
},
// Token settings
tokens: {
expiry: '7d',
refresh: true,
refreshExpiry: '30d',
},
// OAuth providers
oauth: {
github: {
clientId: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET,
redirectUri: '/auth/github/callback',
scopes: ['user:email'],
},
google: {
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
redirectUri: '/auth/google/callback',
scopes: ['email', 'profile'],
},
},
// Two-factor authentication
twoFactor: {
enabled: true,
issuer: 'Stacks',
algorithm: 'sha1',
digits: 6,
period: 30,
},
}
Cache Configuration
// config/cache.ts
export default {
// Default cache driver
default: process.env.CACHE_DRIVER ?? 'file',
// Cache stores
stores: {
file: {
driver: 'file',
path: './storage/cache',
},
memory: {
driver: 'memory',
maxSize: 100_000_000, // 100MB
},
redis: {
driver: 'redis',
connection: 'cache',
lockConnection: 'default',
},
dynamodb: {
driver: 'dynamodb',
table: 'cache',
ttlAttribute: 'expires_at',
},
},
// Cache key prefix
prefix: process.env.CACHE_PREFIX ?? 'stacks_cache_',
// Default TTL (seconds)
ttl: 3600,
}
Queue Configuration
// config/queue.ts
export default {
// Default queue connection
default: process.env.QUEUE_CONNECTION ?? 'redis',
// Queue connections
connections: {
sync: {
driver: 'sync',
},
redis: {
driver: 'redis',
connection: 'default',
queue: 'default',
retry_after: 90,
block_for: 5,
},
sqs: {
driver: 'sqs',
key: process.env.AWS_ACCESS_KEY_ID,
secret: process.env.AWS_SECRET_ACCESS_KEY,
region: process.env.AWS_REGION ?? 'us-east-1',
prefix: process.env.SQS_PREFIX,
queue: process.env.SQS_QUEUE ?? 'default',
},
},
// Failed job settings
failed: {
driver: 'database',
table: 'failed_jobs',
maxRetries: 3,
},
// Default job options
defaults: {
attempts: 3,
timeout: 60,
backoff: [10, 30, 60], // Retry delays in seconds
},
// Named queues with priorities
queues: {
high: { priority: 1 },
default: { priority: 5 },
low: { priority: 10 },
},
}
Mail Configuration
// config/mail.ts
export default {
// Default mailer
default: process.env.MAIL_MAILER ?? 'smtp',
// Mailer configurations
mailers: {
smtp: {
driver: 'smtp',
host: process.env.MAIL_HOST ?? 'localhost',
port: Number(process.env.MAIL_PORT ?? 587),
encryption: process.env.MAIL_ENCRYPTION ?? 'tls',
username: process.env.MAIL_USERNAME,
password: process.env.MAIL_PASSWORD,
timeout: 30,
},
ses: {
driver: 'ses',
region: process.env.AWS_REGION ?? 'us-east-1',
credentials: {
key: process.env.AWS_ACCESS_KEY_ID,
secret: process.env.AWS_SECRET_ACCESS_KEY,
},
},
resend: {
driver: 'resend',
apiKey: process.env.RESEND_API_KEY,
},
log: {
driver: 'log',
channel: 'mail',
},
},
// Global "From" address
from: {
address: process.env.MAIL_FROM_ADDRESS ?? 'noreply@example.com',
name: process.env.MAIL_FROM_NAME ?? 'Stacks',
},
// Markdown mail settings
markdown: {
theme: 'default',
paths: ['./resources/views/emails'],
},
}
Storage Configuration
// config/storage.ts
export default {
// Default disk
default: process.env.FILESYSTEM_DISK ?? 'local',
// Storage disks
disks: {
local: {
driver: 'local',
root: './storage/app',
visibility: 'private',
},
public: {
driver: 'local',
root: './storage/app/public',
url: '/storage',
visibility: 'public',
},
s3: {
driver: 's3',
bucket: process.env.AWS_BUCKET,
region: process.env.AWS_REGION ?? 'us-east-1',
credentials: {
key: process.env.AWS_ACCESS_KEY_ID,
secret: process.env.AWS_SECRET_ACCESS_KEY,
},
url: process.env.AWS_URL,
endpoint: process.env.AWS_ENDPOINT,
visibility: 'private',
cacheControl: 'max-age=31536000',
},
},
// Symbolic links
links: {
'./public/storage': './storage/app/public',
},
// Upload settings
uploads: {
maxSize: '100mb',
allowedMimeTypes: ['image/*', 'application/pdf', 'video/*'],
hashFilenames: true,
},
}
Logging Configuration
// config/logging.ts
export default {
// Default log channel
default: process.env.LOG_CHANNEL ?? 'stack',
// Log channels
channels: {
stack: {
driver: 'stack',
channels: ['daily', 'stderr'],
ignoreExceptions: false,
},
single: {
driver: 'single',
path: './storage/logs/stacks.log',
level: 'debug',
},
daily: {
driver: 'daily',
path: './storage/logs/stacks.log',
level: 'debug',
days: 14,
},
stderr: {
driver: 'stderr',
level: 'warning',
formatter: process.env.LOG_STDERR_FORMATTER ?? 'pretty',
},
syslog: {
driver: 'syslog',
level: 'debug',
facility: 'local0',
},
},
// Log levels: emergency, alert, critical, error, warning, notice, info, debug
level: process.env.LOG_LEVEL ?? 'debug',
// Deprecation logging
deprecations: {
channel: 'stderr',
trace: true,
},
}
Security Configuration
// config/security.ts
export default {
// HTTPS settings
https: {
enabled: process.env.FORCE_HTTPS === 'true',
autoGenerate: true,
hsts: {
enabled: true,
maxAge: 31536000,
includeSubDomains: true,
preload: true,
},
},
// CSRF protection
csrf: {
enabled: true,
cookie: 'XSRF-TOKEN',
header: 'X-XSRF-TOKEN',
except: ['/api/webhooks/*'],
},
// Rate limiting
rateLimit: {
enabled: true,
driver: 'redis',
limits: {
api: { max: 60, window: 60 },
auth: { max: 5, window: 300 },
global: { max: 1000, window: 60 },
},
headers: {
limit: 'X-RateLimit-Limit',
remaining: 'X-RateLimit-Remaining',
reset: 'X-RateLimit-Reset',
},
},
// Content Security Policy
csp: {
enabled: true,
reportOnly: false,
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "'strict-dynamic'"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", 'data:', 'https:'],
fontSrc: ["'self'", 'https:', 'data:'],
connectSrc: ["'self'", 'wss:', 'https:'],
mediaSrc: ["'self'"],
objectSrc: ["'none'"],
frameSrc: ["'none'"],
frameAncestors: ["'none'"],
formAction: ["'self'"],
baseUri: ["'self'"],
upgradeInsecureRequests: true,
},
reportUri: '/csp-report',
},
// Other security headers
headers: {
xContentTypeOptions: 'nosniff',
xFrameOptions: 'DENY',
xXssProtection: '1; mode=block',
referrerPolicy: 'strict-origin-when-cross-origin',
permissionsPolicy: 'geolocation=(), microphone=(), camera=()',
},
// CORS settings
cors: {
enabled: true,
origin: process.env.CORS_ORIGIN?.split(',') ?? ['*'],
methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'],
exposedHeaders: ['X-RateLimit-Limit', 'X-RateLimit-Remaining'],
credentials: true,
maxAge: 86400,
},
// Cookie settings
cookies: {
secure: process.env.NODE_ENV === 'production',
httpOnly: true,
sameSite: 'lax',
encrypt: true,
path: '/',
domain: null,
},
// Request validation
validation: {
sanitize: true,
stripUnknown: true,
},
}
Cloud Configuration (ts-cloud)
// config/cloud.ts
export default {
// Cloud driver
driver: process.env.CLOUD_DRIVER ?? 'aws',
// Project settings
project: {
name: 'my-app',
slug: 'my-app',
region: process.env.AWS_REGION ?? 'us-east-1',
environment: process.env.APP_ENV ?? 'development',
},
// Deployment settings
deploy: {
type: 'serverless', // or 'server', 'containers'
domain: process.env.APP_DOMAIN,
certificateArn: process.env.AWS_CERTIFICATE_ARN,
},
// Infrastructure
infrastructure: {
// API Gateway / Load Balancer
api: {
type: 'http-api',
cors: true,
throttling: {
rateLimit: 10000,
burstLimit: 5000,
},
},
// Lambda / Compute
compute: {
runtime: 'provided.al2023',
architecture: 'arm64',
memory: 1024,
timeout: 30,
reservedConcurrency: 100,
},
// Database
database: {
type: 'dynamodb',
billingMode: 'PAY_PER_REQUEST',
},
// Storage
storage: {
type: 's3',
versioning: true,
encryption: true,
},
// CDN
cdn: {
enabled: true,
priceClass: 'PriceClass_100',
compress: true,
},
// Caching
cache: {
type: 'elasticache',
engine: 'redis',
nodeType: 'cache.t3.micro',
},
},
// CI/CD
pipeline: {
enabled: true,
repository: 'github.com/org/repo',
branch: 'main',
autoDeploy: true,
},
}
Broadcasting Configuration
// config/broadcasting.ts
export default {
// Default broadcaster
default: process.env.BROADCAST_DRIVER ?? 'stacks',
// Broadcaster configurations
connections: {
// Stacks native WebSocket server (recommended - like Laravel Reverb)
stacks: {
driver: 'stacks',
host: process.env.BROADCAST_HOST ?? 'localhost',
port: Number(process.env.BROADCAST_PORT ?? 6001),
// TLS configuration
tls: {
enabled: process.env.BROADCAST_TLS === 'true',
cert: process.env.BROADCAST_TLS_CERT,
key: process.env.BROADCAST_TLS_KEY,
},
// Scaling with Redis (for multi-server deployments)
scaling: {
enabled: false,
redis: {
host: process.env.REDIS_HOST ?? 'localhost',
port: Number(process.env.REDIS_PORT ?? 6379),
},
},
// App credentials (for channel authentication)
app: {
id: process.env.BROADCAST_APP_ID ?? 'stacks',
key: process.env.BROADCAST_APP_KEY ?? 'stacks-key',
secret: process.env.BROADCAST_APP_SECRET ?? 'stacks-secret',
},
// Connection limits
maxConnections: 10000,
maxChannelsPerConnection: 100,
maxPayloadSize: 64 * 1024, // 64KB
},
// Pusher-compatible broadcaster (third-party)
pusher: {
driver: 'pusher',
key: process.env.PUSHER_APP_KEY,
secret: process.env.PUSHER_APP_SECRET,
appId: process.env.PUSHER_APP_ID,
cluster: process.env.PUSHER_CLUSTER ?? 'us2',
useTLS: true,
},
// Redis pub/sub broadcaster
redis: {
driver: 'redis',
connection: 'default',
queue: 'broadcasts',
},
// Null driver (for testing)
null: {
driver: 'null',
},
},
// Channel authorization endpoint
authEndpoint: '/broadcasting/auth',
}
Notification Configuration
// config/notifications.ts
export default {
// Default channels
defaults: ['database', 'email'],
// Channel configurations
channels: {
database: {
driver: 'database',
table: 'notifications',
model: 'Notification',
},
email: {
driver: 'mail',
mailer: 'default',
queue: true,
},
sms: {
driver: 'twilio',
sid: process.env.TWILIO_SID,
token: process.env.TWILIO_TOKEN,
from: process.env.TWILIO_FROM,
},
slack: {
driver: 'slack',
webhookUrl: process.env.SLACK_WEBHOOK_URL,
channel: '#notifications',
},
push: {
driver: 'fcm',
credentials: process.env.FCM_CREDENTIALS,
},
},
// Queueing
queue: {
enabled: true,
connection: 'redis',
queue: 'notifications',
},
}
Scheduler Configuration
// config/scheduler.ts
export default {
// Timezone for scheduled jobs
timezone: 'UTC',
// Scheduled jobs
jobs: [
{
job: 'PruneExpiredTokensJob',
cron: '0 0 * * *', // Daily at midnight
withoutOverlapping: true,
},
{
job: 'SendScheduledNotificationsJob',
cron: '* * * * *', // Every minute
runInBackground: true,
},
{
job: 'GenerateDailyReportsJob',
cron: '0 6 * * *', // Daily at 6 AM
onOneServer: true, // Only run on one server in cluster
},
{
job: 'CleanupTempFilesJob',
cron: '0 3 * * *', // Daily at 3 AM
evenInMaintenanceMode: true,
},
],
// Maintenance
maintenance: {
logOutput: true,
emailOnFailure: 'admin@example.com',
},
}
Frontend Configuration
// config/frontend.ts
export default {
// Build settings
build: {
outDir: './dist',
assetsDir: 'assets',
sourcemap: process.env.NODE_ENV !== 'production',
minify: process.env.NODE_ENV === 'production',
},
// Dev server
dev: {
port: 5173,
open: false,
hmr: true,
},
// Assets
assets: {
hashFilenames: true,
publicPath: '/',
},
// CSS
css: {
preprocessor: 'headwind',
modules: true,
sourceMap: true,
},
// TypeScript
typescript: {
strict: true,
noEmit: true,
},
}
Complete stacks.config.ts
The main configuration file that ties everything together:
// stacks.config.ts
export default {
// Application identity
name: 'My Stacks App',
description: 'A modern full-stack application',
version: '1.0.0',
// Import all config files
app: './config/app',
server: './config/server',
database: './config/database',
auth: './config/auth',
cache: './config/cache',
queue: './config/queue',
mail: './config/mail',
storage: './config/storage',
logging: './config/logging',
security: './config/security',
cloud: './config/cloud',
notifications: './config/notifications',
scheduler: './config/scheduler',
frontend: './config/frontend',
// Path aliases
paths: {
'@': './app',
'@models': './app/Models',
'@controllers': './app/Controllers',
'@middleware': './app/Middleware',
'@components': './resources/components',
},
// Auto-discovery
autoload: {
models: './app/Models',
controllers: './app/Controllers',
middleware: './app/Middleware',
jobs: './app/Jobs',
events: './app/Events',
listeners: './app/Listeners',
},
}