Cockpit – a headless, API-first CMS

Cockpit is a headless Content Management System (CMS), developed by Artur Heinze. The core is written in PHP and it has a permissive license (MIT). “Headless” means: backend for data and content, but no inbuilt frontend for websites.

This article focuses mostly on Cockpit v1. Soon after the rewrite to v2, I left the project.

Toggle table of contents

My role

For multiple years, I helped as a volunteer to move the project forward. I fixed bugs, helped sorting out missing or outdated documentation, reported multiple security issues and wrote many addons.

After a few months, I became moderator in their community/support forum. Moderating was a low effort. The user base is small and – as I observed in many development focused forums – the troll count was immensely low. Mostly I helped explaining (hidden) core concepts or solving weird edge cases. To be honest: helping strangers was one motivation, but solving random code puzzles was the real fun. The forum and issue section became my favorite place for procrastination.

It was an interesting and intense time of my life.

Some numbers

And I’m always astonished, when looking at my forum statistics:

  • 636 days visited
  • 4 days read time
  • 916 topics viewed
  • 3.1k posts read
  • 28 likes given
  • 215 likes received
  • 36 topics created
  • 467 posts created
  • 66 solutions

How Cockpit works

As mentioned, it’s headless. Cockpit focuses on data modeling and providing interfaces to access that data:

  1. Admin panel: graphical user interface (GUI) for creating collections, modeling and maintaining data
  2. REST API: access to data sets from outside, secured with API keys
  3. CLI: many tasks can be done and automated via command line
  4. as PHP library: access to all modules, functions and data with custom-made applications
Graph showing Cockpit's four API endpoints (CLI, REST, GUI, PHP library) around it's core with bidirectional arrows. Library points to Multiplane, bidirectional. REST points to Android app and Web App, bidirectional. Visitors point to Multiplane and Web App. User groups to GUI, Web App and Android App. Admin to CLI and GUI. All human pointers are one-directional.

The admin panel (backend) can be modified with addons. A frontend can be written in any language, accessing data via REST API. When frontend and backend live on the same server, they can communicate directly via PHP API or even via CLI.

At its’ core, Cockpit speaks JSON – or more specifically: MongoDB. Everything is document-oriented. Coming from SQL, I had to readapt:

  1. No relations: e. g. renaming a category means changing a string in all documents. This can be automated using the event system to check for changed categories after saving. But without shifting the mental model to a non-relational database, these things were confusing.
  2. Syntax and logic: applying filters ($and, $or) instead of trying to translate WHERE clauses.

And – although Cockpit speaks MongoDB – it comes with an abstraction layer (MongoLite) to use SQLite as database. And I like SQLite: no server, no passwords, no sql export before and after changing things in a local development setup – just copy and paste.

Why I chose it

In May 2018, after moving from WordPress to Github Pages (jekyll) with prose.io as UI, I searched again for alternatives. Until then, the term “headless” never crossed my mind. After knowing, what I was looking for, the concept convinced immediately.

Self-hosting and a permissive license were mandatory and I was most skilled in PHP – which left only two options: Cockpit and Directus[1]. Both had Gravatar implemented. I asked for an option to disable it, to respect users’ privacy. A few hours later, Artur committed an update and disabled it completely. Months later, I got an answer from Directus. They never thought about Gravatar being a privacy problem and considered changing it.

Obviously, my decision was long done.

Why I left

From the beginning, I was more interested in the PHP (and the CLI) API, than in the REST API. On top of the headless Cockpit CMS v1, I wrote my own frontend (head) Multiplane. So my usage was unusual, not like intended. But I always cared about the headless paradigm when writing addons.

Over the years, I had a deep understanding of all internals. My ecosystem relied on Cockpit’s configurability and hackability. Then Cockpit grew up. Version 2 was released. It looked nice and I liked many changes. Most of my addons could have been rewritten for compatibility, but Multiplane became incompatible. I really tried to find workarounds, but it was unfixable. My vision of Cockpit didn’t match Artur’s anymore.

For a while, I kept a fork of Cockpit v1 alive – until I had to admit, that years of my work became worthless. Sure, I learnt a lot. And I don’t blame Artur for moving forward and building a stable business model. But it still hurts.

On top of that:

  • V2 re-introduced a security issue and multiple accessibility issues, I fixed in v1 already – very annoying.
  • Some core addons became proprietary, which was fine in general. But I couldn’t skim git diffs anymore to understand the motivation for some random looking core changes. Also annoying.
  • Multilingualism was poorly implemented.
  • Accessibility was clearly an after-thought.

In the forum thread about my reasoning for leaving, I go into more (technical) details.

Addons

Some of my addons were used in production for years, some were experimental and unfinished.

Babel
Manage translations of addons and modules
addon for Cockpit CMS v1 and v2
BetterMarkdown
Cache, tasks lists and table of contents for markdown conversion
addon for Cockpit CMS v1
BlockEditor
Visual block editor
draft/experimental
addon for Cockpit CMS v1
BootManager
addon dependency management, module loading order, conditional loading
draft/experimental
addon for Cockpit CMS v1
DashboardGrid
Custom dashboard with grid
addon for Cockpit CMS v1
Feed
RSS Feeds for collections
draft/experimental
addon for Cockpit CMS v1
FormValidation
Form validator and form builder
addon for Cockpit CMS v1
ImageResize
Resizes uploaded images automatically to predefined sizes
addon for Cockpit CMS v1
Migrate
Migrate and convert models, data, accounts etc. from Cockpit CMS v1 to v2.
draft/experimental, never published as official addon
addon for Cockpit CMS v1 and v2
ModuleLink
Field with linked data from modules
draft/experimental
addon for Cockpit CMS v1
MoreOptions
Utility addon with more options (collection grouping, color picker)
draft/experimental, mostly superseded by rljUtils addon
addon for Cockpit CMS v1
Multiplane addon
Frontend logic (head) for the headless Cockpit CMS
addon for Cockpit CMS v1
MultiplaneDocsMods
Modifications for Multiplane docs
simple 2-way bind between markdown files and SQLite database
addon for Cockpit CMS v1
phpLiteAdmin
phpLiteAdmin interface for debugging and data inspection
addon for Cockpit CMS v1
rljUtils
Utility addon with security hardening, cosmetics and helpers
addon for Cockpit CMS v1
SelectRequestOptions
Select field with options based on custom requests
addon for Cockpit CMS v1
SheetExport
Spread sheet export (csv, odt, xls, xlsx)
draft/experimental
quickly modified version of the sheet export from my Tables addon
addon for Cockpit CMS v1
ShowInMenu
re-enable the feature to display collections etc. in the system menu
superseded by rljUtils addon
addon for Cockpit CMS v1
SimpleImageFixBlackBackgrounds
provides a modified SimpleImage library to prevent black backgrounds in transparent images on some systems with a non-bundled PHP-GD version (really nasty bug)
addon for Cockpit CMS v1
Tables
Manage SQL tables with 1:m and m:n relations
addon for Cockpit CMS v1
UniqueSlugs
generates unique url paths (called “slugs”) from page titles
addon for Cockpit CMS v1
VideoLinkField
extract, download and store thumbnails and meta data from videos on YouTube and Vimeo
addon for Cockpit CMS v1
WhiteLabel
Custom logo and custom colors
addon for Cockpit CMS v1

Other stuff

Cockpit v1 fork
Fork of Cockpit CMS v1 (next branch)
stable release for usage with composer and PHP 8.1
contains some improvements from v2
Cockpit scripts repository
A collection of code snippets and notes to modify Cockpit CMS v1 and v2
WPMultiplane
Cockpit CMS v1 and Multiplane implementation as a WordPress plugin
draft/experimental
still not sure, if brilliant or utterly stupid

Footnotes

  1. This was before their complete rewrite to node.js. ↩︎