Introducing CockpitCMS – a CMS for Developers

By Taylor Ren

In this tutorial, we will see how to use Cockpit CMS to set up a CMS backend and to use the API interface provided by Cockpit to build a customized functional frontend.

Not quite like other “heavy weight”, or “fully fledged” CMSes, Cockpit is lightweight and “bare”. It only provides a backend to manage meta-data and data entries, whilst the frontend is all in the developer’s hands.


A copy of Cockpit CMS can be downloaded here in zip form. After downloading, just unzip the archive to a directory on your web server that is accessible. In my case, it is mapped to: http://vagrant/cockpit.

Next, visit the installation page: http://vagrant/cockpit/install to start the installation process.

NOTE: Cockpit uses SQLite as its database engine by default. If you have not installed SQLite yet, please do so before the installation.

NOTE: Cockpit also requires that its /storage/data directory be writable. Please change the mode of that directory accordingly.

The installation is just one click. When the installation is complete, you will be greeted with this page:

Now we can log in with admin/admin and the backend administration dashboard page will be shown:

Well, we don’t have anything set up yet. Before we create our own content, let’s learn about a few key modules in Cockpit.

Modules in Cockpit

The two most important modules in Cockpit are: Collections and Galleries.

We can treat “Collections” as a bunch of tables. All collections are defined in Cockpit with various fields of virtually all kinds of types. Collections are populated with “Entries“, which is similar to a record in a table.

Galleries are “photo albums”. A user creates a photo album which can contain pictures that can be used later, in the backend as well.

Cockpit also has other modules: forms, regions (a kind of reusable snippets to be inserted in the frontend pages), media manager (to manage all the media files in the site). The detailed documentation for these modules (include collections and galleries) can be found on the official site.

Create a Trip collection

To start, I will create a collection to capture my trips made. We need to provide a name for the collection (Trips) and define what its entries will contain:

It is a simple structure and consists of the followings fields:

  • name: a Text field.
  • date: a Date field.
  • location: a Text field.
  • diary: a Markdown field to capture some highlights of the trip.
  • pic: a Text field to link to a gallery of pictures associated with the trip.

The above screenshot shows how a user can visually define the structure and other options (like “What to show in an entry page and show by what order on which field”). Quite intuitive.

NOTE: Cockpit also creates several other fields automatically to store information like ID, creation date, modification date, etc. We can also use these “meta” fields in our code.

We have created a field diary to contain Markdown texts. Later, we will see how to display this in a web page.

You may also notice that though Cockpit supports a field type “Gallery“, we are still using a “text” field. This is because Cockpit can’t yet link an existing gallery in a collection entry. Later, we will see how to get around this.

We can create more collections, galleries, and drop some entries in there.

Now, let’s move to the “frontend” part.

The frontend

NOTE: We’ll be using the Silex framework with Twig to build our front end, but you can pick your favorite – the logic is almost the same in any case, as long as you do the require we mention below.

Cockpit comes with a neat backend but it lacks a frontend to present the data. It is the programmer’s job to make this happen. To facilitate this, Cockpit exposes some fundamental APIs which are categorized by different modules and various Helpers. The official documentation contains a list of these functions. In this demo, we will only focus on some of them.

First, let’s see how to display a Welcome page with all the summary information.

NOTE: To use these APIs in our PHP code, please require_once __DIR__ . '/../cockpit/bootstrap.php';

The code is listed below:

$app->get('/', function () use ($app) {
    $collections = cockpit('collections:collections', []);
    $galleries = cockpit('galleries:galleries', []);

    return $app['twig']->render('index.html.twig', ['collections' => $collections, 'galleries' => $galleries]);

We get all the collections and galleries through the Cockpit API interface. It is very straightforward.

The collections section can be displayed using the below Twig code:

	<p>There are total <strong>{{collections|length}}</strong> collection(s) in the CMS:</p>
    {% for col in collections|keys %}
        	<a href="{{ url('collection', {col: col})}}">{{col}}</a>
    {% endfor %}

With help from Symfony’s new VarDumper, it is very convenient to inspect the inner structure of a variable so that we can easily locate the correct members to be used.

NOTE: VarDumper can be used in Silex too, as well as in any other framework or non-framework app. For a detailed introduction on this new tool from Symfony, please take a look at Bruno’s article on VarDumper. To use this in Silex, you need use Symfony\VarDumper; and add one line in your composer.json file:

"symfony/var-dumper": "3.0.*@dev"

We can now click an entry link and it will bring us to the entry page:

Two points need to be highlighted here.

The notes (diary field) of the entry is a Markdown field and my input in the backend is:

###Japan Trip

**Japan trip** is done in Aug 2013. GR, PR and TR went there for a pleasant journey.

With Markdown syntax, I can skip the configuration of an online editor and use “plain” text to achieve a certain level of formatting effect which, in most cases, is sufficient.

To display Markdown in our final HTML page, we need to install the Markdown bundle by adding one line in the composer.json file:

"michelf/php-markdown": "~1.4"

and reference it in our index.php file:

use Michelf\MarkdownExtra;

NOTE: I am using Markdown Extra syntax in this demo. Details on Markdown (and Markdown Extra) syntax can be found here.

The rendering of a Markdown string (text) is simple:

foreach ($entries as &$entry) {
        $text = $entry['diary'];
        $html = MarkdownExtra::defaultTransform($text);

        $entry['diary'] = $html;

The output of Markdown rendering is satisfying.

Next, we may want to display the picture galleries associated with that entry. As mentioned earlier, there is no easy way (or in my opinion, an intuitive way) to do so. In this demo, the pic field defined above acts as a “link” to the gallery containing the pictures. There are a few lines of code to be done to display the images.

$app->get('/gallery/{gal}', function ($gal) use ($app) {

    $images = cockpit("galleries")->gallery($gal);
    foreach ($images as &$img) {
        $image = $img['path'];
        $imgurl = cockpit('mediamanager:thumbnail', $image, 200, 200);
        $url=str_replace('site:', 'http://'.$app['request']->getHost().'/', $path);

    return $app['twig']->render('gallery.html.twig', ['images'=>$images, 'gal'=>$gal]);

The first step is to get all images for a particular gallery by calling the Cockpit API: $images = cockpit("galleries")->gallery($gal);.

Next, we need to get two things out of each image: a thumbnail and the real path of that image.

To get a thumbnail, Cockpit provides an API: cockpit('mediamanager:thumbnail', $image, 200, 200);, where 200 specifies the width/height of the thumbnail. There are a few other options available to create a thumbnail, like to control the quality and cropping mode. Please consult the documentation for a detailed usage explanation.

One thing is missing, though, from this API, which is an automatic rotation of pictures so that a picutre taken in portrait orientation can be properly recognized and displayed. Now the system displays all pictures in landscape mode, regardless of the orientation of the original picture.

Cockpit does not store the real path of the picture. This may make sense in my case, as my pictures are actually loaded in the backend using vagrant/cockpit and the frontend is vagrant/silex.

If we check the VarDumper dump of $images, the path is in fact something like: "path" => "site:cockpit/assets/images/IMG_3427.JPG". Hence, we use a str_replace to generate a real Web URI for that image: "url" => "http://vagrant/cockpit/assets/images/IMG_3548.JPG". Of course, to make this work, we must make sure the image is served properly via that URI.

And that’s it! With not many lines of coding, we have a functional frontend powered by Cockpit CMS.


Cockpit is lightweight, easy to install and to set up. Its backend is tidy and intuitive. Creating collections and galleries is straightforward and I personally like the various field types it offers. Populating an entry in a collection and loading pictures into a gallery isn’t hard either.

The lack of a frontend, in my opinion, is not a bad thing. Various collection structures will definitely require different presentations and layouts. For example, a book collection may use a tabular style while a trip collection may include a gallery section showing some pictures. A default dumping of all fields of an entry will simply be ugly and unfitting. Thus, I would say Cockpit is quite smart in not providing one. However, this will require the user to code a different layout for each collection structure. It could be troublesome and time consuming in some cases and it requires a certain level of programming skills, which is why CockpitCMS labels itself as the “developer’s CMS”.

Its API is of great value when we do frontend development, but it is still not complete. For example, the lack of providing a usable real path to a picture and the lack of an option to rotate a picture based on its orientation are just a few I’ve noticed in my short time with the CMS. I would suggest the author of the CMS to make some further improvements in this aspect.

Most critical of all, it does not provide APIs to CRUD an entry. This is probably because the collection structure is different from one to another and it is practically impossible to provide a universal CRUD API. But this also stops us from using PHP code to quickly and easily manage the data. All we are left with is the backend, which may not be convenient enough sometimes. I would love to see this part of the API come into being.

Cockpit CMS is best for those PHP developers who possess a certain level of PHP, CSS and framework knowledge, who are unwilling to be bound by other heavier CMSes and want to create a simple, tidy and “everything-under-my-control” CMS to show off their work and life. However, it is important to highlight that this may increase the programming difficulty, especially when we need to add more features into the fronend.

There are certain other areas provided by Cockpit that are not covered in this post – feel free to explore its potential and share what you have achieved.

The demo code for this tutorial can be found in the Github repo here.


Thank you for introducing and presenting Cockpit. I'm the creator and developer of the project.

I have some additional notes to the article:

I agree with the statement that Cockpit is very developer centric. But with that comes great flexibility. Custom layouts, routing, project structure etc. you can even use Cockpit as a data provider for a mobile app if you want.

Again thank you for writing about Cockpit!


Cool. Nothing can be better with the input from the original author.

The hints provided will be absolutely useful and more on the "right" way. Mine is on the "hacker" way.

Documentation is of top importance. Please do make it more usable and better.


So, who is building with Cockpit? Is there a community or support forum somewhere for people to discuss it?


community support right now is provided via a google group -


It's always nice to find out about a new CMS. One thing, though: they can run in so many different environments that it's always good to set the scene from the outset. I had to read a long way into this article to know whether this CMS ran on PHP, Ruby, Node or whatever. It would be good to have clarified that at the start. smile


Well, it's on the PHP channel smile


Well, default value for language in this channel is PHP. sunglasses


Fair enough, although it's not always read in that context—such as on RSS or coming from the forums. Ideally, content should be self-contained and not dependent on the surroundings. Anyhow, minor distraction from a good article. Sorry!


Should be in the PHP category in the forums, too, every time something is published in a language master category, it goes into the appropriate forum subcategory. I can dig the RSS confusion, though, but you shouldn't be able to see the whole post without clicking through to it in your RSS reader and that's when the big PHP badge is shown at the top.

Do you see the whole post in your feed? If so, we need to fix that.


In this case I saw it in the forums, so don't worry. I did miss the PHP tag, but I think (like a lot of people) I'm trained to tune out extraneous material and focus on the main content. So in forums I'm often confused about people's posts, because their only question is contained in the title of the post—somewhat removed from the post itself. Anyhow, maybe it's just me. (I didn't mean to make a mountain over it. smile )


I have been using CockpitCMS. As you have pointed out, it is quite developer centric. The creator of this CMS is very talented and he is also one of the core contributors for UIKit, a lightweight UI framework and pagekit CMS as well. Cockpit CMS uses all the latest techniques in PHP, uses SPLs very wisely. It is a very good tool to have in our arsenal


It looks good, but from what I can see the whole toolkit for working with the API is loaded into the global scope? so cockpit is a global function


I played with this CMS for a week and I have to admit it is a pretty cool concept and offer great potentials of use.

Although I want to expose my concerns about the project:

  • It is not well documented: this limit in my opinion the use of this framework because you have to dig into the code to try to understand what every component does.
  • Project architecture: while the use of the CMS is straightforward and promises great flexibility the code architecture is chaotic to me. I cannot use the component via composer, there is no use of namespacing so the code is less reusable and maintainable from the user perspective. I cannot understand how to export a database structure and import it into another installation of cockpit (versioning of the backend is hard)
  • Use of not tested components: that really push me to use it only for personal projects.

Overall I fell that I have spent well my time on this project since I learned a lot of things and I really wish the best for the author of the framework, I hope you get my critique positively, it is not meant to discredit your work but to improve it. Thank you smiley


Thank you very much for the feedback and for taking an in-depth look at it! I'm sure @faulancer will appreciate it : )


How you can access to dashboard/admin page after creating website in the other folder?



Learn Coding Online
Learn Web Development

Start learning web development and design for free with SitePoint Premium!

Get the latest in PHP, once a week, for free.