The Making of HelgeKlein.com, SetACL’s New Home
Until yesterday, SetACL’s web presence consisted of six static HTML pages. That was great for speed, but it sucked in almost every other aspect. And the design … better not speak about that. The old website was hosted on Sourceforge, on the subdomain setacl.sourceforge.net, to be exact. High time for a radical change. I wanted a good clean design, interactivity (commenting), easy maintenance and my own domain. And I wanted a place where I could assemble and store all the relevant content I publish on the web, namely blog articles and tweets. This is the story of the creation of that place.
CMS
It was pretty clear that I needed a CMS. Although I liked Wordress very much, the fact that I needed a CMS seemed to rule out WordPress. I looked around, searched and read a lot. Finding a CMS is tough, simply because of the sheer number of different ones available. There are hundreds of them. Comparison sites exist, but I did not find a really helpful one. After a lot of research I settled on Textpattern, not least because great web designer Jon Hicks thinks highly of it. Other finalists were Expression Engine, modx and Concrete5. Well-known Drupal and Joomla I ruled out almost from the beginning. They are way too complex. I do not need a steep learning curve, but a flexible tool that lets me realize my ideas quickly.
Self-Hosted or Cloud?
I had experimented with a blog at WordPress.com, which is the officially hosted version of the popular blog software. I liked the idea of a CMS in the cloud very much. My time is very limited and I prefer to spend it programming or writing rather than administering a web server. Creating instead of maintaining. And then there is the security aspect: what if there is a critical security update which I know nothing about because I am busy building sand castles with my daughter in a multi-week holiday? So I looked for a “cloud CMS” operated by a service provider, scalable and secure. Man was I surprised to find out that everybody is talking about clouds – but there is not a single serious offering of a cloud CMS! That is even more peculiar considering the fact that a CMS is typically web-based and as such inherently well-suited for being operated in a cloud.
So, no cloud CMS for me. One might argue that WordPress.com is a cloud CMS, but there I witnessed the biggest disadvantage of software in the cloud: lack of flexibility. Clouds are efficient when the service can be standardized and automated. Indivudual themes, plugins and configurations do not fit well into that model. That was the second reason why I turned away from potential cloud offerings (that do not exist anyway today).
WordPress?!
Suddenly I decided against the “real” CMS and for WordPress. I had researched using WordPress as a CMS before, but had not found substantial evidence for this being a viable solution. But now I had a gut feeling telling me WordPress was the way to go. Why? I had experience with WordPress from my blog at sepago (before we moved to Drupal for the entire site) and knew it to be both easy to use and extremely flexible with a large user base that produces plugins for almost anything. Using the most popular blog/CMS product on the planet has the unbeatable benefits of guaranteeing continuing development, large numbers of themes and plugins to choose from and support via innumerable websites, forums and blogs. So WordPress it is!
Themes
It was clear to me that I needed a good theme to base my own customization and design efforts on. I am no designer and I know it – the obvious and affordable solution are “prêt-à-porter” themes where individual designers or design shops sell their fully-styled creations for prices that range from € 20 to 100. Affordable enough. And simple. Buy, download, install, done. But that is the theory. In practice it is much more labor-intensive, even the buying. Which theme to select? There are thousands, and I could not find a single helpful comparison site. Which reminds me of the CMS selection process. Both of these processes are extremely time-intensive and painful. Entrepreneurs, this calls for a product! Create tools that help people choose CMS and theme! With the right selection tools I could have saved days. Did I mention that time is the scarcest of my resources (yes, even scarcer than money!).
After searching for way too long and nearly choosing Display by an individual designer I went with my previously mentioned policy of “avantgarde mainstream” by choosing Canvas from Woo Themes, a minimalistic but sophisticated theme promising versatility, regular updates and good support. As you see, I am always looking for the same qualities: I want to buy a good product today, but I want it to remain good, which is only possible if the vendor regularly updates the product.
Layout
I love designs that intelligently use the so-called screen real estate. With regards to web site design my benchmark is Jon Hicks’ fluid layout. When visiting his site just change your browser’s width from wide to narrow – you will be amazed! Alas, that is avantgarde today, not found in commercial or free themes. What I did hope for was flexible width, where the main content area expands to fill the available width, but even that proved to be incompatible with my other requirements. So in the end I had no choice but to go with the mainstream and use the prevalent fixed-width layout. At least, with Canvas, the width can be modified.
Hosting Provider
Now I needed a web hoster. Again, I underwent the same procedure as with CMS and theme: very long research, not finding good comparison sites, choosing by gut feeling in the end. Only this time I listened to my gut too late. First I went, as before, with the mainstream and chose a shared account at Hostgator, a very large hoster recommended in many forums. But after installing WordPress and playing around for a while I had to admit to myself that my choice had not been a good one – the server was just veeeery slooooow.
I bit the bullet, underwent the registration and SSL certification setup procedure (I want secure administration!) again, this time with Rochen, a hoster I had read about in a Joomla forum. That is where I am now. The server is lightning-fast (at least compared to Hostgator) and the support is pretty good (though not excellent).
CSS and Design
After installing WordPress and playing around with my new site I quickly noticed that I needed to adjust one thing here, another there. I am way too perfectionist to use a theme out of the box, and Canvas is built for customization. The most noteable thing in this area is that I realized I needed an image in the header representing my site while simply looking good and ideally being meaningful. My wife came up with what you can see now, the steeples of the Cologne Cathedral (“home”) with the birds flying towards it. Everything else is my doing.
Plugins
WordPress has great plugins, and there are so many of them that chances are good that you find one for nearly every idea you want to realize. In my case I had a couple of site features I absolutely wanted, while others I implemented because it was possible easily. But as a general rule, I try to use as few plugins as possible. Given the abundance of plugins that may sound strange, but it is really the same as being in a candy store with a all-you-can-eat ticket. Eat little – and you will enjoy the experience. Eat a lot – and you will be seriously ill.
Plugins needs to be maintained by their authors. The more you have, the higher the chances that you cannot upgrade to future WordPress versions because of incompatible plugins. And plugins are scripts, programs. They potentially slow the server down. That is especially important with shared hosting, where resources are not exactly abundant. That brings me to my first plugin, WP Super Cache. WordPress and all its plugins are written in PHP, an interpreted language. Interpretation means slowness or, in other words, high resource consumption. WP Super Cache replaces ineffective interpretation of the same code over and over each time a page is requested by creating a static version of each page automatically. Given the dynamic nature of WordPress this is a very tough job, and I must say, I am very impressed!
Out of the other plugins I use, I want to highlight Table of Content. It creates a table of content from an existing page automatically without requiring modiyfing the page’s code. You can see it in action here. I selected it over similar plugins because of the clean code. What really convinced me, though, was that developer Ulrich Kautz provided the most excellent support imaginable – for free!
These are the other plugins I use:
- Lightbox 2: Shows images in a pop-up “lightbox”.
- Top 10: Counts which pages and posts are viewed how often and offers a “popular posts” widget.
- WP-reCAPTCHA: Stops spam by requiring users to solve a CAPTCHA (“Completely Automated Public Turing test to tell Computers and Humans Apart”) when commenting. Helps Google with its book scanning.
- WP-Syntax: I am a developer. I write code. Presenting code on the web is difficult. WP-Syntax takes care of that.
- Yet Another Related Posts Plugin: People come to your site via Google. They read the article Google pointed them to, then they leave. That is not what webmasters want – they want visitors to stay on the site and read other articles. This plugin helps by calculating which other articles might be related to the current page and displaying a list of related posts below each blog post.
- Yoast Breadcrumbs: Navigation, navigation, navigation. Visitors need to know where they are and how to get from where they are to where they want to be. Breadcrumbs help.
- WP Minify: Reduces page load times by combining and compressing JS and CSS files.
Migration
Migrating content from one site to another is not fun. It is a labor-intensive process requiring much manual intervention to fix the arising problems small and large. Once the content is safely tucked away in the WordPress database, the big moment comes: flipping the switch. Apart from making the new site visible to the public by disabling Private Only, HTTP 301 redirects are essential. Only with 301s both visitors and search engines can be transparently moved from an old to a new domain.
During the migration, my personal blog moved from blog.helgeklein.com to helgeklein.com/blog. That looks like a simple migration, and it is. But only because I already had the blog on my own domain. With everything under my control I simply changed the A record in DNS for blog.helgeklein.com to point from Google’s name servers (I migrated away from Blogger.com) to my own new server. On the server itself I made use of the popular Apache module mod_rewrite to implement the actual URL rewriting, i.e. changing blog.helgeklein.com to helgeklein.com/blog. This is the code from .htaccess in the root folder of the site:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# Begin redirect from blog.helgeklein.com to helgeklein.com/blog (Blogger to this WordPress instance)
RewriteCond %{HTTP_HOST} ^blog\.helgeklein\.com$
RewriteRule ^2010/09/how-to-map-generic-rights-to-standard\.html$ https://helgeklein.com/blog/2010/09/how-to-map-generic-rights-to-standard-and-specific-rights/ [R=301,L]
RewriteCond %{HTTP_HOST} ^blog\.helgeklein\.com$
RewriteRule ^2010/08/what-is-synchronize-file-access-right\.html$ https://helgeklein.com/blog/2010/08/what-is-the-synchronize-file-access-right/ [R=301,L]
[... more rules - one for each blog article ... then a general catch-all]
RewriteCond %{HTTP_HOST} ^blog\.helgeklein\.com$
RewriteRule ^ https://helgeklein.com/blog/ [R=301,L]
# End redirect from blog.helgeklein.com to helgeklein.com/blog (Blogger to this WordPress instance)
</IfModule>
The swtich from setacl.sourceforge.net to helgeklein.com was similar, but not identical. Luckily Sourceforge allows the use of .htaccess files on their web servers. They do not have the module mod_rewrite installed, though. HTTP 301 redirects can be implemented as my example shows:
Redirect 301 /html/doc-activex.html https://helgeklein.com/setacl/documentation/com-version-setacl-ocx/
Redirect 301 /html/doc-basics.html https://helgeklein.com/setacl/documentation/
Redirect 301 /html/doc-reference.html https://helgeklein.com/setacl/documentation/command-line-version-setacl-exe/
Redirect 301 /html/examples.html https://helgeklein.com/setacl/examples/
Redirect 301 /html/faq.html https://helgeklein.com/setacl/faq/
Redirect 301 /index.html https://helgeklein.com
Redirect 301 / https://helgeklein.com
As before, each page needs to be redirected individually. The last rule redirects the home page.
Tweet Archive
When I thought I was finished I suddenly had another idea. I had pondered the idea of a tweet archive before, but none of the existing Twitter backup solutions I deemed satisfactory. But now I had my own web server, an altogether different situation. Why not pull my tweets into WordPress, making them available long-term and, of course, easily searchable? That proved to be very doable indeed.
While loosely following these instructions, I made some alterations worth mentioning. I had previously switched WordPress into network mode, a new feature of WordPress 3 allowing multiple blogs with one installation of WordPress. Now I quickly created another site positioned at helgeklein.com/tweets and installed the free tweet archive theme by stopdesign. Then I installed “Twitter Tools” and used “Twitter Importer” as suggested in the instructions. I now had every single tweet as an individual blog post on by tweets blog – but links were not clickable. I did not want to employ a plugin solely for the purpose of working around a partly broken importer. Instead I exported the posts database table, wrote a script to add anchors to the URLs and then re-imported the modified SQL file. Here is the (Perl) script:
use strict;
open (IN, "<tweets-in.txt") or die "could not open input\n";
open (OUT, ">tweets-out.txt") or die "could not open output\n";
while (<IN>)
{
chomp;
# Ignore empty lines and comments
if (/^\s*[#|;]/ || /^\s*$/)
{
next;
}
my $line = $_;
# Make URL clickable
my $line2 = $line;
foreach ($line =~ m!(http\://[a-zA-Z0-9]+(\.[a-zA-Z0-9]+)+([a-zA-Z0-9\.\?=\-\/_]+)*)!i)
{
my $url = $1;
unless ($url =~ m!helgeklein.com/tweets!i)
{
# Remove trailing dot
$url =~ s!\.$!!;
if ($url gt "")
{
$line2 =~ s!$url!<a href="$url" target="_blank">$url</a>!;
last;
}
}
}
# Link to user names (@user)
$line2 =~ s!(\@([0-9a-zA-Z_]+))!<a href="http://www.twitter.com/$2" target="_blank">$1</a>!;
print OUT "$line2\n";
}