---
title: Configuration
---

Mantle is configured in two places: PHP constants that must be defined before the plugin boots, and a settings option managed through the admin UI, the REST API, or WP-CLI.

## Constants

`mantle.php` defines these constants at load time. Only the three guarded ones can be overridden from `wp-config.php`; the rest are fixed values the plugin uses internally.

<!-- wp:docspress/fields {"title":"Plugin constants","description":"Defined in <code>mantle.php</code>. Constants marked overridable are wrapped in <code>if ( ! defined( … ) )</code>, so a value set earlier in <code>wp-config.php</code> wins.","fields":[{"name":"MANTLE_PLUGIN_DEBUG","type":"boolean","required":false,"defaultValue":"false","description":"Overridable. Enables plugin debug behaviour.","values":"true, false","deprecated":false},{"name":"MANTLE_PLUGIN_DEV_MODE","type":"boolean","required":false,"defaultValue":"false","description":"Overridable. Enables development-mode behaviour.","values":"true, false","deprecated":false},{"name":"MANTLE_SSO_PREFLIGHT_SALT","type":"string","required":false,"defaultValue":"mantle-sso-preflight-salt","description":"Overridable. Salt used when signing SSO preflight requests. Change this per site.","values":"","deprecated":false},{"name":"MANTLE_PLUGIN_VERSION","type":"string","required":false,"defaultValue":"2.1.23","description":"Fixed. Managed by release-please; also drives the migration check.","values":"","deprecated":false},{"name":"MANTLE_PLUGIN_FILE","type":"string","required":false,"defaultValue":"","description":"Fixed. Absolute path to <code>mantle.php</code>.","values":"","deprecated":false},{"name":"MANTLE_PLUGIN_PATH","type":"string","required":false,"defaultValue":"","description":"Fixed. Plugin directory path from <code>plugin_dir_path()</code>.","values":"","deprecated":false},{"name":"MANTLE_PLUGIN_URL","type":"string","required":false,"defaultValue":"","description":"Fixed. Plugin directory URL from <code>plugin_dir_url()</code>.","values":"","deprecated":false},{"name":"MANTLE_PLUGIN_NAME","type":"string","required":false,"defaultValue":"Mantle","description":"Fixed. Display name.","values":"","deprecated":false},{"name":"MANTLE_API_URL","type":"url","required":false,"defaultValue":"https://api.linchpin.com/api/v1","description":"Fixed. Linchpin API base URL used for site reporting and connection.","values":"","deprecated":false},{"name":"MANTLE_SHOP_URI","type":"url","required":false,"defaultValue":"https://shop.linchpin.com","description":"Fixed. Licence server used for activation and deactivation.","values":"","deprecated":false},{"name":"MANTLE_SHOP_PRODUCT_ID","type":"number","required":false,"defaultValue":"1616","description":"Fixed. Mantle's product ID on the licence server.","values":"","deprecated":false},{"name":"DISALLOW_FILE_EDIT","type":"boolean","required":false,"defaultValue":"true","description":"WordPress core constant. Mantle forces this to <code>true</code> unless already defined, disabling the plugin and theme file editors.","values":"true, false","deprecated":false}],"searchable":true,"compact":false} /-->

To override an overridable constant, define it in `wp-config.php` above the `require_once ABSPATH . 'wp-settings.php';` line:

<!-- wp:docspress/colorful-code {"language":"php","filename":"wp-config.php","code":"// Per-site SSO salt. Do not reuse across environments.\ndefine( 'MANTLE_SSO_PREFLIGHT_SALT', 'replace-with-a-unique-random-string' );\n\n// Keep the WordPress file editors available.\ndefine( 'DISALLOW_FILE_EDIT', false );\n\nrequire_once ABSPATH . 'wp-settings.php';","highlightedLines":"2,5","showLineNumbers":true,"caption":"Constants must be defined before WordPress loads plugins.","copyMode":"all","diffMode":"none"} /-->

<!-- wp:docspress/callout {"tone":"danger","title":"Change MANTLE_SSO_PREFLIGHT_SALT before enabling SSO","content":"<p>The default salt is a literal string committed to the repository, so it is identical on every installation that does not override it. Define a unique random value per site before switching the <code>sso</code> module on.</p>","collapsible":false} /-->

## Settings

All module settings live in a single serialised WordPress option named `mantle`. The schema is assembled at runtime: `Mantle\Model\Settings::get_settings_schema()` applies a filter that every module hooks into, so the schema always describes exactly the modules present on the site.

<!-- wp:docspress/diagram {"title":"How a settings key comes to exist","type":"flow","source":"Module -> register_schema: on Module_Loader::init\nregister_schema -> settings filter: add module keys\nsettings filter -> get_settings_schema: assembled schema\nget_settings_schema -> get_settings: merge saved over defaults\nget_settings -> REST + CLI + admin UI: read and write","caption":"Modules contribute schema keys whether or not they are enabled, so saved values are never orphaned."} /-->

Reading a setting merges saved values over schema defaults, and any saved key absent from the schema is discarded on read. That means removing a module makes its keys inert rather than corrupting the option.

For the complete list of keys, see the [settings reference](../reference/settings.md).

### Reading and writing settings

<!-- wp:docspress/code-tabs {"tabs":[{"label":"PHP","language":"php","filename":"example.php","code":"$settings = new \\Mantle\\Model\\Settings();\n\n// Read one key.\n$enabled = $settings->get_setting( 'maintenance_enabled' );\n\n// Write one key.\n$settings->save_setting( 'maintenance_enabled', true );"},{"label":"WP-CLI","language":"bash","filename":"Terminal","code":"# Audit the whole option against the schema.\nwp mantle settings audit\n\n# Toggle maintenance mode.\nwp mantle maintenance enable"},{"label":"REST","language":"bash","filename":"Terminal","code":"# Read every setting the current user may see.\ncurl --cookie \"$COOKIE\" \\\n  -H \"X-WP-Nonce: $NONCE\" \\\n  https://example.com/wp-json/mantle/v1/settings"}],"showLineNumbers":false,"caption":"The same option is reachable from PHP, WP-CLI, and the REST API."} /-->

<!-- wp:docspress/callout {"tone":"warning","title":"Multi-line settings need explicit allow-listing","content":"<p>The REST settings controller sanitises string values with <code>sanitize_text_field()</code>, which strips newlines. Keys that legitimately hold multi-line text or Markdown must be listed in the controller's textarea allow-list, or their line breaks are silently removed on save.</p>","collapsible":false} /-->

## Migrations

On every `init` (priority 100) Mantle compares the `version` setting with `MANTLE_PLUGIN_VERSION`. When the stored version is older, it runs its migrations and writes the new version back. It also ensures the AI chatbot conversations table exists; that check short-circuits on a single autoloaded option read when the schema is current.

## Next steps

- [First run](first-run.md) — the setup wizard and enabling modules.
- [Settings reference](../reference/settings.md) — every registered key.
