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

# Configuration

> Aikeedo's three layers of configuration: environment variables, computed config values, and database-backed options.

Configuration comes from three places, with different lifetimes and audiences.

| Layer | Set by | Where it lives | Read as |
| - | - | - | - |
| Environment | The person installing | `.env` | `env('NAME')` |
| Config | Computed at bootstrap | Memory | `config.*` container IDs |
| Options | Administrators in the panel | The `option` table | `option.*` container IDs |

## Environment variables

`.env` is loaded at bootstrap, falling back to `.env.example` for keys it doesn't define. These settings belong to the installation, not the business.

### Application

| Variable | Purpose |
| - | - |
| `ENVIRONMENT` | `prod`, `dev`, `demo` or `install`. `install` routes everything to the installer; `demo` is used for public demo installations. |
| `DEBUG` | Shows errors, disables caches, makes Twig strict, and rethrows plugin boot failures. |
| `CACHE` | Enables template, route, listener and metadata caching, when debug is off. |
| `JWT_TOKEN` | Secret used to sign session tokens. |
| `APP_ENCRYPTION_KEY` | Master key for credentials encrypted at rest, such as connector sign-ins. `base64:` followed by 32 random bytes; generated by the installer, by the 5.1 update, or by `php bin/console app:generate-key`. Back it up with the database: replacing or losing it makes stored credentials unreadable. |
| `PUBLIC_DIR` | Web root directory name, such as `public` or `public_html`. |

### Database

| Variable | Purpose |
| - | - |
| `DB_DRIVER` | `mysql`. Leaving it empty means no database, which is how the installer boots. |
| `DB_HOST`, `DB_PORT`, `DB_NAME`, `DB_USER`, `DB_PASSWORD` | Connection details. |
| `DB_CHARSET` | Character set, normally `utf8mb4`. |
| `DB_UNIX_SOCKET` | Socket path, as an alternative to host and port. |

### Frontend and assets

| Variable | Purpose |
| - | - |
| `HMR` | Load application assets from the Vite dev server instead of the build. |
| `ASSETS_SERVER` | That dev server's URL, defaulting to `http://localhost:5173`. |
| `THEME_ASSETS_SERVER` | The theme dev server's URL, normally port 5174. Overrides theme asset resolution whenever it's set. |

### Sessions, logs and tooling

| Variable | Purpose |
| - | - |
| `COOKIE_DOMAIN`, `COOKIE_PREFIX` | Cookie scope and naming, for multi-app domains. Misconfiguring these breaks sign-in. |
| `LOG_MAX_FILES`, `LOG_ERROR_MAX_FILES` | How many rotated log files to keep. |
| `COMPOSER_HOME` | Composer's home directory, used when installing plugins. |

Read them with the global helper, which takes a default:

```php theme={null}
$environment = env('ENVIRONMENT', 'prod');
```

<Warning>
  Environment variables are exposed to Twig as the `env` global. Read a specific key when a template genuinely needs one, and never dump or serialize the object.
</Warning>

## Config values

Computed at bootstrap and injected by ID:

```php theme={null}
use Easy\Container\Attributes\Inject;

public function __construct(
    #[Inject('config.dirs.uploads')]
    private string $uploads,

    #[Inject('config.enable_debugging')]
    private bool $debug = false,
) {}
```

| ID | Value |
| - | - |
| `config.dirs.root` | Installation root |
| `config.dirs.webroot` | Web root, honoring `PUBLIC_DIR` |
| `config.dirs.cache`, `.log` | `var/cache`, `var/log` |
| `config.dirs.src`, `.views` | `src`, `resources/views` |
| `config.dirs.uploads` | `{webroot}/uploads` |
| `config.dirs.locale` | `locale` |
| `config.dirs.extensions` | `extra/extensions` |
| `config.dirs.artifacts` | `extra/artifacts` |
| `config.enable_debugging` | `DEBUG`, as a boolean |
| `config.enable_caching` | `CACHE`, as a boolean |
| `config.locale` | The language catalogue from `locale/locale.json` |

Two more IDs are set alongside them: `version`, read from the `VERSION` file, and `license`.

## Options

Options are rows of JSON, edited by administrators. They're loaded once per request and exposed as dot paths:

```php theme={null}
#[Inject('option.billing.currency')]
private ?string $currency = 'USD',

#[Inject('option.features.chat.is_enabled')]
private ?bool $chatEnabled = false,
```

In Twig they're all under `option`:

```twig theme={null}
{{ option.site.name ?? '' }}
{% if option.features.chat.is_enabled|default(false) %}…{% endif %}
```

### Common option groups

| Prefix | Controls |
| - | - |
| `option.site.*` | Name, domain, HTTPS, landing page, verification policy |
| `option.brand.*` | Logos and favicon |
| `option.color_scheme.*` | Light and dark modes, accent colors |
| `option.features.*` | Feature switches, including the REST APIs |
| `option.billing.*` | Currency, usage mode, tax engine, fallback plan, trials |
| `option.credit_rate` | Per-rate credit pricing |
| `option.mail.*`, `option.smtp.*` | Mail transport |
| `option.cdn.*` | Storage adapter, URL signing, grouping |
| `option.embeddings.*` | Vector store adapter and embedding model |
| `option.policies.*` | Legal page contents |
| `option.script_tags.*` | Analytics and support widgets |
| `option.theme` | The active theme |

### Writing options

```php theme={null}
use Option\Application\Commands\SaveOptionCommand;

$this->dispatcher->dispatch(new SaveOptionCommand(
    'acme',
    json_encode(['api_key' => $key])
));
```

Writes merge into the existing JSON: nested objects are merged recursively, and lists are replaced. `DeleteOptionCommand` removes a key, including a nested one.

Administrator-facing forms post to the options API rather than calling this directly. See [Admin settings pages](/development/plugins/admin-settings-pages).

## Which layer to use

| Setting | Layer |
| - | - |
| Credentials for the installation itself, such as the database | Environment |
| Anything an administrator should change without editing files | Options |
| Paths and derived flags | Config |

<Note>
  Options require a database, so anything needed before the database exists, such as the debug flag, has to be an environment variable.
</Note>

## Related

* [Dependency injection](/development/core/dependency-injection)
* [Bootstrap and lifecycle](/development/core/bootstrap-and-lifecycle)
* [Local development](/development/local-development)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.