Requirements
Before I built this site I came up with three key requirements:
- Must be really easy to add new content.
- Must not be bloated with blog/CMS software.
- Must not use a database backend.
Number 1 is pretty obvious, number 2 was because I wanted to keep the site as lightweight as possible and number 3 was to help save hosting costs. (MS SQL Server databases usually incur an extra charge, and I didn't want to use MySQL).
Technology
The backend for the site was written in C#, as an ASP.NET Webforms application. I may well rewrite it as an ASP.NET MVC application – if I ever get the time!
Articles
The only element of the site that is managed by the CMS is the collection of articles.
Each article consists of at least 2 files. The files are stored in a single folder within the website.
The first file is a "meta data" file and the second is a "body content" file. They are named using this pattern (where xxx is a number):
xxx_meta.xml
xxx_content.text
Here's the contents of the meta data file for this article (at the time of writing):
<?xml version="1.0" encoding="utf-8" ?>
<article title="How this site works / building a rudimentary flat-file CMS" created="2010-02-28">
<summary>A description of how this site works, including details of the rudimentary flat file CMS it uses.</summary>
</article>
As you can see, the meta data file provides the title, summary and creation date for the article.
The body content file contains plain text that has been marked up with MarkDown.
In addition, an optional "head content" file can be added using this pattern:
xxx_head.htm
The head content contains HTML to be inserted into the header of the article. (This can be used for adding custom stylesheets or JavaScript to an article).
Loading articles into memory
When the site is first accessed a static singleton class called ArticleManager is constructed. ArticleManager scans the articles folder and reads each meta data file.
The meta data information is stored in a series of Article objects that are held within the ArticleManager. These objects are kept until the application is recycled. One additional piece of meta information that isn't taken from the meta data file is the "Last modified" date. This date is deduced by looking at the last modified date for the body content file.
When a particular article is viewed the appropriate Article object is retrieved from the ArticleManager and a method called GetArticleContent() is called on the Article.
GetArticleContent() returns an ArticleContent object, either by creating a new one (and then caching it) or by looking in the Cache to see if it already exists.
Creating the ArticleContent object
The ArticleContent object holds the head and body content along with a list of section names.
When a new ArticleContent object is constructed the following steps take place:
- Body content file is read from the disk and all of the H3 headings are recorded as section names.
- Body content is run through the Markdown transform.
- H3 tags have section ids inserted into them (to allow in-page linking).
- Optional head content file is loaded (if present).
Rendering an article
Every article is viewed in the ArticleView.aspx page. I use URL rewriting (provided by my web host) to mask the page name. (That's why you can't see it in the URL at the moment).
Once the ArticleContent has been retrieved it's just a matter of writing the different pieces of content into a series of Literal/Repeater controls.
Adding new content
This is how I add a new article to the site:
- Create a new body content and meta data file.
- Write my article in the body content file.
- Upload the 2 files to the articles folder.
- Use an administration page to empty the Cache and recycle the meta data cache within
ArticleManager.
Eye candy
I use the following tools and jQuery plugins to give the page some visual flair: