Database-driven Themes

Database-driven Themes

Store theme content changes in the database instead of the file system.

In some cases you may not have access to write to the filesystem to make changes to the theme. Database-driven themes allows you to store all changes to CMS templates in the database. This covers pages, layouts, partials, content files, and language files.

To enable this feature for a single theme, navigate to Settings → Frontend Theme, select Edit Properties and check the checkbox called Save Changes in Database.

Alternatively you can enable this feature globally for all themes with the config item cms.database_templates or using the environment variable.

CMS_DB_TEMPLATES=true

# How Database-driven Templates Behave

When the database layer is active for a theme, edits made in the CMS editor are written to the database instead of the filesystem. Reads check the database first and fall back to the filesystem, so files that have never been edited continue to be served directly from the theme directory.

Deleting a template via the editor writes a tombstone row to the database. The tombstone hides the filesystem copy from listings and reads, so the file appears deleted across every instance even though the on-disk copy is still present. This is the same mechanism used for templates and language files.

# Importing from Database to Filesystem

The theme:copy command can be used to copy the database version of the theme to the filesystem. Simply call the command with the --import-db option. This imports templates, language files, assets, and blueprints in a single pass and applies tombstones by deleting the corresponding on-disk files.

php artisan theme:copy demo --import-db

To delete all the imported database rows at the same time, use the --purge-db option.

php artisan theme:copy demo --import-db --purge-db

# Database-driven Assets

By default, asset files like images and stylesheets do not save in the database and cannot be modified without access to the filesystem. When your application runs across multiple instances with a disposable local filesystem, asset edits made in the CMS editor (theme CSS, JavaScript, images, fonts) need somewhere shared to live. Database-driven assets publishes these files to a shared storage disk so they are immediately visible across every instance.

This feature is intended for multi-instance deployments where the local filesystem cannot be relied upon. For single-instance setups the default filesystem behavior is simpler and recommended.

# How it Works

Theme assets are published to a dedicated assets filesystem disk. In production this disk is typically backed by Amazon S3 or another object storage service, fronted by a CDN. The ASSET_URL environment variable points at the same origin, so URLs generated by asset() resolve to the published location.

When an asset is edited via the backend, the new bytes are written directly to the assets disk and a database record is created tracking the change. The edit is live across all instances immediately.

# Setup

Three pieces need to be in place.

1. Configure the assets filesystem disk

Add an assets disk to your config/filesystems.php. For an S3-backed setup:

'assets' => [
    'driver' => 's3',
    'key' => env('AWS_ACCESS_KEY_ID'),
    'secret' => env('AWS_SECRET_ACCESS_KEY'),
    'region' => env('AWS_DEFAULT_REGION'),
    'bucket' => env('AWS_ASSETS_BUCKET'),
    'url' => env('ASSET_URL'),
    'visibility' => 'public',
],

For local development you can point the disk at a public path on the local filesystem instead.

2. Set the ASSET_URL environment variable

ASSET_URL should point at the same origin as the assets disk. This ensures asset() calls resolve to the published location.

ASSET_URL=https://cdn.example.com

3. Enable the feature

Set the cms.database_assets config item, or use the environment variable.

CMS_DB_ASSETS=true

The feature is disabled by default so a fresh checkout of the project does not require shared storage credentials to run.

# Publishing Assets on Deployment

The october:mirror command publishes all theme, module, plugin, and app assets to a filesystem disk when called with the --disk option. Run this as part of your deployment pipeline so the published assets reflect the latest version of the code.

php artisan october:mirror --disk=assets

The command is additive, meaning it uploads or overwrites files but never deletes. Orphaned files left by code changes can be cleaned up with object storage lifecycle rules at the bucket level if desired. Unchanged files are skipped using a size comparison, use the --checksum option to compare content hashes instead, the --force option to upload everything, or the --dry-run option to preview the upload list.

# Cache Invalidation

When an asset changes via the CMS editor, the cms.asset.invalidate event fires with the theme and the changed disk keys. Listen to this event to purge cached copies at your CDN, keeping the core CDN-agnostic.

Event::listen('cms.asset.invalidate', function ($theme, $diskPaths) {
    MyCdnProvider::invalidate($diskPaths);
});