Painless Switch from TypePad to WordPress

Earlier this week I switched my blogging platform from TypePad to WordPress. TypePad is a hosted service and its been REALLY slow lately, its feature-set has stagnated, and it reports barely any statistics. Switching to WordPress would give me tons of power and flexibility.

But switching isn’t easy. It was critical to me not to have any down time and and not to break incoming links. Links from other people or from search engines needed to “just work”.

If I had been using the default TypePad URL stiles.typepad.com I would have been up-a-creek, but I used their domain mapping function and my blog has always served pages at http://www.adamstiles.com. Because I control that domain and its DNS I could manage the switch more easily.

The first thing I did was setup the new WordPress site on one of my servers. The new site was “located” at adamstiles.com but http://www.adamstiles.com was still working at TypePad. Having two live sites with similar URLs made it easy to test links. Just grab a link from the old blog, remove the “www”, test it, etc. When I was finally ready to switchover, I would just change the “www” CNAME DNS record to point at adamstiles.com instead of at stiles.typepad.com. Easy.

TypePad shares an export format with its cousin MovableType. My old TypePad urls took the format adam/{year}/{month}/{name}.html. I setup WordPress to do something similar. In WordPress Admin, Options, Permalinks, set Structure to this value:

/%year%/%monthnum%/%postname%/

OK – lets import the posts from my old blog. The WordPress/Movable Type importer worked great, but my new post URLs didn’t map very well to the old ones.

OLD: /adam/2005/10/refactoring_wit.html
NEW: /2005/10/refactoring-with-pickaxe/

Arghh. The TypePad exporter didn’t include the post “name” (called a “slug” in WordPress lingo) so WordPress created its own. That’s not gonna work. I could workaround the missing “adam” in the URL or the extra “.html” at the end (more on that later), but I needed my post names to come through. TypePad custom templates to the rescue.

All TypePad pages are created using templates. These templates have variables and you can use these variables to do a “mail-merge” to create new documents. If I could create a template that could mail-merge my posts into the standard TypePad export format, but add the post name, then tweak the WordPress importer to recognize and save the post name, I’d be good to go.

Here’s the custom export template I created, and here’s the new importer. I had to make three changes to the old importer: I added a section that would import the correct post name; I removed the old post name section; and I worked around some extra line breaks in the PING parsing section. If anyone wants to see a diff, just ask. I exported my data (I actually did it a bunch of times, made tweaks, reset the database, and started over), imported it into WordPress, and now my new URLs are much closer to what I need.

The custom-export custom-import tweaks go me this far…

OLD: /adam/2005/10/refactoring_wit.html
NEW: /2005/10/refactoring-with-pickaxe/

…but now I needed to make sure that WordPress would respond correctly to the old URLs. That’s where Apache’s mod_rewrite module comes in. mod_rewrite lets you take in incoming URL, slice-and-dice it, and rewrite it in another format.

The first custom mod_rewrite rule I added maintains my permalinks. Any URL coming in that starts with “adam” followed by a 4-digit-year and a 2-digit-month, and ending in “.html” would be handled exactly like the sample WordPress URL above… we would pass WordPress the year, month and name variables and everything would work as expected.

#
# Rewrite old permalinks to new location
# FROM: /adam/2005/12/article_name.html
# TO: index.php?year=2005&monthnum=12&name=article_name
# Same as 2005/12/article_name/ in new system
#
RewriteRule ^adam/([0-9]{4})/([0-9]{1,2})/(.*).html$ /index.php?year=$1&monthnum=$2&name=$3 [QSA,L]

The next custom rule allowed me to maintain the old calendar archive links. These links are similar to the permalinks above but don’t have a name.

#
# Redirect montly archives to new location
# FROM: adam/2005/12/index.html
# TO: index.php?year=2005&monthnum=12
#
RewriteRule ^adam/([0-9]{4})/([0-9]{1,2})/index.html$ /index.php?year=$1&monthnum=$2 [QSA,L]

The next rule makes sure the old category links are maintained too.

#
# Rewrite old category links to new location
# FROM: adam/blogging/index.html
# TO: index.php?category_name=blogging
#
RewriteRule ^adam/(.*)/index.html$ /index.php?category_name=$1 [QSA,L]

One gotcha when importing categories – TypePad uses underscores (_) to separate multiple word category names, and WordPress uses dashes (-). Version 2 of my importer should take this into account, but for now, I just changed my two multi-word categories using the WordPress admin functions.

The last custom rule was important to make sure that old feed/rss subscriptions still worked.

#
# Rewrite old RSS links to new location
# FROM: adam/atom.xml
# TO: index.php?&feed=atom
#
# FROM: adam/index.rdf
# TO: index.php?&feed=rss
#
RewriteRule ^adam/atom.xml$ /index.php?&feed=atom [QSA,L]
RewriteRule ^adam/index.rdf$ /index.php?&feed=rss [QSA,L]

These rules should all come before the default WordPress rules.

Now that all the old links are working (remember the remove-the-www and test trick I mentioned above?) I was set to make the old site live. I changed the DNS so that http://www.adamstiles.com points to the new site at adamstilesoft.com and then started watching my error logs. Those would be the first indicator of broken links. I added a favicon and a robots.txt file, but that was it – everything else (except for some Google-cache issues) worked.

The only minor irritation was that feed-readers “lost track” of which posts my subscribers has already read. That’s because the last-modified date and e-tag data from the old server was lost in the transfer. Not a big deal, and its a small one-time cost. After a few days on WordPress I have no regrets from making the switch.

Tags: , ,

Refactoring with the Pickaxe

Programming Ruby, better known as the Pickaxe, the most valuable "programming book" on my shelf. Actually, it doesn’t live on my shelf, it lives on my desk. I’ve learned and used lots of languages over the years but I never remember using a reference book like this before. Ruby is an incredibly rich language and I find myself "mining" the Pickaxe looking for cool ways to fix problems and writer shorter and more readable. Here’s an example of refactoring a simple method.

Start with a hash object called params. A hash object is just a list of name, value pairs: this1 = that1, this2 = that2, etc. I have a hash object and want to build a URL query string out of it. We need to string our variables together to get something that looks like this: this1=that1&this2=that2&this3=that3. The key are joined to values with an equals sign (=), and the combined values are joined with an ampersand (&).

Here was my first crack at the code.

query = ""
params.each do | key, value |
    if (query != "") query += "&"
    query += key + "=" + value
end

This works, but it seems longer than necessary. So here’s take two.

query = ""
params.each { | key, value | query += (("&" if (query != "")) || "") + key + ‘=’ + value }

This code works, buts its not very readable. I wonder if there isn’t some cool Ruby method that help us clean this up. Thumbing through Pickaxe, we find that the Hash object mixes-in Enumerable, which has a method called collect that should make things easier. Hash::collect iterates over a hash, processes each item according to a block, and returns a new array – perfect. Let’s use collect to create a new array of keys joined to their values with the equals sign. After that, we can use the Array::join to join the tuples with the ampersand.

tuples = params.collect do | key, value |
  key + "=" + value
end
return tuples.join("&")

This can be shortened…

tuples = params.collect{ | key, value | key + "=" + value }
return tuples.join("&")

… or even shorter, and I think just as readable …

params.collect{ | key, value | key + "=" + value }.join("&")

Tags: ,

No More TV Shows

Here’s a great post at Creating Passionate Users on killing the television, keeping the shows. Kathy writes about being "off tv" for more than 5 years. Being "off tv" means not watching live TV shows, but still watching DVDs or Tivo’d stuff. She’s got some great stuff about addiction patterns and the effect of the watch-lots-of-live-tv lifestyle on your brain.

Nancy and I killed our satellite TV subscription a couple of months ago. We have a Blockbuster Online subscription (works like Netflix) so we can rent DVDs by mail and use coupons at our local store too. We haven’t tried to tune in local channels. I’m surprised at how easy the transition was. I thought I’d miss the weekly dramas/reality TV shows like Lost, Survivor, The Amazing Race, etc. The kids missed not having the Disney Channel, but only for a few days. But really, its been a very easy, and the monthly savings is nice too. Our evenings are freer – or will be after soccer season is over. The only time I’ve really missed TV is during a couple of recent UCLA football games. Tracking last minute, come-from-behind-victories via ESPN Gamecast just isn’t the same. I’ll definitely find a place to watch UCLA-USC this year.

Apply the try-before-you-buy algorithm to this. Turn off your tv for two weeks and see how it goes. You might be surprised.

Long Beach Marathon – I Did It

I finished the Long Beach Marathon yesterday! It was a long day, and my final time was quite a bit slower than I had project based on my long training runs (18, 20, and 22, etc) but the important thing is that I finished.

This marks the end of a long journey for me. Eight years ago I started training to run a marathon with my dad (many time finisher at Big Sur International) but I developed achilles tendinitis once I reached 13 mile training runs. The best way to heal AT is to rest, so I put those plans on hold to try again later. I’m not sure how many times I’ve started this process (probably 5 or 6), but I’ve had to put off my plans many times. Four years ago I completed the Long Beach HALF marathon but still wasn’t able to progress beyond that distance.

26miles_1This time I planned out a 6 month training program and was able to stick to it the whole way. After a number of "failures", I feel very blessed to have accomplished this goal. really good shoes helped.  Along the way I listened to countless hours of podcasts, sermons, speeches, and music on my iPod mini, and it helped to carry me through the race as well.

A few race memories: a half a Hooah bar at mile 10 tasted great and provided much-needed boost; a Team-in-Training coach named Jimmy who was very encouraging, even though I wasn’t part of his program; a thunder and lightning storm that cleared in time for the race to start; and the best one – finishing the race with my parents and family cheering me on. And thanks to my sweet wife Nancy for supporting me along the way, and to all the volunteers who made the race possible!

Now I need a new goal…

No Scanning with Google Reader

My test of Google Reader only lasted a day. Serious RSS readers will find fundamental usability problems with the GR approach.

I currently use FeedDemon to monitor 61 RSS feeds. I don’t have the time or desire to read 61 feeds worth of posts every day, so I scan headlines, read the posts I want, and mark the rest as "read" so I don’t have to see them again. FeedDemon makes this "river of news" approach to RSS reading very easy with its surfer style. I don’t need a feed reader, I need a feed scanner. A client that makes me "read" all posts is far too restrictive. And that’s the problem with Google Reader.

Google Reader makes me read every post before it gets marked as "read" and sent to the bit-dumpster. An email client that made you read all your spam before you could delete it would drive you bonkers, but that’s exactly what GR is doing here.

I had hoped that GR would fulfill the promise of fast-feed-access-from-any-networked-computer in the same way Gmail has for email.  But I’ve also known FeedDemon’s author Nick Bradbury for years. You won’t meet a
nicer guy or a better software developer/designer. It felt sorta treasonous to consider a switch away from FeedDemon. Lucky for me I won’t have to deal with any inner-conflict because Google Reader is not an option at this point.

Google Reader might work well for users who are just getting started with RSS but it is far too restrictive for anyone scanning more than a handful of feeds everyday.

Posted in RSS