Migrating imakewebsites.ca to Hexo

Today I migrated http://imakewebsites.ca from a home-made PHP and MySQL CMS to the Hexo static blogging engine. Moving content over was easy, but it took some time to rebuild my theme and figure out a few quirks when using Hexo for a site without a blog component.

Why migrate?

I rarely update imakewebsites.ca, so moving it to static hosting makes life easier and takes a microscopic amount of load off the web server. I also want to learn what working with Hexo is like.


Like WordPress, Hexo supports pages, which are like blog posts but without chronological order and their own template. Hiding the blog related functionality by removing links the template engine was easy, but I discovered you must have at least 1 blog post in a site, otherwise the site’s homepage (index.html) will not render. I had to keep a dummy blog post in the site which is an orphaned page (no links to it)

Preserving URLs from my custom site was easy. I ended up with a directory structure like this:

public │ .htaccess │ favicon.ico │ index.html │ ├───2015 | (hidden dummy blog posts) │ ├───404 │ index.html │ ├───archives │ (hidden dummy blog posts) │ ├───contact │ (contact specific images) │ index.html │ ├───css │ style.css | ├───free-zen-cart-templates │ (template specific images and files) │ index.html │ ├───img │ (images used all over the site) │ ├───making-downloadable-products | (tutorial specific images and files) │ index.html │ ├───portfolio │ (portfolio specific images used on the homepage) │ └───zen-cart-layouts (tutorial specific images) index.html

I moved my page specific images out of a general /images folder and into the folder associated with each page. The content of each page is in each index.html, but browsers won’t need to show that in the URL. The folder names match the names of my old pages from the CMS.

It would be nice to disable the archive and blog page generation entirely, but their overhead is tiny so it isn’t a big problem.

Rendering HTML

Hexo encourages you to write content in Markdown. However, I already wrote content for the site in HTML. If you supply blog posts and page content with a .html extension, Hexo will use it and not run it through any sort of generator. Your raw HTML gets integrated into the site smoothly.

Moving the theme

I took the included Landscape theme and overwrote its HTML with content from my own site. I removed code for some blogging features. EJS Package for Sublime Text came in very handy for editing the theme’s files.

Deployment Process

hexo-deploy-ftpsync looks like is being smart and only uploading files that have changed, but I haven’t confirmed that yet. I wish I didn’t have to save my FTP name and password inside _config.yml to use it.

The fun part is when I make changes to the site, I can generate the new /public directory of the project and deploy with one terminal command:

hexo generate && hexo deploy

I like that!

WordPress to Hexo?

Matias presented a static blog generator called Hexo with some Angular addons to the AngularJS Meetup. I liked what I saw, so I set up my own install and imported my posts with the WordPress migrator. The transfer went smoother than with Ghost.. Moving text content over worked OK, although I loose some cool video and oembed features of WordPress. Moving images over will take more effort.

Having a static site is appealing, but I think I would miss having a place online to write posts. There is an admin plugin, but maybe using GitHub as a writing environment would be good. I could set up a post-commit webhook that tells a hosted version of Hexo somewhere (Heroku?) to build and deploy the site somewhere else.

Broken link checker plugins are helpful – I use one with WordPress already. Here’s a broken link checker for Hexo.

ngToronto Angular Meetup notes – January 2015

Promise-based architecture by Yuri


  • think of promises as wrappers around uncertain results
  • promises separate defining a request and response handler (callback) at the same time.
  • writing functions that accept promises as arguments and return promises, you can make something that almost looks like synchronous code

Check the table in the presentation for useful definitions of promise behaviour (“when the callback…”)

Avoid $q.defer, Denodify instead

Trivial Promises

  • $q.when(x) returns an ok promise
  • $q.reject(e) returns a rejected promise

Stay consistent

  • functions should never ‘sometimes’ return a promise. Always return a promise, or never return a promise. See $q.when and $q.reject
  • return a promise if you aren’t sure whether code will eventually be async or not async

Avoid Optimistic Code

  • optimistic code is code where you assume that data will eventually be loaded
  • ask for a promise instead, even if you think the data loaded already

Neat things with promises

Hexo + AngularJS by Matias

Slides and Code

Hexo is:

Static sites are good because:

  • Host on AWS S3 (cheap and fast) and CloudFlare (even faster!)
  • You get a local copy of your site that’s always up to date by default. Your writing happens locally, and is saved in version control

Hexo is good because:

  • Hexo rebuilds pages and sites quickly, hexo server command watches for content changes and live-reloads them in your browser while you are writing posts
  • posts are written in markdown with a small YAML header
  • your content can live as files in a Git repo, and custom theme in another Git repo (possibly a private repo)
  • templates use common js templating formats – ejs, jade
  • uses excellent tools like Warehouse.js
  • supports custom pages too (not just posts)

How do I handle dynamic behaviour without a backend?

3rd party services and more JS!

Angular idea

How about capturing all internal link clicks using an Angular directive, and replacing the default behaviour with pushstate, an AJAX call to load the requested page, and an animation to load the content into the current page? That gives you even faster page loads and room to animate content coming and going. Yearofmoo.com is doing this now.

AngularJS Service Architecture

Wednesday, Jan 28, 2015, 7:00 PM

Mozilla Community Space
366 Adelaide St. W, Suite 500 Toronto, ON

180 Members Went

Join us for the first AngularJS Toronto meetup of 2015! Mozilla will host us and Cetaris & rangle.io will provide beer and pizza.First Talk: Promise Based Architecture – Yuri Takhteyev CTO of rangle.io  (@qaramazov)Yuri is a former faculty member at the University of Toronto, and a published author, whose interests span software architecture and …

Check out this Meetup →