Configuration

Ava CMS's configuration is simple and transparent. All settings live in app/config/ as plain PHP files.

Quick Start: The settings most people change first

Open app/config/ava.php and update these:

'site' => [
    'name'        => 'My Awesome Site',
    'base_url'    => 'https://example.com',    // Full URL, no trailing slash
    'timezone'    => 'Europe/London',          // php.net/timezones
    'locale'      => 'en_GB',                  // php.net/setlocale
    'date_format' => 'F j, Y',                 // php.net/datetime.format
],

See Site Identity below for details on each option, or the PHP date format reference for date formatting.

Why PHP Configs?

We use PHP arrays instead of YAML or JSON because:

  1. It's Readable: You can add comments to explain why you changed a setting.
  2. It's Powerful: You can use constants, logic, or helper functions right in your config.
  3. It's Standard: No special parsers or hidden .env files to debug.

The Config Files

File What it controls
ava.php Main site settings (name, URL, cache, themes, plugins, security).
content_types.php Defines your content types (Pages, Posts, etc.). See also Writing Content.
taxonomies.php Defines how you group content (Categories, Tags). See also Taxonomy Fields.
users.php Admin users (managed automatically by CLI). See User Management.

Main Settings (ava.php)

This is where you set up your site's identity and behavior.

Site Identity

return [
    'site' => [
        'name'        => 'My Awesome Site',
        'base_url'    => 'https://example.com',    // Full URL, no trailing slash
        'timezone'    => 'Europe/London',          // php.net/timezones
        'locale'      => 'en_GB',                  // php.net/setlocale
        'date_format' => 'F j, Y',                 // php.net/datetime.format
    ],
    // ...
];
Option Type Default Description
site.name string 'Ava CMS Site' Your site's display name. Used in templates, RSS feeds, sitemaps, and admin.
site.base_url string required Full URL (no trailing slash). Used for sitemaps, canonical URLs, and absolute links.
site.timezone string 'UTC' Timezone for dates. Use a PHP timezone identifier.
site.locale string 'en_GB' Locale for date/number formatting. See PHP locale codes.
site.date_format string 'F j, Y' Default format for $ava->date(). Uses PHP date() format codes.

In templates: Access site info via $site['name'], $site['url'], and $site['timezone']. See Theming - Template Variables.

Paths

Directory locations for your content, themes, plugins, and other assets.

Important: Most people should not change these paths from the defaults. Only change them if you have a specific reason. Aliases are safe to customize.
'paths' => [
    'content'  => 'content',       // Where your Markdown files live
    'themes'   => 'app/themes',    // Where theme folders live
    'plugins'  => 'app/plugins',   // Where plugin folders live
    'snippets' => 'app/snippets',  // Snippets for [snippet] shortcode
    'storage'  => 'storage',       // Cache, logs, and temporary files

    'aliases' => [
        '@media‎:' => '/media/',
    ],
],
Option Type Default Description
paths.content string 'content' Directory containing your Markdown content files.
paths.themes string 'app/themes' Directory containing theme folders.
paths.plugins string 'app/plugins' Directory containing plugin folders.
paths.snippets string 'app/snippets' Directory for PHP snippets. See Shortcodes - Snippets.
paths.storage string 'storage' Directory for cache files, logs, and temporary data.
paths.aliases array ['@media‎:' => '/media/'] Path aliases for use in content. See Writing Content - Images and Media.

All paths are relative to your project root unless they start with /.

Theme

'theme' => 'default',
Option Type Default Description
theme string 'default' The active theme folder name inside app/themes/.

See: Theming for theme structure, template variables, and development documentation.

Content Index

The content index is a binary snapshot of your content metadata—used to avoid parsing Markdown files on every request.

'content_index' => [
    'mode'           => 'auto',   // When to rebuild: auto, never, always
    'backend'        => 'array',  // Storage: array or sqlite
    'use_igbinary'   => true,     // Faster serialization if available
    'prerender_html' => false,    // Pre-render Markdown during rebuild
],
Option Type Default Description
mode string 'auto' auto = rebuild when files change, never = CLI only (production), always = every request (debug only).
backend string 'array' array = binary PHP arrays (default), sqlite = SQLite database (for 10k+ items).
use_igbinary bool true Use igbinary extension for faster serialization if installed.
prerender_html bool false Pre-render Markdown → HTML during rebuild to speed up uncached requests.

See: Performance - Content Indexing for detailed explanations of modes, backends, tiered caching, and benchmarks.

Webpage Cache

The webpage cache stores fully-rendered HTML for near-instant serving.

'webpage_cache' => [
    'enabled' => true,
    'ttl'     => null,       // Seconds, or null = until rebuild
    'exclude' => ['/api/*'], // URL patterns to never cache
],
Option Type Default Description
enabled bool false Enable HTML webpage caching. Recommended true for production.
ttl int|null null Cache lifetime in seconds. null = cached until next rebuild.
exclude array [] URL patterns to never cache. Supports glob wildcards (*).

See: Performance - Webpage Caching for how it works, fast-path optimization, and cache management.

Routing

'routing' => [
    'trailing_slash' => false,
],
Option Type Default Description
trailing_slash bool false URL style: false = /about, true = /about/. Mismatches trigger 301 redirects.

See: Routing for URL styles, custom routes, and taxonomy URLs.

Content Parsing

Controls how Ava CMS processes your Markdown content files.

'content' => [
    'frontmatter' => [
        'format' => 'yaml',
    ],
    'markdown' => [
        'allow_html'       => true,
        'heading_ids'      => true,
        'disallowed_tags'  => ['script', 'noscript'],
    ],
    'id' => [
        'type' => 'ulid',
    ],
],
Option Type Default Description
frontmatter.format string 'yaml' Frontmatter parser format. Currently only YAML is supported.
markdown.allow_html bool true Allow raw HTML tags in Markdown content.
markdown.heading_ids bool true Add id attributes to headings for deep linking.
markdown.disallowed_tags array [] HTML tags to strip even when allow_html is true.
id.type string 'ulid' ID format for new content: 'ulid' (recommended) or 'uuid7'.

See: Writing Content for frontmatter fields and Markdown syntax.

Security

'security' => [
    'shortcodes' => [
        'allow_php_snippets' => true,
    ],
    'preview_token' => null,
],
Option Type Default Description
shortcodes.allow_php_snippets bool true Enable the shortcode for including PHP files from app/snippets/.
preview_token string|null null Secret token for previewing draft content without logging in.

Preview token usage: Access drafts via https://example.com/path?preview=1&token=your-token

See: Shortcodes - Snippets and Routing - Preview Mode.

Admin Dashboard

The admin dashboard provides a web-based interface for managing your site.

'admin' => [
    'enabled' => false,
    'path'    => '/admin',
    'theme'   => 'cyan',

    'media' => [
        'enabled'          => true,
        'path'             => 'public/media',
        'organize_by_date' => true,
        'max_file_size'    => 10 * 1024 * 1024,   // 10 MB
        'allowed_types'    => [
            'image/jpeg', 'image/png', 'image/gif',
            'image/webp', 'image/svg+xml', 'image/avif',
        ],
    ],
],
Option Type Default Description
enabled bool false Enable the admin dashboard.
path string '/admin' URL path for the admin area. Change to obscure admin location.
theme string 'cyan' Color theme: cyan, pink, purple, green, blue, or amber.
media.enabled bool true Enable the media upload feature.
media.path string 'public/media' Upload directory (relative to project root).
media.organize_by_date bool true Create /year/month/ subfolders for uploads.
media.max_file_size int 10485760 Maximum file size in bytes (10 MB default).
media.allowed_types array See code Array of allowed MIME types for uploads.
Important: Create admin users with ./ava user:add before enabling the admin dashboard.

See: Admin Dashboard for features, security, and user management.

Debug Mode

Control error visibility and logging for development and troubleshooting.

'debug' => [
    'enabled'        => false,
    'display_errors' => false,
    'log_errors'     => true,
    'level'          => 'errors',
],
Option Type Default Description
enabled bool false Master switch for debug features.
display_errors bool false Show PHP errors in browser output. Never enable in production!
log_errors bool true Write errors to storage/logs/error.log.
level string 'errors' Error reporting: all (dev), errors (prod), or none.
Security Warning: Never enable display_errors in production—it can expose sensitive information.

Logs

Control log file size and automatic rotation.

'logs' => [
    'max_size'  => 10 * 1024 * 1024,   // 10 MB
    'max_files' => 3,
],
Option Type Default Description
max_size int 10485760 Maximum log file size in bytes before rotation (10 MB).
max_files int 3 Number of rotated log files to keep.

See: CLI - Logs for log viewing and management commands.

CLI Appearance

'cli' => [
    'theme' => 'cyan',
],
Theme Description
cyan Cool cyan/aqua (default)
pink, purple, green, blue, amber Alternative colors
disabled No colors (for CI/CD or non-ANSI terminals)

Plugins

'plugins' => [
    'sitemap',
    'feed',
    'redirects',
],

Array of plugin folder names to activate. Plugins load in the order listed.

See: Bundled Plugins for sitemap, RSS feed, and redirects configuration.

Custom Settings

Add your own site-specific configuration. Access values in templates with $ava->config():

// In ava.php
'analytics' => [
    'tracking_id' => 'G-XXXXXXXXXX',
    'enabled'     => true,
],
// In templates
<?php if ($ava->config('analytics.enabled')): ?>
    <!-- Analytics code for <?= $ava->config('analytics.tracking_id') ?> -->
<?php endif; ?>

Content Types: content_types.php

Define what kinds of content your site has. Each content type specifies where files live, how URLs are generated, and which templates to use.

<?php

return [
    'page' => [
        'label'       => 'Pages',
        'content_dir' => 'pages',
        'url' => [
            'type' => 'hierarchical',
            'base' => '/',
        ],
        'templates' => [
            'single' => 'page.php',
        ],
        'taxonomies' => [],
        'fields'     => [],
        'sorting'    => 'manual',
    ],

    'post' => [
        'label'       => 'Posts',
        'content_dir' => 'posts',
        'url' => [
            'type'    => 'pattern',
            'pattern' => '/blog/{slug}',
            'archive' => '/blog',
        ],
        'templates' => [
            'single'  => 'post.php',
            'archive' => 'archive.php',
        ],
        'taxonomies' => ['category', 'tag'],
        'sorting'    => 'date_desc',
    ],
];

Content Type Options

Option Type Required Description
label string Yes Human-readable name shown in admin UI.
content_dir string Yes Folder inside content/ where files for this type live.
url array Yes URL generation settings. See Routing - URL Styles.
templates array Yes Template file mappings (single, archive).
taxonomies array No Which taxonomies apply to this type. Default: []
fields array No Custom field definitions for validation and admin UI. See Fields.
sorting string No Default sort: date_desc, date_asc, title, or manual.
cache_fields array No Extra frontmatter fields to include in archive cache for fast access.
search array No Search configuration (enabled, fields, weights).

Example with Custom Fields

Here's a more complete example showing custom fields for a blog post type:

'post' => [
    'label'       => 'Blog Posts',
    'content_dir' => 'posts',
    'url' => [
        'type'    => 'pattern',
        'pattern' => '/blog/{slug}',
        'archive' => '/blog',
    ],
    'templates' => [
        'single'  => 'post.php',
        'archive' => 'archive.php',
    ],
    'taxonomies' => ['category', 'tag'],
    'sorting'    => 'date_desc',
    
    // Custom fields for validation and admin UI
    'fields' => [
        'author' => [
            'type'     => 'text',
            'label'    => 'Author Name',
            'required' => true,
        ],
        'featured_image' => [
            'type'  => 'text',
            'label' => 'Featured Image URL',
        ],
        'reading_time' => [
            'type'    => 'number',
            'label'   => 'Reading Time (minutes)',
            'min'     => 1,
            'max'     => 60,
            'default' => 5,
        ],
        'featured' => [
            'type'    => 'boolean',
            'label'   => 'Featured Post',
            'default' => false,
        ],
    ],
    
    // Include these fields in archive cache for fast listing access
    'cache_fields' => ['author', 'featured_image', 'reading_time', 'featured'],
],

See: Fields for all available field types (text, number, boolean, select, date, etc.) and validation options.

Taxonomies: taxonomies.php

Taxonomies organize content into groups (categories, tags, authors, etc.).

<?php

return [
    'category' => [
        'label'        => 'Categories',
        'hierarchical' => true,
        'public'       => true,

        'rewrite' => [
            'base'      => '/category',
            'separator' => '/',
        ],

        'behaviour' => [
            'allow_unknown_terms' => true,
            'hierarchy_rollup'    => true,
        ],

        'ui' => [
            'show_counts' => true,
            'sort_terms'  => 'name_asc',
        ],
    ],

    'tag' => [
        'label'        => 'Tags',
        'hierarchical' => false,
        'public'       => true,

        'rewrite' => [
            'base' => '/tag',
        ],

        'behaviour' => [
            'allow_unknown_terms' => true,
        ],

        'ui' => [
            'show_counts' => true,
            'sort_terms'  => 'count_desc',
        ],
    ],
];

Taxonomy Options

Option Type Default Description
label string Required Human-readable name for the taxonomy.
hierarchical bool false Support parent/child term relationships.
public bool true Create public archive pages for terms.
rewrite.base string '/{taxonomy}' URL prefix for term archives.
rewrite.separator string '/' Separator for hierarchical term paths.
behaviour.allow_unknown_terms bool true Auto-create terms when used in content.
behaviour.hierarchy_rollup bool true Include child terms when filtering by parent.
ui.show_counts bool true Display content count next to terms.
ui.sort_terms string 'name_asc' Default sort: name_asc, name_desc, count_asc, count_desc.

Using taxonomies in content:

---
title: My PHP Tutorial
category: Tutorials
tag:
  - php
  - beginner
---

See: Writing Content - Taxonomy Fields for usage examples and Routing - Taxonomy Routes for URL generation.

Environment-Specific Config

Use PHP logic to override settings per environment:

// app/config/ava.php

$config = [
    'site' => [
        'name'     => 'My Site',
        'base_url' => 'https://example.com',
    ],
    'content_index' => ['mode' => 'never'],
    'debug' => ['enabled' => false],
];

// Development overrides
if (getenv('APP_ENV') === 'development') {
    $config['site']['base_url'] = 'http://localhost:8000';
    $config['content_index']['mode'] = 'auto';
    $config['admin']['enabled'] = true;
    $config['debug'] = [
        'enabled'        => true,
        'display_errors' => true,
        'level'          => 'all',
    ];
}

return $config;

Set the environment variable in your server config:

export APP_ENV=development

Ava CMS is provided as free, open-source software without warranty. You are responsible for reviewing, testing, and securing any deployment.