I was on the search for a minimalistic blogging experience. I have found it in PicoCMS. Here's how I build my minimal blog on it.

A few months ago I started to go more bare bone. A minimalist approach to software, so to say. So that included my personal website. It needed it to function and be convenient, yet simple enough so I knew exactly what was going on at any point.

Pico is a so-called 'flat file CMS'. You drag and drop .md files in a folder and it'll show on the website.

No database nonsense and full markdown support. Just the way I like it.

How I setup Pico as a blog

Initially, Pico is not meant as a blogging platform. However, it makes it simple to make it a blog out of it.

Instead of displaying the different pages in the navigation menu, I made it display the pages as a list.

I rewrote how Pico displays its content. The following code does two things:

  1. It'll determine whether I am on the front page, and display the 'index.md'. (If it is not the front page, it will display the article.)
  2. List all other markdown files marked with 'Type: post' in the directory /content/. (That way I can exclude pages from the 'articles list'.)
 <div class="wrap">
            {% if is_front_page %}
                {% if not(page.url == base_url ~ '/') %}
                    {{ content }}
                    <div class="blog-articles">
                        {% for page in pages | sort_by("time") | reverse %}
                            {% if page.meta.type == 'post' %}
                                <section>
                                    <a href="{{ page.url }}"></a>
                                    <h1>
                                        {{ page.title }}
                                    </h1>
                                    <p class="excerpt">{{ page.description }}</p>
                                </section>
                            {% endif %}
                        {% endfor %}
                    </div>

                {% endif %}
            {% else %}
                <article class="post">
                    <a href="./" class="back-link">Back link</a>
                    <header>
                        <h1>{{ meta.title }}</h1>
                        <div class="post-meta">
                            <time>Published on
                                {{ meta.date }}</time>
                        </div>
                    </header>

                    <div class="post-content">
                        {{ content }}
                    </div>
                </article>
            {% endif %}

        </div>

Plugins

Setting up a sitemap.xml

The plugins work the same way as articles. One php file in the plugins folder and done: I have an automatic generated sitemap on geffrey.io/sitemap.xml.

Here's the PHP script I used (written by DaveKin on Github):

<?php

class PicoXMLSitemap extends AbstractPicoPlugin
{
    private $is_sitemap = false;

    public function onRequestUrl(&$url)
    {
        if($url == 'sitemap.xml') {
            $this->is_sitemap = true;
        }
    }

    public function onPagesLoaded(&$pages, &$currentPage, &$previousPage, &$nextPage)
    {
                if($this->is_sitemap){
            header($_SERVER['SERVER_PROTOCOL'].' 200 OK');
            header('Content-Type: application/xml; charset=UTF-8');
            $xml = '<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
            foreach( $pages as $page ){
                $xml .= '<url><loc>'.$page['url'].'</loc>';
                if(!empty($page['date'])){
                    $xml .= '<lastmod>'.date('c', $page['time']).'</lastmod>';
                }
                $xml .= '</url>';
            }
            $xml .= '</urlset>';
            header('Content-Type: text/xml');
            die($xml);
        }
    }

}

That's it. That's what I am running now.

Things that are still left to do:

  1. Pagination
  2. RSS feed implementation
  3. SEO optimisation
  4. Open Graph images for sharing articles
  5. Support for more pages