> ## Documentation Index
> Fetch the complete documentation index at: https://docs.modelence.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Configuration

> Define typed configuration schemas and access them with Module.getConfig and createClientModule(...).getConfig. Available since modelence@0.15.0.

Modelence modules support a `configSchema` that lets you define typed, named
configuration values. These values can be managed through Modelence Cloud and
accessed at runtime via typed accessors.

This is the recommended way to store settings like API keys, feature toggles,
default values, and any other configuration your module needs — without
hardcoding them or relying solely on environment variables.

## Version Requirements

Configuration accessors in this guide require:

* `Module.getConfig()` - available since `modelence@0.15.0`
* `createClientModule(...).getConfig()` - available since `modelence@0.15.0`

## Defining a Config Schema

Add a `configSchema` to your module definition. Each key becomes a configuration
value namespaced under the module name:

```typescript title="src/server/payments/index.ts" theme={null}
import { Module } from 'modelence/server';

export default new Module('payments', {
  configSchema: {
    apiKey: {
      type: 'secret',
      default: '',
      isPublic: false,
    },
    currency: {
      type: 'string',
      default: 'USD',
      isPublic: true,
    },
    maxRetries: {
      type: 'number',
      default: 3,
      isPublic: false,
    },
  },
});
```

Each config field requires three properties:

| Property   | Type             | Description                                             |
| ---------- | ---------------- | ------------------------------------------------------- |
| `type`     | `ConfigType`     | The data type — see [Config Types](#config-types) below |
| `default`  | *(matches type)* | Default value used when no value has been set           |
| `isPublic` | `boolean`        | Whether this value is accessible on the client          |

## Config Types

The `type` field accepts one of five values:

| Type        | Value Type | Description                                                                                          |
| ----------- | ---------- | ---------------------------------------------------------------------------------------------------- |
| `'string'`  | `string`   | A short text value (single line)                                                                     |
| `'text'`    | `string`   | A longer text value (multi-line, rendered as a textarea in Cloud)                                    |
| `'number'`  | `number`   | A numeric value                                                                                      |
| `'boolean'` | `boolean`  | A true/false toggle                                                                                  |
| `'secret'`  | `string`   | A sensitive value like an API key or token. Masked in the Cloud dashboard. **Cannot be `isPublic`.** |

<Warning>
  Config values with `type: 'secret'` cannot have `isPublic: true`. Modelence
  will throw an error at startup if this rule is violated.
</Warning>

## Reading Config Values

### Server-side

Call `getConfig` directly on the module instance. The return type is inferred
automatically from the schema — no casts needed:

`Module.getConfig()` is available since `modelence@0.15.0`.

```typescript title="src/server/payments/index.ts" theme={null}
import { Module } from 'modelence/server';

const paymentsModule = new Module('payments', {
  configSchema: {
    apiKey: { type: 'secret', default: '', isPublic: false },
    maxRetries: { type: 'number', default: 3, isPublic: false },
  },
  mutations: {
    async charge({ amount }) {
      const apiKey = paymentsModule.getConfig('apiKey');     // string
      const retries = paymentsModule.getConfig('maxRetries'); // number
      // ...
    },
  },
});

export default paymentsModule;
```

### Client-side

Use `createClientModule` to create a typed accessor for a module's public config values.
Pass the module type via `import type` — no server code is bundled on the client.

`createClientModule(...).getConfig()` is available since `modelence@0.15.0`.

```typescript title="src/client/payments.ts" theme={null}
import type paymentsModule from '../server/payments';
import { createClientModule } from 'modelence/client';

export const payments = createClientModule<typeof paymentsModule>('payments');
```

```typescript title="src/components/Checkout.tsx" theme={null}
import { payments } from '../client/payments';

function Checkout() {
  const currency = payments.getConfig('currency'); // string | undefined

  return <div>Currency: {currency}</div>;
}
```

Only values marked `isPublic: true` are available on the client. Private and
`secret` values are **not** sent to the client and will not appear as valid keys.

For typed query and mutation wrappers, see:

* [Queries](/core-concepts/queries)
* [Mutations](/core-concepts/mutations)

## Managing Values in Modelence Cloud

Once your module defines a `configSchema`, the configuration fields appear
automatically in the Modelence Cloud dashboard:

1. Go to [cloud.modelence.com](https://cloud.modelence.com)
2. Select your environment
3. Open the **Application** tab
4. Find your module's configuration section
5. Set values and save

Changes sync to your running application automatically (within \~10 seconds).

<Tip>
  Config values set in Modelence Cloud take precedence over defaults defined in
  your code. Environment variables take precedence over both.
</Tip>

## Examples

### Storing a third-party API key

```typescript title="src/server/ai/index.ts" theme={null}
import { Module } from 'modelence/server';

const aiModule = new Module('ai', {
  configSchema: {
    apiKey: {
      type: 'secret',
      default: '',
      isPublic: false,
    },
    model: {
      type: 'string',
      default: 'gpt-4o',
      isPublic: false,
    },
  },

  mutations: {
    async generateResponse({ prompt }: { prompt: string }) {
      const apiKey = aiModule.getConfig('apiKey'); // string
      const model = aiModule.getConfig('model');   // string

      if (!apiKey) {
        throw new Error('AI API key not configured');
      }

      const response = await fetch('https://api.openai.com/v1/chat/completions', {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${apiKey}`,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          model,
          messages: [{ role: 'user', content: prompt }],
        }),
      });

      return response.json();
    },
  },
});

export default aiModule;
```

### Feature toggle with a boolean config

```typescript title="src/server/notifications/index.ts" theme={null}
import { Module } from 'modelence/server';

const notificationsModule = new Module('notifications', {
  configSchema: {
    emailEnabled: {
      type: 'boolean',
      default: true,
      isPublic: false,
    },
    footer: {
      type: 'text',
      default: 'You are receiving this because you signed up for our service.',
      isPublic: false,
    },
  },

  mutations: {
    async sendNotification({ userId, message }: { userId: string; message: string }) {
      const emailEnabled = notificationsModule.getConfig('emailEnabled'); // boolean

      if (!emailEnabled) {
        return { skipped: true };
      }

      const footer = notificationsModule.getConfig('footer'); // string
      // Send email with message + footer...
    },
  },
});

export default notificationsModule;
```

### Exposing config to the client

```typescript title="src/server/app/index.ts" theme={null}
import { Module } from 'modelence/server';

export default new Module('app', {
  configSchema: {
    appName: {
      type: 'string',
      default: 'My App',
      isPublic: true,
    },
    maintenanceMode: {
      type: 'boolean',
      default: false,
      isPublic: true,
    },
  },
});
```

```typescript title="src/client/app.ts" theme={null}
import type appModule from '../server/app';
import { createClientModule } from 'modelence/client';

export const app = createClientModule<typeof appModule>('app');
```

```typescript title="src/components/Header.tsx" theme={null}
import { app } from '../client/app';

function Header() {
  const appName = app.getConfig('appName');         // string | undefined
  const maintenance = app.getConfig('maintenanceMode'); // boolean | undefined

  if (maintenance) {
    return <div>We are currently undergoing maintenance. Please check back soon.</div>;
  }

  return <h1>{appName}</h1>;
}
```

## Type Reference

See the full API reference for config types:

* [`ConfigSchema`](/api-reference/modelence/server/type-aliases/ConfigSchema) — The schema object passed to a module
* [`ConfigType`](/api-reference/modelence/server/type-aliases/ConfigType) — The union of allowed type values
* [`getConfig` (server)](/api-reference/modelence/server/functions/getConfig) — Read config on the server (untyped, for dynamic keys)
* [`getConfig` (client)](/api-reference/modelence/client/functions/getConfig) — Read config on the client (untyped, for dynamic keys)
