Skip to content

Configuration

CruzJS uses a typed configuration file (cruz.config.ts) in your app root to define deployment bindings, environment variables, and deployment settings. When deploying to Cloudflare (the default), the CLI reads this file to generate wrangler.toml and manage infrastructure. Other deployment targets use their respective adapter configuration.

Create a cruz.config.ts file in your app root (e.g., apps/web/cruz.config.ts):

import { defineConfig } from '@cruzjs/cli/config';
export default defineConfig({
name: 'myapp',
compatibilityDate: '2024-12-01',
compatibilityFlags: ['nodejs_compat'],
bindings: {
d1: true, // D1 SQL database
kv: true, // KV key-value store (caching)
r2: false, // R2 object storage
ai: false, // Workers AI
aiGateway: false, // AI Gateway
vectorize: false, // Vectorize vector DB
queues: false, // Queues
rateLimiting: false, // Rate limiting
},
email: {
provider: 'mailchannels', // 'mailchannels' | 'resend' | 'none'
},
vars: {
APP_NAME: 'My Application',
},
environments: {
production: {
vars: {
NODE_ENV: 'production',
APP_URL: 'https://myapp.example.com',
},
domain: 'myapp.example.com',
},
staging: {
vars: {
NODE_ENV: 'staging',
APP_URL: 'https://staging.myapp.example.com',
},
},
},
});
OptionTypeDefaultDescription
namestring(required)App name. Used as a prefix for all cloud resources (e.g., myapp-production-db).
compatibilityDatestringCloudflare Workers compatibility date (Cloudflare adapter only).
compatibilityFlagsstring[]Cloudflare compatibility flags (Cloudflare adapter only). nodejs_compat is required for CruzJS on Cloudflare.
bindingsCruzBindings{ d1: true, kv: true }Which platform bindings your app uses. Each adapter maps these to native services.
emailCruzEmailConfig{ provider: 'none' }Email provider configuration.
varsRecord<string, string>{}Variables shared across all environments.
migrationsDirstring'./src/database/migrations'Path to Drizzle migration files relative to app root.
environmentsRecord<string, CruzEnvironmentConfig>{}Per-environment overrides.
BindingDescriptionResource Created
d1SQL database. D1 on Cloudflare, RDS/Aurora on AWS, Cloud SQL on GCP, etc.<name>-<env>-db
kvKey-value cache. KV on Cloudflare, Redis (ElastiCache/Memorystore/etc.) on other adapters.<name>-<env>-kv
r2Object storage. R2 on Cloudflare, S3 on AWS, GCS on GCP, Blob Storage on Azure.<name>-<env>-bucket
aiAI inference. Workers AI on Cloudflare, Bedrock on AWS, Vertex AI on GCP, OpenAI-compatible elsewhere.Platform-specific
aiGatewayAI request logging, caching, and rate limiting (Cloudflare-specific).<name>-<env>-ai-gateway
vectorizeVector database for semantic search and RAG applications.<name>-<env>-vectorize
queuesMessage queues for async processing. Queues on Cloudflare, SQS on AWS, Pub/Sub on GCP.<name>-<env>-queue
rateLimitingBuilt-in rate limiting for API endpoints.Configured per route

CruzJS supports multiple .env files for different environments:

FilePurpose
.envLocal development (default)
.env.exampleTemplate for required variables (committed to source control)

For production and staging, environment variables are set as Cloudflare secrets (not in .env files):

Terminal window
# Set a secret for an environment
cruz secrets set AUTH_SECRET --env production
# List secrets
cruz secrets list --env production
VariableDescription
AUTH_SECRETSession encryption key. Must be a strong random string (32+ characters).
DATABASE_URLLocal dev only. The value depends on your adapter (e.g., file:./dev.db for Cloudflare/SQLite, a PostgreSQL connection string for other adapters). In production, the adapter provides the database binding automatically.
VariableDescription
GOOGLE_CLIENT_IDGoogle OAuth client ID for social login.
GOOGLE_CLIENT_SECRETGoogle OAuth client secret.
SCM_ENCRYPTION_KEYEncryption key for sensitive data fields.
STRIPE_SECRET_KEYStripe API key (only with @cruzjs/pro billing).
STRIPE_WEBHOOK_SECRETStripe webhook signing secret.

Accessing Variables at Runtime with ConfigService

Section titled “Accessing Variables at Runtime with ConfigService”

Environment variables and vars from cruz.config.ts are accessible through the ConfigService:

import { Injectable, Inject } from '@cruzjs/core/di';
import { ConfigService } from '@cruzjs/core/shared/config/config.service';
@Injectable()
export class MyService {
constructor(
@Inject(ConfigService) private readonly config: ConfigService
) {}
doSomething() {
// Get a required value (throws if missing)
const appUrl = this.config.getOrThrow<string>('APP_URL');
// Get an optional value with a default
const appName = this.config.get<string>('APP_NAME', 'My App');
}
}

Variables from cruz.config.ts are also bridged to process.env during Cloudflare context initialization, so they are available via standard Node.js patterns. However, using ConfigService is preferred for type safety and testability.

CruzJS exposes platform bindings through injectable services rather than direct platform APIs. This keeps your application code portable across adapters.

The database is managed by Drizzle ORM. Inject the DRIZZLE token to access it:

import { Injectable, Inject } from '@cruzjs/core/di';
import { DRIZZLE, type DrizzleDatabase } from '@cruzjs/core/shared/database/drizzle.service';
@Injectable()
export class MyService {
constructor(@Inject(DRIZZLE) private readonly db: DrizzleDatabase) {}
}

The adapter determines the underlying driver automatically — D1 on Cloudflare, PostgreSQL on AWS/GCP/Azure, or SQLite locally.

Use KVCacheService for key-value caching. See Caching for full details:

import { Injectable, Inject } from '@cruzjs/core/di';
import { KVCacheServiceFactory, KVCacheService } from '@cruzjs/core/shared/cloudflare/kv-cache.service';
@Injectable()
export class ProductService {
private cache: KVCacheService;
constructor(@Inject(KVCacheServiceFactory) cacheFactory: KVCacheServiceFactory) {
this.cache = cacheFactory.create('products');
}
async getProduct(id: string) {
const cached = await this.cache.get<Product>(`detail:${id}`);
if (cached) return cached;
// ... fetch from database and populate cache
}
}

Use StorageService for file uploads and media. See File Storage for full details:

import { Injectable, Inject } from '@cruzjs/core/di';
import { StorageService } from '@cruzjs/core/shared/storage/storage.service.server';
@Injectable()
export class DocumentService {
constructor(@Inject(StorageService) private readonly storage: StorageService) {}
async upload(key: string, content: Buffer) {
const driver = this.storage.disk();
await driver.put(key, content, { contentType: 'application/pdf' });
}
}

Use AIService for text generation, embeddings, and more. See AI Integration for full details:

import { Injectable, Inject } from '@cruzjs/core/di';
import { AIService } from '@cruzjs/core';
@Injectable()
export class SummaryService {
constructor(@Inject(AIService) private readonly ai: AIService) {}
async summarize(text: string) {
return this.ai.chat({ prompt: text, system: 'Summarize concisely.' });
}
}

When deploying to Cloudflare, CruzJS uses a consistent naming convention for all resources. Other adapters use the name field from cruz.config.ts as a resource prefix in their respective platforms.

<app-name>-<environment>-<resource-type>

For example, an app named myapp creates:

ResourceProductionStaging
D1 Databasemyapp-production-dbmyapp-staging-db
KV Namespacemyapp-production-kvmyapp-staging-kv
R2 Bucketmyapp-production-bucketmyapp-staging-bucket

This naming is handled automatically by cruz init and cruz deploy. You do not need to create or name resources manually.