CMS / content platform12 min readNot archived on GitHub

Bolt CMS: content model, scope and lifecycle caveats

A guide to Bolt, a content platform with ContentTypes, Twig theming and extensions, with lifecycle and compatibility marked unknown.

PHP compatibility and project lifecycle

Unknown. The supplied source does not state supported PHP versions, Symfony version, current Bolt version or persistent worker support. Check System Requirements in the official docs. The example script is plain PHP written for PHP 8.4 and is not Bolt code.

Official sources checked 2026-10-22. Browser lessons on this site run PHP 8.5.

It relies on one official source: the introduction page of the Bolt documentation. That page is a table of contents, so many details below are marked unknown instead of guessed.

What Bolt is

Bolt is a CMS, meaning a content platform. The documentation introduction lists these areas: Getting Started (about Bolt, system requirements, installation and upgrading), ContentTypes (records, fields, taxonomies and relationships), Templating and Theming (Twig, fetching content, paging, search), Routing, and Extending Bolt (writing extensions and submitting them to a Marketplace). It also links a community manifesto and a section of HOWTOs.

The assignment describes Bolt as Symfony-based and asks you to verify its lifecycle. The supplied page does not state the Symfony relationship, so treat that as an assignment note to confirm in the About and System Requirements pages. Lifecycle is unknown: the packet gives no release dates, maintenance statement or support policy. Check the project's own channels before choosing it for new work.

What Bolt is not

Bolt is a CMS product. It is not PHP core, and it is not a standalone PHP runtime or interpreter. It is not an async library or a framework adapter. It is also not Drupal. Drupal is a separate CMS built on PHP, so Drupal documentation does not apply to Bolt.

Framework components are libraries a developer assembles, while a CMS product ships editing workflows, content storage concepts and theming conventions. If Bolt uses Symfony components, that is an implementation detail to confirm. Learning Symfony alone will not teach you Bolt's ContentTypes or extension system.

The same care applies to runtime names. Swoole and Open Swoole are different projects, so never assume documentation for one covers the other. Neither is part of Bolt, and the supplied source does not mention either.

Architecture and content model

The source suggests this layering:

  • ContentTypes define kinds of content. They include records, fields, taxonomies and relationships.
  • Templates are written with Twig. They fetch content, page through it and support search.
  • Routing configures routes that create custom links and URLs.
  • Extensions add behavior and can be submitted to a Marketplace.

The packet does not describe storage engines, configuration file formats, the admin interface, user roles, caching or an API. All of that is unknown here. Read the ContentTypes and Routing pages before designing anything.

Execution model and persistent workers

A classic PHP request lifetime starts a fresh process or worker context for each request. Variables, static properties and object graphs disappear when the request ends. A persistent worker boots the application once and handles many requests in the same process.

Persistent workers can leak state. Static properties, singletons, service containers, caches held in memory, open database connections, the current user, locale, and request-scoped data can survive into the next request. The usual symptoms are one visitor seeing another visitor's data and memory growth. The mitigation is to reset request-scoped services between requests, avoid mutable statics, close or validate connections, and restart workers on a schedule.

The supplied source does not say whether Bolt supports persistent workers. Assume the classic request lifetime unless the official documentation says otherwise. Do not run Bolt or its extensions in a worker mode without confirming support. Extensions deserve special scrutiny because they may hold state.

Practical use cases

Based only on the documented feature areas, Bolt fits sites where editors manage structured content: articles, pages, listings and taxonomies, rendered through Twig themes with custom URLs. It may suit teams that want to define content structures and templates themselves. Whether it fits a given project, such as multilingual sites, large editorial teams, headless delivery or e-commerce, is unknown from this source.

Installation approach

The documentation lists an Installation section with various methods to install Bolt quickly, plus a System Requirements page. The packet contains neither the commands nor the supported PHP versions, so this guide does not supply them. Follow this order:

  1. Read System Requirements and confirm the supported PHP version against the PHP 8.4 learning track. PHP 8.5 is planned for the track, and compatibility with either is unknown.
  2. Pick one installation method from the Installation page and copy its commands from the official docs.
  3. Install on a development machine first. If you expose a development server, bind it to 127.0.0.1.
  4. Create a ContentType, add a record, and render it with a Twig template.
  5. Only then evaluate extensions from the Marketplace.

No Docker Compose file is given because the source provides no image names or tags, and inventing them would be unsafe.

Strengths

  • The documentation is organized around a clear content workflow: model, template, route, extend.
  • Twig theming is a widely known approach.
  • A documented extension mechanism and Marketplace exist.
  • Help channels are listed: a forum, Slack and GitHub.

Limitations and unknowns

  • Lifecycle, current version, license, price and support status are unknown from the packet.
  • PHP version compatibility is unknown.
  • The Symfony relationship is only an assignment note here.
  • Persistent worker support is unknown.
  • Extension compatibility and maintenance quality are unknown.
  • This guide cannot compare performance and makes no speed claims.

Deployment

The packet does not describe deployment. In general, put a web server in front of PHP, never expose FastCGI publicly, keep secrets out of the repository, and test upgrades on a copy of the content first. Follow the Bolt Installation and Upgrading pages for the actual steps. Before choosing Bolt for production, verify that the project is still maintained.

The example

The included example is not Bolt code. It is a small plain PHP 8.4 command-line script that checks a planning file you write before configuring real ContentTypes. It helps you think about slugs, fields and titles. It has no dependencies, no network use and no browser component. It needs a local PHP CLI.

Links

Use the official Bolt documentation as the final authority.

Practical examples

These examples have not been run in a live environment yet. Commands and versions follow the official documentation linked on this page; check them before relying on them, and report a problem if one does not work.

Plain PHP 8.4 content model planning check (not Bolt code)

A dependency-free CLI script that reads a self-made planning file describing content types and fields, then reports structural problems. The file format is invented for this exercise and is not Bolt's configuration format. Use it to prepare before following the official Bolt installation and ContentTypes documentation.

content-model.json

{
  "contentTypes": [
    {
      "slug": "articles",
      "fields": [
        { "name": "title", "type": "text" },
        { "name": "body", "type": "textarea" }
      ]
    },
    {
      "slug": "pages",
      "fields": [
        { "name": "title", "type": "text" },
        { "name": "summary", "type": "text" }
      ]
    }
  ]
}

check-content-model.php

<?php

declare(strict_types=1);

$path = __DIR__ . '/content-model.json';
$raw = file_get_contents($path);

if ($raw === false) {
    fwrite(STDERR, "Cannot read content-model.json\n");
    exit(2);
}

try {
    $data = json_decode($raw, true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
    fwrite(STDERR, 'Invalid JSON: ' . $e->getMessage() . "\n");
    exit(2);
}

$problems = [];
$types = is_array($data) ? ($data['contentTypes'] ?? []) : [];

if (!is_array($types) || $types === []) {
    $problems[] = 'No content types defined.';
    $types = [];
}

$seen = [];

foreach ($types as $index => $type) {
    $slug = is_array($type) ? ($type['slug'] ?? null) : null;

    if (!is_string($slug) || preg_match('/^[a-z0-9]+(?:-[a-z0-9]+)*$/', $slug) !== 1) {
        $problems[] = "Content type #{$index} has a missing or invalid slug.";
        continue;
    }

    if (isset($seen[$slug])) {
        $problems[] = "Duplicate content type slug: {$slug}";
        continue;
    }
    $seen[$slug] = true;

    $fields = $type['fields'] ?? [];
    if (!is_array($fields) || $fields === []) {
        $problems[] = "{$slug}: no fields defined.";
        continue;
    }

    $valid = true;
    foreach ($fields as $field) {
        if (!is_array($field) || !is_string($field['name'] ?? null) || !is_string($field['type'] ?? null)) {
            $problems[] = "{$slug}: every field needs a string name and type.";
            $valid = false;
            break;
        }
    }

    if ($valid && !array_any($fields, fn (array $f): bool => $f['name'] === 'title')) {
        $problems[] = "{$slug}: no field named title.";
        $valid = false;
    }

    if ($valid) {
        echo 'OK: ' . $slug . ' (' . count($fields) . " fields)\n";
    }
}

if ($problems !== []) {
    foreach ($problems as $problem) {
        fwrite(STDERR, 'PROBLEM: ' . $problem . "\n");
    }
    exit(1);
}

echo "Content model looks consistent.\n";

Install and run

php --version
php check-content-model.php

Expected behavior

With the supplied JSON, the script should print one OK line each for articles and pages (2 fields each), then 'Content model looks consistent.' and exit with code 0. If you remove the title field or duplicate a slug, it should print PROBLEM lines to standard error and exit with code 1.

Requires a PHP 8.4 CLI because it uses array_any. It does not install, configure or call Bolt, and its JSON format is not Bolt's. It only helps you plan. It is not a browser exercise.