# Configuration Directory in usekaneo/kaneo: How Environment Configuration Works

> Discover how usekaneo/kaneo manages environment configuration. Learn about its decentralized approach using .env.sample and config.ts modules instead of a central directory.

- Repository: [kaneo.app/kaneo](https://github.com/usekaneo/kaneo)
- Tags: how-to-guide
- Published: 2026-08-04

---

**No, usekaneo/kaneo does not have a top-level configuration directory.** Instead, the project uses a **decentralized environment-based approach** where configuration is split between a central `.env.sample` file and feature-specific [`config.ts`](https://github.com/usekaneo/kaneo/blob/main/config.ts) modules throughout the codebase.

This approach keeps configuration scoped to the services and plugins that actually need it, rather than centralizing everything in a single folder. The **Kaneo** project is a TypeScript-based monorepo, and its configuration pattern reflects modern Node.js best practices for environment-driven applications.

---

## How Kaneo Handles Configuration Without a Config Directory

### The Central Environment File

All runtime configuration starts with **`.env.sample`** at the repository root. This file serves as the single source of truth for required environment variables:

1. `KANEO_CLIENT_URL` – URL for the frontend client
2. `KANEO_API_URL` – URL for the API server
3. `AUTH_SECRET` – Secret key for authentication
4. `DATABASE_URL` – PostgreSQL connection string
5. `POSTGRES_DB`, `POSTGRES_USER`, `POSTGRES_PASSWORD` – Database credentials
6. `CORS_ORIGINS` – Allowed CORS origins
7. `VITE_API_URL` – API URL for Vite build process
8. `REDIS_URL` – Redis connection string

Developers copy this to `.env` and fill in actual values. The project loads these via `dotenv/config` at runtime.

---

## Feature-Specific Configuration Files

### Billing Configuration

In [`apps/api/src/billing/config.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/billing/config.ts), the billing system reads its settings directly from `process.env`:

```typescript
import { env } from "process";

export const BILLING_ENABLED = env.BILLING_ENABLED === "true";
export const STRIPE_SECRET_KEY = env.STRIPE_SECRET_KEY ?? "";
export const STRIPE_WEBHOOK_SECRET = env.STRIPE_WEBHOOK_SECRET ?? "";
export const STRIPE_PUBLIC_KEY = env.STRIPE_PUBLIC_KEY ?? "";

```

This pattern validates and transforms environment variables at the module boundary, converting `BILLING_ENABLED` from string to boolean and providing defaults with nullish coalescing.

### Plugin Configuration Modules

Each integration plugin follows the same decentralized pattern. In [`apps/api/src/plugins/slack/config.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/plugins/slack/config.ts):

```typescript
export const SLACK_BOT_TOKEN = process.env.SLACK_BOT_TOKEN ?? "";
export const SLACK_APP_ID = process.env.SLACK_APP_ID ?? "";
export const SLACK_SIGNING_SECRET = process.env.SLACK_SIGNING_SECRET ?? "";

```

The GitHub, Discord, and other plugins implement identical [`config.ts`](https://github.com/usekaneo/kaneo/blob/main/config.ts) files in their respective directories.

---

## Practical Configuration Examples

### Loading Environment Variables

```typescript
// apps/api/src/index.ts or entry point
import "dotenv/config"; // Loads .env into process.env automatically

// Access variables anywhere in the application
const apiUrl = process.env.KANEO_API_URL;

```

### Using Billing Configuration

```typescript
// In a billing controller or service
import { BILLING_ENABLED, STRIPE_SECRET_KEY } from "./config";

if (!BILLING_ENABLED) {
  throw new HTTPException(403, "Billing is disabled");
}

// Initialize Stripe only when billing is enabled
import Stripe from "stripe";
const stripe = new Stripe(STRIPE_SECRET_KEY, { apiVersion: "2023-10-16" });

```

### Using Slack Plugin Configuration

```typescript
// apps/api/src/plugins/slack/client.ts
import { WebClient } from "@slack/web-api";
import { SLACK_BOT_TOKEN } from "./config";

// Fail fast if not configured
if (!SLACK_BOT_TOKEN) {
  console.warn("Slack integration disabled: SLACK_BOT_TOKEN not set");
}

export const slackClient = SLACK_BOT_TOKEN 
  ? new WebClient(SLACK_BOT_TOKEN) 
  : null;

```

---

## Configuration File Locations

| File Path | Purpose |
|-----------|---------|
| `.env.sample` | Template for all required environment variables |
| [`apps/api/src/billing/config.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/billing/config.ts) | Billing feature configuration wrapper |
| [`apps/api/src/plugins/slack/config.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/plugins/slack/config.ts) | Slack integration settings |
| [`apps/api/src/plugins/github/config.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/plugins/github/config.ts) | GitHub integration settings |
| [`apps/api/src/plugins/discord/config.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/plugins/discord/config.ts) | Discord integration settings |

---

## Why Kaneo Avoids a Central Config Directory

This decentralized approach provides three advantages:

- **Scoped configuration** – Each module owns its settings, reducing merge conflicts
- **Lazy loading** – Configuration modules are only imported when features are used
- **Type safety** – TypeScript can enforce config shapes per feature without a global type definition

The pattern aligns with the **conventional configuration** approach used in modern JavaScript frameworks, where environment variables replace static config files.

---

## Summary

- **usekaneo/kaneo has no `config/` directory** – configuration is environment-driven
- **`.env.sample`** at root defines all required variables for the entire application
- **Feature-specific [`config.ts`](https://github.com/usekaneo/kaneo/blob/main/config.ts) files** in `apps/api/src/**` transform and export relevant `process.env` values
- **Billing, Slack, GitHub, Discord, and other plugins** each maintain their own configuration module
- The pattern enables **optional features** to disable gracefully when environment variables are absent

---

## Frequently Asked Questions

### Where do I set database credentials in Kaneo?

Database credentials go in the `.env` file, copied from `.env.sample`. Set `DATABASE_URL` with the full PostgreSQL connection string, or use the split `POSTGRES_DB`, `POSTGRES_USER`, and `POSTGRES_PASSWORD` variables for Docker Compose setups.

### How do I enable billing in Kaneo?

Set `BILLING_ENABLED=true` in your `.env` file and provide the three Stripe-related variables: `STRIPE_SECRET_KEY`, `STRIPE_WEBHOOK_SECRET`, and `STRIPE_PUBLIC_KEY`. The billing module in [`apps/api/src/billing/config.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/billing/config.ts) automatically picks these up.

### Can I add a custom config directory to Kaneo?

While possible, it would break the established pattern. If you need additional configuration, create a new [`config.ts`](https://github.com/usekaneo/kaneo/blob/main/config.ts) file in the relevant feature directory following the existing pattern of reading from `process.env` with nullish coalescing for defaults.

### How does Kaneo handle missing environment variables?

Each [`config.ts`](https://github.com/usekaneo/kaneo/blob/main/config.ts) module handles missing variables independently. Most use the `?? ""` pattern to provide empty string defaults, while critical variables like `DATABASE_URL` typically cause startup failures if absent. Check [`ENVIRONMENT_SETUP.md`](https://github.com/usekaneo/kaneo/blob/main/ENVIRONMENT_SETUP.md) in the repository for required vs. optional variables.