iOS Developer / Photographer living in downtown Toronto. Associate at Teehan+Lax; Developer of Readability, TweetMag, and (someday) FindNext.


A Simple Blog Platform

Toronto. 2013-06-04

A couple of months back I decided I should refresh my website and do something more with the content I create. Sites I have traditionally used to share thoughts and photographs have fallen out of favour and my work is scattered across a bunch of networks. Time to take ownership again.

Unfortunately, I struggled to find a blog / content platform that clicked with my needs. I used WordPress off and on but found dealing with a database and login permissions fussy for a personal site, and Tumblr triggers concerns over ownership and copyright. So, I decided to build my own using familiar technology and the simplest server setup possible.

Here are the components I tied together.

Markdown

"Markdown allows you to write using an easy-to-read, easy-to-write plain text format, then convert it to structurally valid XHTML (or HTML)."

Thanks to GitHub and its rich commenting and push request system, I've become fairly well-versed in Markdown syntax. All the content for this site is stored as Markdown (.md) files which are parsed by the PHP Markdown library.

Dropbox

Dropbox is used as the CMS. It just made sense - I have access to it from anywhere, basic versioning is built-in, and I can author and push content from my iPhone (using Byword for example) if I like. I can create a document with any path and filename I like and then link to it. Done.

For example, this post is a-simple-blog-platform.md. The filesystem and mod_rewrite (see below) do the rest. Dropbox for linux was installed and a daemon and upstart script put in place. Rather than sync my entire Dropbox account to this server, I created a dedicated account for the content and then I shared a directory back to my primary account. Sync is extremely fast.

Note: Dropbox wants to be in a user's root directory by default, and while there are tools to change that I decided not to mess with the configuration. Instead, I created a symlink so the web server could access the files.

Apache mod_rewrite

For the display of content, there is only one PHP script on this server. It looks at the incoming request URI, locates the markdown file with that path and parses it using the PHP library. Here are the rewrites being used - requests for images or other files on the filesystem aren't tampered with.

RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

git

git

git has grown on me, again mostly thanks to GitHub. While the content is managed using Dropbox, scripts and server config are checked into git. As this platform idea is a work in progress, git allows me to tinker without worrying. I can roll back a change if something goes awry. Also I can add nearly any configuration file to the repo by copying the file and then symlinking back to the expected location.

Twitter Bootstrap

The Twitter Bootstrap framework is probably overkill for a simple site like this one, but there is some great built-in functionality I can tap should I need it. Since I'm managing the server config and scripts using git, I brought Bootstrap in as a submodule. I simply symlink to the compiled CSS and JS files.

URL Shortener

I reluctantly used a database for this one. I moved my existing custom shortener (blyn.ch) data from MySQL to MongoDB and simplified the code to include it in the main PHP script. If a Markdown file isn't found for a given URL, it checks to see if a matching slug exists in the Mongo DB. If so, it'll redirect to that site (and perform some tracking along the way). Otherwise, it just pushes to a 404 page. Administration functions are rolled in too.

More to explore

Down the road, I'll likely transition to Flask and Python-Markdown (which I've used elsewhere). There are certain aspects of this platform approach that require more manual intervention than I'd like, but I'm very happy with the workflow to post new content. Let me know what you think or if you implement a similar setup!