World's smallest Content Management System

Ok, lets not argue, I guess you can always find a smaller one written in Perl or something, so let me rephrase to “a really small and simple CMS”.

A year ago I needed a CMS. My challenge was an easy and small one, and I wanted to keep the solution easy and small. I was running a phpBB-forum and wanted a simple way to make a list of featured forum-posts. Each item in the list of featured posts should contain a title, a photo and a link the forum-post in mind. I also liked to keep the hardware requirements at a minimum and have as little maintenance as possible.

Problem was, all Open Source solutions I’ve tested or looked at had grown really big. I also checked Yahoo Pipes to see if I could make something out of it, but somehow I always hit a brick wall when trying it out.

Google Docs to the rescue!
So, then I remembered that you can connect an HTML-form to a Google Docs Spreadsheet. The form has it’s own URL and can be included anywhere and elsewhere. Also, the actual spreadsheet document can be published as a CSV-file. And with those two details you have your own, simple, hosted database-table, complete with an input-form.

Creating some HTML and saving it to a file
I’m not a programmer, I have only written some code in PHP and Python. Checking out the documentation on how to open a file, fopen, and how to parse the CSV-content,, made me choose PHP. It’s dead simple. From PHP you simply do:

  1. Open Google Docs Spreadsheet and parse CSV-data
  2. Generate HTML and populate $html
  3. Open existing HTML-file and check if it’s == $html
    1. If yes: Die
    2. If not, overwrite file


/* Open CSV file, and setting count-variable to 0 */
$handle = fopen("[URL to CSV-version of Google Doc Spreadsheet]", "r");
$c = 0;

/* gets data from csv file, and populates array $data */
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {

/* stores rows of data into array $featured */
$featured[$c] = $data;
/* Debug: check data put into array $featured */
//echo $data[0] . " " . $data[1] . " " . $data[2] . " " . $data[3] . "<br />\n";

/* Reverse topic-array so newest is line zero. The input form puts newest content at the bottom of the spreadsheet */
$featured = array_reverse($featured);

/* Traverses from row 0 to row 9 in array $featured and creates HTML */
$row = 0;
$html = "<div id=\"featured\">\n";
while ($row <= 9) {
$html .= " <div>\n <a href=\"" . $featured[$row][2] . "\">" . $featured[$row][1] . "</a>\n <a href=\"" . $featured[$row][2] . "\"><img alt=\"photo\" width=\"320\" height=\"160\" src=\"" . $featured[$row][3] . "\"></a>\n </div>\n" ;
$row++; // count to last row of data
$html .= "</div>\n";

/* Debug: check if $html is being populated */
//echo $html;

/* Opens a read-only version of the HTML-file and checks if equal to variable $html */
$fp = fopen('[path to HTML-file]featured.html', 'r+');
$htmlfil = file_get_contents('[path to HTML-file]featured.html');
if ($htmlfil == $html) {
echo ('Content has not been changed, not writing to file --- ');
/* Opens a read-write version of the HTML file, sets the filepointer at the beginning of the file and truncates the file to zero length.
If the file doesn't exist, the function will attempt to create it. */
} else {
$fpoverwrite = fopen('[path to HTML-file]featured.html', 'w+');
echo ('Content has changed, writing to file --- ');
fwrite($fpoverwrite, $html);

In addition you may want to do these two steps:

  1. No escaping of characters is being done, so php-file should be protected. Running LAMP, you could set up .htpasswd and .htaccess to password protect a folder.
  2. Let featured.php be run from i.e. crontab.

Checking for changes in spreadsheet automatically
I used crontab to run the featured.php-file every five minutes.

Apache and security
Instead of making the PHP-file secure, escaping characters etc, I took the easy way out. Only me, or people I know will use the form. , used .htaccess and .htpasswd to password-protect the folder on the webserver. Write access to the Google Docs Spreadsheet is managed by Google.


AuthUserFile [path to file].htpasswd
AuthName "Password protected area"
AuthType Basic
<Limit GET POST>
require valid-user

Command-line stuff to create the .htpasswd-file:

htpasswd -c [path to file].htpasswd [username]

The file featured.php creates a file featured.html, which is not a full HTML-file, but contains HTML-code. For my purpose, this was perfect. If you need something of a full HTML-file, there are many ways of achieving that. Easiest would probably be to expand the $html-variable.

So, what could make this better?
All comments are welcome, either within this “framework”, or by poiting out some other solution.

Vist 3420 ganger. Følges av 1 person.