If you want to be in full control of your site, static site generators are great!
If you enjoyed this story, please click the 👏 button and share to help others find it! Feel free to leave a comment below.
In this article I am talking about how to get going with one of the many flavors of static content frameworks there are, namely Hexo. I will show you how to get started with Netlify and then explain how you can use Firebase instead and what additional features Firebase has to offer that come in very handy. I will not praise one over the other though, instead I will tell you exactly what to look after if you go for Firebase. The nature of static site content is that it “runs” on everything that serves websites, so feel free to pick any deployment destination instead. AWS Amplify Console is something to look at.
There are good reasons to blog with Hexo. On the other hand, you have to master a steep learning curve and the tool is not for everybody. Certainly not for a mix of creative content editors and developers for sure, for example.
In many cases, in particular if you are dealing with “simple” landing page requirements, you may use either a paid service like landerapp or just work on top of a professional looking bootstrap theme.
If you decide you should have a sophisticated blogging system with full programmatic control and working based entirely on static content then follow me through a series of steps. Note — it really only makes sense if you keep producing content and use Hexo as a blog. A “one-pager” would be overkill for sure.
Without any further due, what is covered in this document:
1) Use Hexo via Netlify
2) Use Hexo to deploy on Firebase Hosting instead
3) Use this Hexo Plugin to generate AMP pages
4) Use a Hexo Plugin to generate a XML site-map
5) If you serve images via Hexo use this module
6) Minify everything
There are similarities but differences, too.
1) Optional: Netlify + Hexo
Let us say all your blog contents are in a directory named /superblog on your dev machine.
So here is how you can set up a Hexo blog (/superblog folder):
It was all done following more or less this tutorial from Netlify: https://www.netlify.com/blog/2015/10/26/a-step-by-step-guide-hexo-on-netlify/
First of all, install hexo globally:
npm install hexo-cli -g
In case hexo is not available globally thereafter, do this cleanup:
rm -rf node_modules/ && npm install (For context: that was necessary because just installing hexo-cli globally would not instantly work, see as well https://github.com/hexojs/hexo/issues/2076)
Then it’s time for some hexo magic, compare as well to this page: http://jr0cket.co.uk/2016/06/blogging-for-developers-with-hexo.html:
hexo init
Run the site, using a different port (more on that: https://hexo.io/docs/server.html), note that Cloud9 serves only specific ports publically:
hexo server -p 8080
This will create all the hexo files needed.
Now let us push it all to GITHUB (https://github.com/xxx/site.git) and therefore have Netlify build the site in parallel — because Netlify is connected to exactly this GIT repository and will receive a GIT event:
git init
git remote add origin https://github.com/xxx/site.git
git config credential.helper store
git add .
git commit -am “something clever”
Optional: git push -f (to force overwriting files on GitHub)
How to create a new blog post now?
hexo new “blog post title”
(That will create a new file at superblog/source/_posts).
Now it is just about editing the new file. You can test it locally with the hexo server command, by pushing it all back to GitHub it end up with Netlify:
git add .
git commit -am “ehem ehem”
git push
As mentioned earlier, Netlify will automatically pick up the changes and do its magic.
But don’t take my word for it and visit:
https://<yournetlifyapp>.netlify.com/
You should extend the Netlify build command like this to avoid build errors:
hexo clean && hexo generate
What about pictures or any static documents like PDFs, where to host that?
Two options:
A) You host it on highly scalable storage services that will do a great job of dealing with static assets. AWS S3, Azure Blob Storage, Google Cloud Bucket. They’re all great.
B) You host assets, in particular pictures, along with the other static elements on your web host, like in this case Netlify. (Later on we’ll talk about deploying everything to Firebase instead.)
A is the best choice from a clean architecture perspective with clear separation of concerns.
B is the better pramgatic choice, because the Hexo plugins can take care of creating different renditions of pictures for different form factors for you and you don’t have to do anything else.
A+B can of course be married up with a little bit of extra-effort. It’s up to you, really.
BUT WHAT NOW?
Probably you want to change the theme (https://hexo.io/themes/) as the default theme is not really grand.
The one taken for my little blog was ICARUS, and in the rest of the document I will reference it: https://github.com/ppoffice/hexo-theme-icarus/wiki
(An even nicer one I found in the meantime is the Phantom theme.)
There are some additions you can add to the website like this one, to extend the on-site search functionality: https://github.com/artchen/hexo-azuresearch
NOTE: Breaking GIT structures:
If you just clone a theme into your site folder you will see GIT go wildfire with “unstaged commits” and ignoring your GIT adds altogether.
The reason is that git clone copies a .git folder into your subdir which is another git checkout point — messing around with your GIT sync altogether.
Find these files:
find themes/*.git*
Just delete the entire .git folder and the .gitignore too in that theme folder.
Run then from your site root git add *, then git commit -am “whatever” and go: git push.
HOW TO WRITE BLOG PAGES IN MARKDOWN
https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet
Create a new Hexo post via the CLI:
hexo new blog post title (which can have spaces!)
Something to bear in mind is that the so called “permalinks” can be configured. These are the links that are constructed based on the name of a blog article for example. In other terms, the “headline URLs” for your website pages. In fact is highly advisable to change these links to make them pretty and meaningful.
An example for a solid permalink pattern could be something like this:
:year/:month/:day/:post_title/
The post_title here is the title in the header of your .md file. Which is much better than :title which would use the file name.
2) Recommended: Hexo + deployment on Firebase Hosting
Firebase is high-performing and comes with CDN and free custom SSL. Plenty of reasons to have your static site on Firebase.
Consider, though:
- Downside with Firebase, from 10 GB transfer on you have to start paying for the hosting — at some point, with a very popular site, a migration could be economically a wise move. In any way will need to be evaluated.
- You can have like 440k (non-cached) page downloads roughly for $132 flexible pricing on Firebase Hosting
- Pro-Tip: Try combining Firebase with CloudFlare for cost optimization — CloudFlare has a generous free tier and might take away the biggest hit.
Dealing with the hexo CLI remains the same, however the code push does not happen via GIT per default.
Here is how it would work instead, now assuming again that the contents of the blog reside in folder /superblog of your dev machine:
First things first: For this to work, the Firebase CLI has to be installed and you have to be authenticated.
Go the folder where you want to start deployments from, which does not have to be the “Firebase public” root folder but can be wherever you want.
Hit firebase init there — and then you will be guided to select the Hosting project to associate with.
The result of this will be a firebase.json file. You will probably have to do some changes to it, see https://firebase.google.com/docs/hosting/full-config.
A typical firebase.json looks like this:
{“hosting”: {
“public”: “public”,
“ignore”: [“firebase.json”, “**/.*”, “**/node_modules/**”],
“headers”: [{
“source”: “**”,
“headers”: [{
“key”: “Cache-Control”,
“value”: “max-age=960000”
}]},{
“source”: “404.html”,
“headers”: [{
“key”: “Cache-Control”,
“value”: “max-age=960000”
}]},{
“source”: “**/*.@(eot|otf|ttf|ttc|woff|font.css)”,
“headers”: [{
“key”: “Access-Control-Allow-Origin”,
“value”: “*”
}]}],
“rewrites”: [{
“source”: “**”,
“destination”: “/index.html”
}],
“cleanUrls”: true,
“trailingSlash”: false
}}
If you initiated in the directory that represents the Firebase public directory then just use “.” for the public property.
There is quite some configuration that Firebase JSON up there. Read on https://firebase.google.com/docs/hosting/full-config what it all means, basically it is setting cache headers and instructing on whether to allow trailing slashes and things like that. Very useful stuff — you can configure rewrites here as well.
OKAY ENOUGH OF THAT, HOW DO I DEPLOY MY HEXO NOW?
Just change to the public output directory of Hexo and hit:
firebase deploy
You will have to make sure the public directory is up to date, meaning you will have to have at least run
hexo generate
And if you want to be sure to have it all clean then
hexo clean && hexo generate
Now back to how the hosting is configured with Firebase for this little hosting project:
It’s configured with the Hosting project xxx you defined in Firebase, hence the URL:
Look it all up in the Firebase console/portal: https://console.firebase.google.com/
3) AMP Pages with HexoFirst, get this plugin for Hexo
https://www.npmjs.com/package/hexo-generator-amp
Useful in this context is this article explaining how the server would know about an AMP version of your page:
https://stackoverflow.com/questions/37103814/how-does-the-server-know-when-to-serve-an-amp-page
Deviating from the tutorial provided on the npmjs package description, I had to do take the steps as follow instead.
a) Fix “could not generate content.json”:
I was able to fix that annoying error like this:
npm install hexo-generator-json-content@1 — save (which uses version 1 only and downloads it updating package.json as well)
b) Changing head.ejs — but somewhere else!
Then edit the file “head.ejs” in my icarus theme directory, like it says on the npm how-2 — only that this file is not under (..)/_partial but themes/icarus/layout/common!
In head.ejs I pasted this jade snippet right before the first <link rel> starts:
<% if (is_post() && config.generator_amp){ %>
<link rel=”amphtml” href=”<%= config.url %>/<%= page.path %>amp/index.html”>
<% } %>
(The config.url in your page _config.yml file needs to be correctly set, otherwise the URL will be malformed!)
Run the test server and check whether the content is valid AMP via this site:
https://validator.ampproject.org/
Your AMP urls would look like this:
http://<site>/2017/06/25/life/amp/
And is it indexed yet?
All of this is useless if your page is not indexed.
You can check it out like so: https://www.google.com/search?q=site:https://mysite.com
Generally speaking you could check the indexing+processing of your AMP pages via the webmaster tools: https://www.google.com/webmasters/tools/accelerated-mobile-pages
Changing the Google Analytics tracking
There is a tracking bit out of the box. Touch it by going via the .ejs template. Search under themes/landscape/layout where your installed theme is installed, for example icarus. The template used would be named google-analytics.ejs.
Adding any other custom JavaScript/HTML
Go to the content template files like article.ejs in <theme>/layout/common and insert whatever is common to that content type (article) in there. I inserted for example a FB Chat on-page.
More details in this nice blog post.
Note that the Facebook Chat experience on mobile web is poor. If that is a concern, then consider placing a link to a FB Messenger Bot (channel). As that would be way to go if you want to route all users to your FB chat.
4) XML-Sitemap for your Hexo site
There is a plugin for that. You want to use it as AMP versions of your pages is one thing, more importantly search engines need to be easily able to crawl your site contents and that is where the XML sitemap is good. It’s no silverbullet however.
As it says there: https://github.com/hexojs/hexo-generator-sitemap
…install it directly via NPM:
npm install hexo-generator-sitemap –save
Beware — the version of Hexo you use matters.
A simple entry like this is enough in the _config.yml, no need to specify a template unless you want to:
sitemap:
path: sitemap.xml
It might be worth manually adding that file to the Google Search Console. The challenge here is that the general recommendation for XML sitemaps is to only put in pages there that are useful to Google Search, so no “utility pages”. In fact the same goes for robots.txt. You can spend quite some time on fine-tuning these things. Welcome to the world of SEO!
5) Use this module if you serve images via Hexo
Otherwise you will serve high-res pictures to each and everybody.
https://www.npmjs.com/package/hexo-image-sizes
Actually, hosting images with the rest of the Hexo webpage code is not a bad idea because it makes it very easy to auto-generate different renditions of the images. If you link out to e.g. a picture on S3 then it will always be that picture, no matter if viewed on mobile or Desktop for example.
Another good way of dealing with this is serving small images and linking out to high-res pictures which could sit anywhere. These pictures would at least not interfere with the page load as big images inevitably will.
6) Always minify everything — automatically
This module as follow will reduce the size of CSS and JS as part of the build-up. What it does not do however is bundling JS and CSS into few files altogether.
https://www.npmjs.com/package/hexo-filter-cleanup
Last but not least, do some basic performance check
Whatever you do, better check the final hosted site with the typical google tools like https://developers.google.com/speed/pagespeed/insights/
…or, very similar in fact:
https://testmysite.withgoogle.com/intl/en-gb
Go go go!
And then make the world hear about your great product, of course. This article summarizes neatly what you should be doing right away. Technically you have done all the bare minimum, doing the marketing around your site is now the next big challenge.
https://blog.kissmetrics.com/get-google-to-index/
Appendix
Meta-Tags
As far as SEO support goes, would Hexo add at least appropriate Meta Tags? Yes, in fact plenty. Here is how you would influence the generated meta-tags: https://stackoverflow.com/questions/44168115/how-do-you-override-generated-meta-tags.
Only know that meta-tags are overrated for SEO in general as it appears.
Interested in DNS flattening? Check this out.