---
url: /foehn-framework/guide/configuration.md
---
# Configuration

Each config class is customized by creating a `*.config.php` file in your app directory.

## How Config Files Work

Føhn reads every file matching the `*.config.php` pattern in the directories it discovers. Each file must return a config class instance:

```php
<?php
// app/timber.config.php

use Studiometa\Foehn\Config\TimberConfig;

return new TimberConfig(
    templatesDir: ['views', 'templates'],
);
```

Føhn registers the returned instance in the container, under its own class and any interface it implements, so anything asking for a `TimberConfig` receives yours. If no config file is found, sensible defaults are used.

Installed packages are read before your own files, so a package can ship defaults that your project overrides.

### Per-environment files

A file can be named for an environment, and is then read only in that one, as reported by [`wp_get_environment_type()`](https://developer.wordpress.org/reference/functions/wp_get_environment_type/):

| File                          | Read when the environment is |
| ----------------------------- | ---------------------------- |
| `foehn.config.php`            | always                       |
| `foehn.local.config.php`      | `local`                      |
| `foehn.dev.config.php`        | `development`                |
| `foehn.staging.config.php`    | `staging`                    |
| `foehn.production.config.php` | `production`                 |

The environment's own file wins over the plain file beside it, so the plain one holds what every environment shares:

```php
<?php
// app/foehn.config.php — the default everywhere

use Studiometa\Foehn\Config\FoehnConfig;
use Tempest\Discovery\DiscoveryCacheStrategy;

return new FoehnConfig(discoveryCacheStrategy: DiscoveryCacheStrategy::NONE);
```

```php
<?php
// app/foehn.production.config.php — production caches discovery

use Studiometa\Foehn\Config\FoehnConfig;
use Tempest\Discovery\DiscoveryCacheStrategy;

return new FoehnConfig(discoveryCacheStrategy: DiscoveryCacheStrategy::FULL);
```

::: warning
A config file replaces the object, it does not merge into it. `Kernel::boot()`'s configuration array is a default that a `foehn.config.php` overrides wholesale — prefer the file.
:::

## Available Config Classes

### FoehnConfig — Core Settings

Controls the bootstrap process: discovery caching, debug mode, and opt-in hooks.

```php
<?php
// app/foehn.config.php

use Studiometa\Foehn\Config\FoehnConfig;
use Studiometa\Foehn\Hooks\Cleanup\CleanHeadTags;
use Tempest\Discovery\DiscoveryCacheStrategy;

return new FoehnConfig(
    discoveryCacheStrategy: DiscoveryCacheStrategy::FULL,
    hooks: [CleanHeadTags::class],
    debug: false,
);
```

| Property                 | Type                     | Default | Description                    |
| ------------------------ | ------------------------ | ------- | ------------------------------ |
| `discoveryCacheStrategy` | `DiscoveryCacheStrategy` | `NONE`  | Discovery cache strategy       |
| `discoveryCachePath`     | `?string`                | `null`  | Custom cache path              |
| `hooks`                  | `class-string[]`         | `[]`    | Opt-in hook classes            |
| `debug`                  | `bool`                   | `false` | Enable discovery debug logging |

See [FoehnConfig API](/api/foehn-config) for details.

### TimberConfig — Templates

Controls where Timber looks for `.twig` template files.

```php
<?php
// app/timber.config.php

use Studiometa\Foehn\Config\TimberConfig;

return new TimberConfig(
    templatesDir: ['views'],
);
```

| Property       | Type       | Default         | Description              |
| -------------- | ---------- | --------------- | ------------------------ |
| `templatesDir` | `string[]` | `['templates']` | Template directory names |

See [TimberConfig API](/api/timber-config) for details.

### AcfConfig — ACF Integration

Controls how ACF fields are handled in blocks.

```php
<?php
// app/acf.config.php

use Studiometa\Foehn\Config\AcfConfig;

return new AcfConfig(
    transformFields: true,
);
```

| Property          | Type   | Default | Description                               |
| ----------------- | ------ | ------- | ----------------------------------------- |
| `transformFields` | `bool` | `true`  | Auto-convert ACF values to Timber objects |

See [AcfConfig API](/api/acf-config) for details.

### RestConfig — REST API

Controls default permissions for `#[AsRestRoute]` endpoints.

```php
<?php
// app/rest.config.php

use Studiometa\Foehn\Config\RestConfig;

return new RestConfig(
    defaultCapability: 'edit_posts',
);
```

| Property            | Type      | Default        | Description                   |
| ------------------- | --------- | -------------- | ----------------------------- |
| `defaultCapability` | `?string` | `'edit_posts'` | Default capability for routes |

See [RestConfig API](/api/rest-config) for details.

### QueryFiltersConfig — URL Query Filtering

Controls which custom taxonomies and query vars are exposed via URL parameters.

```php
<?php
// app/query-filters.config.php

use Studiometa\Foehn\Config\QueryFiltersConfig;

return new QueryFiltersConfig(
    taxonomies: [
        'genre' => ['in', 'not_in'],
        'product_cat' => ['in'],
    ],
    publicVars: [
        'posts_per_page' => [12, 24, 48],
    ],
);
```

See [Guide: Query Filters](/guide/query-filters) for details.

## Override Priority

When multiple sources provide the same config:

1. **Environment config file** (`app/*.{environment}.config.php`) — highest priority
2. **Config file** (`app/*.config.php`)
3. **Package config file** — defaults an installed package ships
4. **Kernel::boot() array** — legacy fallback (only for `FoehnConfig`)
5. **Defaults** — built-in defaults from the config class constructor

## Environment-Specific Configuration

Use PHP logic in your config files for environment-specific settings:

```php
<?php
// app/foehn.config.php

use Studiometa\Foehn\Config\FoehnConfig;
use Tempest\Discovery\DiscoveryCacheStrategy;

$isDev = defined('WP_DEBUG') && WP_DEBUG;

return new FoehnConfig(
    discoveryCacheStrategy: $isDev
        ? DiscoveryCacheStrategy::NONE
        : DiscoveryCacheStrategy::FULL,
    debug: $isDev,
);
```

## File Structure Example

```
theme/
├── app/
│   ├── foehn.config.php         # Core configuration
│   ├── timber.config.php        # Template directories
│   ├── acf.config.php           # ACF settings
│   ├── rest.config.php          # REST API defaults
│   ├── query-filters.config.php # Query filter rules
│   ├── foehn.production.config.php # Read in production only
│   ├── Hooks/
│   ├── Models/
│   └── ...
└── functions.php
```

## Related

* [API: FoehnConfig](/api/foehn-config)
* [API: TimberConfig](/api/timber-config)
* [API: AcfConfig](/api/acf-config)
* [API: RestConfig](/api/rest-config)
* [Guide: Section Rendering](/guide/section-rendering)
* [Guide: Theme Conventions](/guide/theme-conventions)
