Configuration Directory in usekaneo/kaneo: How Environment Configuration Works
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 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:
KANEO_CLIENT_URL– URL for the frontend clientKANEO_API_URL– URL for the API serverAUTH_SECRET– Secret key for authenticationDATABASE_URL– PostgreSQL connection stringPOSTGRES_DB,POSTGRES_USER,POSTGRES_PASSWORD– Database credentialsCORS_ORIGINS– Allowed CORS originsVITE_API_URL– API URL for Vite build processREDIS_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, the billing system reads its settings directly from process.env:
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:
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 files in their respective directories.
Practical Configuration Examples
Loading Environment Variables
// 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
// 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
// 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 |
Billing feature configuration wrapper |
apps/api/src/plugins/slack/config.ts |
Slack integration settings |
apps/api/src/plugins/github/config.ts |
GitHub integration settings |
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.sampleat root defines all required variables for the entire application- Feature-specific
config.tsfiles inapps/api/src/**transform and export relevantprocess.envvalues - 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 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 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 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 in the repository for required vs. optional variables.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →