EN / ZH
Hexo: A Fresh Take on Independent Blogging

Hexo — this supremely cool way for programmers to write — I love it. Even the name “Hexo” sounds like “hacker-o”! If you’re as torn as I am about where to blog, come join us on GitHub and let’s hexo! I’m sure Hexo will catch on quickly.

Hexo was created by Taiwanese university student @tommy351. It’s a static blog framework based on Node.js that can compile hundreds of posts in mere seconds. The static pages Hexo generates can be deployed directly to GitHub Pages, BAE, SAE, and other platforms. First, let’s see how tommy vented about Octopress — Hexo Makes Its Grand Entrance.

The setup process may feel a tad tedious, but once it’s done, writing articles is extremely simple and comfortable.

With just a few simple commands, you can handle everything.

hexo n #new post
hexo g #generate
hexo d #deploy # can be combined with hexo g as: hexo d -g

Let’s dive into the details.

Environment Setup

Install Node

Go to the Node.js website and download the latest version for your platform. Installation is straightforward.

Install Git

There are many Git clients available. Just download from the official site. For detailed instructions, check this article: Building an Independent Blog with GitHub Pages

Install Sublime (Optional)

Sublime Text is used here simply as a text editor. It supports all kinds of programming languages and file formats, including Markdown syntax — a truly exceptional coding companion.

Using GitHub

  • First, register a GitHub account (skip if you already have one)
  • Create a repository matching your username: “your_user_name.github.com”
  • Add your SSH public key at “Account settings -> SSH Keys -> Add SSH Key”

Skipping the first two steps, let’s focus on step three: adding the SSH key.
First, set your username and email:

git config --global user.email "your email"
git config --global user.name "your username"

Generate the key:

ssh-keygen -t rsa -C "your email"

# Enter file path:
H:\hexo\blog>ssh-keygen -t rsa -C "xxxxx@xxxx.com (your email)"
Generating public/private rsa key pair.
Enter file in which to save the key (//.ssh/id_rsa): H:\git\myssh\ssh
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in H:\git\myssh\ssh.
Your public key has been saved in H:\git\myssh\ssh.pub.
The key fingerprint is:
b0:0c:2e:67:33:ab:c1:50:10:40:0a:ba:c1:80:59:22 xiaowu@aips.me

Note: there’s a bug where the drive letter H in the file path must be uppercase, otherwise you’ll get an error. If the above commands succeed, two files — id_rsa and id_rsa.pub — will be generated in H:\git\myssh. The final two steps:

  • Open ssh.pub with a text editor, copy the contents, and add them at Add SSH Key
  • Copy id_rsa and id_rsa.pub to the .ssh directory under your Git installation, e.g., H:\PortableGit-1.8.4\.ssh

Verify with:

ssh -T git@github.com

If there are issues, reconfigure. Common errors can be found at:
GitHub Help - Generating SSH Keys
GitHub Help - Error Permission denied (publickey)

Install Hexo

With Node and Git installed, run the following to install Hexo:

npm install -g hexo

Initialization

Run the init command to initialize Hexo in your target directory:

hexo init

You can also cd into the target directory and run hexo init. And that’s it — installation is complete.

Generate Static Pages

Navigate to your init directory and run the following to generate static pages into the hexo\public\ directory:

hexo generate

Note: The command must be run in the init directory. It won’t work otherwise, but it also won’t show any errors.

If modifying article tags or content doesn’t regenerate correctly, try deleting hexo\db.json and retrying. If that doesn’t work, delete the corresponding files in the public directory and regenerate.

Local Preview

Run the following to start a local server for previewing and debugging:

hexo server

Open http://localhost:4000 in your browser to see your Hexo blog.

Writing Articles

Run the new command to create an article at hexo\source\_posts\postName.md. The simplest way is to just create a new Markdown file directly in the Hexo local directory.

hexo new [layout] "postName" #new article

The layout parameter is optional, defaulting to post. Check the scaffolds directory for available layouts — filenames are layout names. You can add your own layouts by creating new files. You can also edit existing layouts, like the post layout at hexo\scaffolds\post.md:

title: {{ title }}
date: {{ date }}
tags:
---

To add categories automatically, just modify this file to add a line:

title: {{ title }}
date: {{ date }}
categories:
tags:
---

The postName is both the md filename and part of the article URL. If it contains spaces, wrap it in quotes. Chinese characters are supported.

Note: All fields must have a space after the colon, otherwise you’ll get errors.

Here’s what the generated file hexo\source\_posts\postName.md looks like:

title: postName #Display name on the article page, freely editable, won't appear in URL
date: 2014-05-16 15:30:16 #Generation time, usually unchanged but editable
categories: #Article category, can be empty. Note: space after the colon
tags: #Article tags, can be empty. For multiple tags use [tag1,tag2,tag3]. Note: space after colon
---
Start writing your content in markdown here.

Now you can write your articles in your favorite editor. For Markdown syntax, refer to the Markdown Syntax Guide.

fancybox

You might be interested in the fancybox effect on the Reading page. Just add a photos field to your article’s .md header and list the photos line by line:

layout: photo
title: My Reading Journey
date: 2085-01-16 07:33:44
tags: [hexo]
photos:
- http://cdn.imzl.com/2013/11/27/reading/photos-0.jpg
- http://cdn.imzl.com/2013/11/27/reading/photos-1.jpg

Don’t want to add this manually each time? Open hexo\scaffolds\photo.md:

layout: { { layout } }
title: { { title } }
date: { { date } }
tags:
photos:
-
---

Then generate photo articles with the layout parameter:

hexo new photo "photoPostName" #new photo article

description

You can also add a description field in the Markdown header to override the global description in _config.yml:

title: hexo your blog
date: 2013-11-22 17:11:54
categories: default
tags: [hexo]
description: Your description for this page
---

Hexo processes all Markdown and HTML files by default. To exclude a file, add layout: false to the header.

Article Excerpts

Add the following where you want the excerpt to end:

Above is the excerpt
<!--more-->
Below is the full text

Content above “more” shows as the excerpt on the homepage. Content below only appears when clicking “Read More.”

Note: All files in Hexo use UTF-8 encoding.

Theme Installation

Everyone has their own taste — swapping themes is a blogging essential. Check out the Hexo Themes list.

My favorites are pacman, modernist, ishgo, and raytaylorism. Pacman is the most polished — clean, fresh, with great mobile support. However, the author didn’t expose many configurable parameters. I ultimately chose modernist.

Install themes with a single git command:

git clone https://github.com/heroicyang/hexo-theme-modernist.git themes/modernist

The directory name doesn’t matter as long as it matches _config.yml.

After installation, open hexo\_config.yml and set the theme to modernist:

theme: modernist

Open hexo\themes\modernist and edit the theme config _config.yml:

menu: #Configure which menus appear in the header
# Home: /
Archives: /archives
Reading: /reading
About: /about
# Guestbook: /about

excerpt_link: Read More #Excerpt link text
archive_yearly: false #Archive by year

widgets: #Configure footer widgets
- category
# - tag
- tagcloud
- recent_posts
# - blogroll

blogrolls: #Blogroll links
- bruce sha's duapp wordpress: http://ibruce.duapp.com
- bruce sha's javaeye: http://buru.iteye.com
- bruce sha's oschina blog: http://my.oschina.net/buru
- bruce sha's baidu space: http://hi.baidu.com/iburu

fancybox: true #Enable fancybox effect

duoshuo_shortname: buru #Duoshuo account

google_analytics:
rss:

Update the theme:

cd themes/modernist
git pull

Comment System

Static blogs need third-party comment systems. Hexo comes with Disqus integration by default, but for well-known reasons, Duoshuo is recommended for Chinese users.

Log into Duoshuo using your Weibo/Douban/Renren/Baidu/Kaixin account and configure the basics. With the modernist theme, set duoshuo_shortname in modernist_config.yml to your Duoshuo shortname. You can also customize the comment box format in Duoshuo’s backend. For CSS settings, refer to this. My setup is based on HeroicYang’s with modifications.

For other third-party comment systems, paste the universal code into hexo/themes/modernist/layout/_partial/comment.ejs:

<% if (config.disqus_shortname && page.comments){ %>

<section id="comment">#Your universal code here
<% } %>

Custom Pages

Run the new page command:

hexo new page "about"

An about directory will be created in hexo\source\ containing index.md. Edit it directly, then configure it to display in the theme’s _config.yml.
This can also be done manually — creating about.md and index.md in hexo\source\ works identically.

Since Markdown doesn’t handle tables well, I build my about page with index.html directly, writing HTML content. Hexo adds the header and footer automatically.

404 Page

GitHub Pages makes custom 404 pages very easy — just create a 404.html in the root directory. However, custom 404 pages only work with custom top-level domains bound to the project. GitHub’s default subdomain and hexo server local debugging won’t trigger them.

Your 404 page can serve a greater purpose — consider a public welfare 404 project. Current charity 404 integration URLs include (I chose Tencent’s):

Image Hosting

For blog speed and easier migration, image hosting is essential. I strongly recommend Qiniu Cloud Storage — blazing fast access with logging, hotlink protection, and watermarks.

The free tier includes 10GB monthly traffic + 10GB total space + 100K PUT/DELETE requests + 1M GET requests per month — more than enough for a personal blog. Qiniu doesn’t have directories, but filenames can contain /, e.g., 2013/11/27/reading/photos-0.jpg. See About Key-Value Storage Systems.

If you’re not happy with Qiniu’s web file management interface, try the official Qiniu Cloud Storage Tools.

Custom Domain (Optional)

GitHub Pages assigns each user a subdomain: your_user_name.github.com or your_user_name.github.iodetails here.

If that doesn’t satisfy you, register your own domain and bind it to GitHub Pages. Binding is simple: create a CNAME file in the repo root containing just your domain name.

Commands

Common commands:

hexo new "postName" #New article
hexo new page "pageName" #New page
hexo generate #Generate static pages to public directory
hexo server #Start preview server (default port 4000, 'ctrl + c' to stop)
hexo deploy #Deploy .deploy directory to GitHub

Common compound commands:

hexo deploy -g
hexo server -g

Shorthand:

hexo n == hexo new
hexo g == hexo generate
hexo s == hexo server
hexo d == hexo deploy

That covers the basics. Now go write!