Pico CMS and Draft – awesome blogging solution


Few days ago I stumbled upon a beautifully simple flat file CMS called Pico. Pico is a product of Gilbert Pellegrom and is so amazingly simple that I see it as the next big thing in blogging.

It is flat file based, you create MarkDown files and just upload them to content folder. Yes, simple as that. There is no admin. No login. No database. No nothing. Just blogging.

As you already noticed, there is a plethora of activity in the blogging revolution sector lately, but I find Pico very interesting to a blogger. Everything in Pico is so simple that it hurts.

It uses Twig engine for it’s themes and comes with only one file in default theme folder. One file and a style sheet.

But, I was thinking that writing Markdown files somewhere locally, saving, then uploading to the server via FTP is just not 21st century…

So, that’s where Draft comes in. Draft is an awesome product by Nathan Kontny . You can use it as distraction free writing tool with version control and some neat features like publishing to different platforms, saving to cloud and other great stuff Nathan does.

It also comes with an API, web hooks and markdown tools.

Pico and Draft wedding

All that awesomeness of Draft and Pico made me think about combining those two products and making them even more cool. So I wrote a Pico plugin that is used to catch Draft’s publish web hook POST request and saves the received file in Pico’s content folder.

Oh yeah. Sounds cool. You know what is even cooler? It is just a couple of lines of code in Pico and couple of clicks in Draft.

Pico Draft plugin

Ok, here is the whole Pico plugin:

class Pico_Draft {

	public function request_url(&$url)
		// change this to something that is not easily guessed!!!
		// you will need this URL to set up a webhook on Draft settings page
		if ('a4337bc45a8fc543c03f52dc758cd6e1e87021bc896588bd79e901e3' == $url) {
			// getting the payload, decoding it and saving to file system inside content dir
			if ($_POST['payload']) {
				// we have a request from Draft, let's save it to file
				$payload = json_decode($_POST['payload']);
				$fileName = strtolower($payload->name) . CONTENT_EXT;
				@file_put_contents(CONTENT_DIR . $fileName, $payload->content);
			exit; // stop everything!

Copy/paste this code into a pico_draft.php file (it has to be called exactly that), change that long URL and put that file into Pico’s plugin folder. Change the permissions in /content folder so that web server can write into it.

This code is checking the requested URL, if it is found to be your big ass string, than it get’s the payload received from Draft and saves it as a file in content directory. If the file already exists, it will overwrite it’s content!

To make all this work, upload Pico along with your new plugin to your web server.

Now, we need to create a web hook on Draft to add new publisher and make all this possible. So go to Draft and Sign Up and Login (you can even buy a subscription to help the project, but it’s not necessary).

After you log in, there will be a Settings link in the upper left corner. Click it, then click on Places to publish.
Click on Webhook URL, enter the name for your Web hook (it can be whatever you want).

As for the webhook URL, you need to enter your URL where Pico is installed and your long string from plugin. In my case something like: http://domain.com/a4337bc45a8fc543c03f52dc758cd6e1e87021bc896588bd79e901e3

Click Save and that’s it, you just paired Pico and Draft into, what I think, is quite an awesome pair.

Now, create a new Pico document on Draft (don’t forget the comment with meta data on top), for example:

Title: My awesome document
Description: This description will go in the meta description tag
Author: Zvonko Biškup
Date: 2013/06/30

## Some heading
Some awesome text of yours

Now, save it and Publish it to your web hook. If everything went ok, you should be able to access your new document by going to http://domain.com/name where name is the name of the document as you entered it on Draft (Not that one in document’s comment, that’s for meta data).

To make Pico look more like a blog, I changed some things in the default theme, commented out the navigation and added the list of pages to the front page:


<!DOCTYPE html>
<html lang="en" class="no-js">
	<meta charset="utf-8" />

	<title>{% if meta.title %}{{ meta.title }} | {% endif %}{{ site_title }}</title>
{% if meta.description %}
	<meta name="description" content="{{ meta.description }}">
{% endif %}{% if meta.robots %}
	<meta name="robots" content="{{ meta.robots }}">
{% endif %}

	<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Open+Sans:400,700" type="text/css" />
	<link rel="stylesheet" href="{{ theme_url }}/style.css" type="text/css" />

	<script src="{{ theme_url }}/scripts/modernizr-2.6.1.min.js"></script>

	<header id="header">
		<div class="inner clearfix">
			<h1><a href="{{ base_url }}">{{ site_title }}</a></h1>
			<!-- <ul class="nav">
				{% for page in pages %}
				<li><a href="{{ page.url }}">{{ page.title }}</a></li>
				{% endfor %}
			</ul> -->

	<section id="content">
		<div class="inner">
			{% if is_front_page %} <!-- Front page lists all blog posts -->
				<div id="posts">
					{% for page in pages %}
						{% if page.date %} <!-- Note we check for Date field (posts) here -->
						<div class="post">
							<h3><a href="{{ page.url }}">{{ page.title }}</a></h3>
							<p class="meta">{{ page.date_formatted }}</p>
							<p class="excerpt">{{ page.excerpt }}</p>
						{% endif %}
					{% endfor %}
			{% else %}
				<div class="post">
					{% if meta.title %}<h2>{{ meta.title }}</h2>{% endif %}
					<p class="meta">{{ meta.date_formatted }}</p>
					{{ content }}
			{% endif %}

	<footer id="footer">
		<div class="inner">
			<a href="http://pico.dev7studios.com">Pico</a> was made by <a href="http://gilbert.pellegrom.me">Gilbert Pellegrom</a>
			from <a href="http://dev7studios.com">Dev7studios</a>.


Source files

I will surely write some more tutorials on this subject, but this is it for now.

Please, share your opinions in the comments below.

About the author

Zvonko Biškup

A passionate web developer with more than 13 years experience in PHP and other web related technology. My main interest is WordPress and new PHP frameworks.
Owner of Influendo Programming.
Enjoys exploring new stuff and possibilities, using new technologies and just having fun developing awesome stuff.

  • Matt Genovese

    Thank you for the well-written post. You may also want to mention that care should be given to the permissions on the content/ directory. Took me a while to debug why the content file was not created on my own server.

    • Nice catch, I edited the tutorial to mention proper permissions inside the content folder

  • idriss jouid

    hi Zvonko,

    Thank you very much for this post i really like this concept. But i have a problem whene testing this into a free web hosting account : the drafts created an published didn’t upload in my free host server. Is it because a free hosting plan ? do we have some tools to debug the pulish.

    • It depends on the hosting company, maybe you have PHP error log in which there is more information in the root of your site. Ask the hosting company for help on finding the error logs.

  • Thanks, I’ll be looking into this more as I go, just needed some advice on which direction to take.