Logo
Configuration Management

Configuration Management

Type-safe configuration for every environment. Stop scattering .env files across your codebase. Define schemas with Zod, manage three tiers of config values, and sync across your team with the CLI.

Architecture

The config system is built on three core concepts that work together to provide type-safe, environment-aware configuration.

Schemas

Define the shape and validation rules for your configuration. Each key has a type, default value, and description.

Environments

Isolate configuration by deployment stage (development, staging, production) or any custom environment.

Values

Set values per environment with three tiers: public (client-safe), secret (server-only), and feature flags.

CLI in Action

The smooai-config CLI lets you manage configuration directly from your terminal. Initialize projects, push schemas, and pull values without leaving your workflow.

smooai-config
$ smooai-config init
Initializing Smoo AI Config...
Created smooai.config.ts
Created .env.smooai
$ smooai-config push --env production
Pushing config to production...
Validated 8 public keys
Validated 3 secret keys
Validated 2 feature flags
Config pushed successfully
$ smooai-config pull --env staging
Pulling config from staging...
Written 13 values to .env.smooai
Config is up to date
pnpm add @smooai/config

defineConfig

The defineConfig function is the heart of the config system. Define your schema using Zod validators, organized into three tiers. The CLI and SDK both read from this definition.

import { defineConfig } from '@smooai/config';
import { z } from 'zod';

export default defineConfig({
    public: {
        API_URL: z.string().url().describe('Base URL for the API'),
        APP_NAME: z.string().default('My App'),
        SUPPORT_EMAIL: z.string().email().default('[email protected]'),
        MAX_UPLOAD_SIZE_MB: z.number().int().positive().default(10),
    },
    secret: {
        DATABASE_URL: z.string().describe('PostgreSQL connection string'),
        JWT_SECRET: z.string().min(32).describe('Secret for signing JWTs'),
        STRIPE_SECRET_KEY: z.string().startsWith('sk_'),
    },
    featureFlags: {
        NEW_DASHBOARD: z.boolean().default(false),
        DARK_MODE: z.boolean().default(true),
        AI_SUGGESTIONS: z.boolean().default(false),
    },
});

Supports any Standard Schema validator — while this example uses Zod, you can also use Valibot, ArkType, or any library that implements the Standard Schema interface.

Three-Tier Configuration

Public Config

Safe to expose to clients and browsers. Examples: API base URLs, feature names, UI theme settings. Accessible via usePublicConfig() in React.

Secret Config

Server-only values that should never be exposed to clients. Examples: API keys, database credentials, signing secrets. Only accessible in server-side code. Automatically blocked for B2M (browser) API keys.

Feature Flags

Boolean toggles for gradual rollouts and A/B testing. Enable or disable features per environment without redeploying. Use useFeatureFlag() in React.

React Integration

Wrap your app with ConfigProvider and access config values anywhere with type-safe hooks.

import { ConfigProvider, usePublicConfig, useFeatureFlag } from '@smooai/config/react';

// In your app root
function App() {
    return (
        <ConfigProvider schemaId="your-schema-id" environmentId="your-env-id">
            <Dashboard />
        </ConfigProvider>
    );
}

// In any component
function Dashboard() {
    const appName = usePublicConfig('APP_NAME');
    const showNewDashboard = useFeatureFlag('NEW_DASHBOARD');

    return (
        <div>
            <h1>{appName}</h1>
            {showNewDashboard ? <NewDashboard /> : <LegacyDashboard />}
        </div>
    );
}

Security: API Key Types

The Config API enforces tier-based access control depending on your API key type. Browser-to-Machine (B2M) keys are designed for frontend clients and automatically restrict access to protect sensitive data.

OperationB2M (Public Key)M2M (Secret Key)
Read public valuesYesYes
Read feature flagsYesYes
Read secret valuesNo (filtered)Yes
Write config valuesNo (403)Yes
Delete config valuesNo (403)Yes

Use B2M keys in frontend apps — they are safe to embed in browser code. Secret-tier values are automatically excluded from API responses. Use M2M keys only in server-side code where secrets are needed.

Next.js Integration

For Next.js applications, fetch config on the server and pass it to client components with zero loading flash using getConfig and SmooConfigProvider.

// app/layout.tsx (Server Component)
import { getConfig, SmooConfigProvider } from '@smooai/config/nextjs';

export default async function RootLayout({ children }: { children: React.ReactNode }) {
    const config = await getConfig({
        environment: 'production',
        fetchOptions: { next: { revalidate: 60 } }, // ISR: revalidate every 60s
    });

    return (
        <html><body>
            <SmooConfigProvider
                initialValues={config}
                baseUrl={process.env.SMOOAI_CONFIG_API_URL}
                apiKey={process.env.SMOOAI_CONFIG_API_KEY}
                orgId={process.env.SMOOAI_CONFIG_ORG_ID}
                environment="production"
            >
                {children}
            </SmooConfigProvider>
        </body></html>
    );
}

// Any client component — values available instantly (no loading flash)
'use client';
import { usePublicConfig, useFeatureFlag } from '@smooai/config/nextjs';

function Dashboard() {
    const { value: apiUrl } = usePublicConfig<string>('API_URL');
    const { value: showNew } = useFeatureFlag<boolean>('NEW_DASHBOARD');
    return <div>{showNew ? <NewDashboard apiUrl={apiUrl} /> : <LegacyDashboard />}</div>;
}

Vite React Integration

For Vite-based React apps, call preloadConfig() before mounting React to start fetching config as early as possible.

// main.tsx
import { preloadConfig } from '@smooai/config/vite';
import { ConfigProvider } from '@smooai/config/vite';
import { createRoot } from 'react-dom/client';

// Start fetching config immediately (before React renders)
preloadConfig({ environment: 'production' });

createRoot(document.getElementById('root')!).render(
    <ConfigProvider
        baseUrl="https://config.smooai.dev"
        apiKey="your-b2m-public-key"
        orgId="your-org-id"
        environment="production"
    >
        <App />
    </ConfigProvider>
);

Multi-Language Support

Use the config SDK in any language. The same schema definition drives type-safe config access across your entire stack.

import { createConfigClient } from "@smooai/config";

const config = createConfigClient({
    serverUrl: "https://api.smoo.ai",
    token: process.env.SMOO_ACCESS_TOKEN!,
    schemaId: "your-schema-id",
    environmentId: "your-env-id",
});

const apiUrl = await config.get("API_URL");       // string
const retries = await config.get("MAX_RETRIES");   // number
const darkMode = await config.flag("DARK_MODE");   // boolean

Environment Management

Each environment gets its own set of config values. Public values, secrets, and feature flags flow independently per environment so you can test features in staging without affecting production.

KeyDevelopmentStagingProduction
API_URLlocalhost:3000staging.api.comapi.example.com
DATABASE_URLlocal postgresstaging dbproduction db
NEW_DASHBOARDtruetruefalse

REST API

The Config API provides full CRUD for schemas, environments, and values. All endpoints require authentication.

Create a Config Schema

curl -X POST https://api.smoo.ai/organizations/{org_id}/config-schemas \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "my-app-config",
    "description": "Configuration for my application",
    "schema": {
      "API_URL": { "type": "string", "default": "https://api.example.com" },
      "MAX_RETRIES": { "type": "number", "default": 3 },
      "DEBUG_MODE": { "type": "boolean", "default": false }
    }
  }'

Set Config Values

curl -X PUT https://api.smoo.ai/organizations/{org_id}/config-values \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "schemaId": "schema_id",
    "environmentId": "env_id",
    "values": {
      "API_URL": "https://api.production.example.com",
      "MAX_RETRIES": 5
    }
  }'

SDK Usage

Use the @smooai/config SDK to read configuration values in your application with type safety and local caching.

import { createConfigClient } from "@smooai/config";

const config = createConfigClient({
    serverUrl: "https://api.smoo.ai",
    token: process.env.SMOO_ACCESS_TOKEN!,
    schemaId: "your-schema-id",
    environmentId: "your-env-id",
});

// Type-safe config access
const apiUrl = await config.get("API_URL");
const maxRetries = await config.get("MAX_RETRIES");