0%

How To Build This Blog

Overview

Welcome to my blog! In this my very first post, I will record my experience of building this blog with the help of Github Pages and the amazing Hexo! This not only keeps a record of what I did, but also may help those who want to build a personal blog site.

Static sites can be hosted anywhere and are fast to serve and easy to cache. Github Pages offers a very fast way to host your site and Hexo is a static blogging framework built on Node.js. Using Hexo, you can publish Markdown documents in the form of blog posts. Blog posts and content are processed and converted into HTML/CSS, which is sourced from the default or custom template theme files. All of the software in Hexo is modular, so you can install and set up exactly what you need.

Ok, let’s get down to the business.

Install

Installing Hexo is quite easy. However, you do need to have a couple of other things installed first:
Git
Node.js
If your computer already has these, congratulations! Just install Hexo with npm:

$ npm install -g hexo-cli

If not, please follow the following instructions to install all the requirements.

Git

Windows: Download & install Git.
Mac: Install it with Homebrew, MacPorts or installer.
Linux (Ubuntu, Debian): sudo apt-get install git-core
Linux (Fedora, Red Hat, CentOS): sudo yum install git-core

Node.js

The best way to install Node.js is with Node Version Manager.
To install or update nvm, you can use the install script using cURL:

$ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash

or Wget:

$ wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash

Once nvm is installed, restart the terminal and run the following command to install Node.js:

$ nvm install stable

Alternatively, download and run the installer.

Hexo

Once all the requirements are installed, you can install Hexo with npm:

$ npm install -g hexo-cli

Strongly recommend you to read Hexo’s Docs. before setting up your own blog, since the official documentation is written in detial that you can follow it step-by-step. Here I will just write down some essential setting.

Initialize

Once Hexo is installed, run the following commands to initialise Hexo in the target <folder>.

1
2
3
$ hexo init <folder>
$ cd <folder>
$ npm install

If <folder> is not specified, Hexo will create the project in the current working directory.

Writing

$ hexo new post [your-post-title]

Will find a new post is created in ../source/_posts. All posts created by hexo is written in Markdown.

Generating

$ hexo generate

This will create a /public folder in the root of your project, and it contains all static html, css, js, fonts, images, etc.

Server

$ hexo server

Your website will run at http://localhost:4000 by default. When the server is running, Hexo will watch for file changes and update automatically so it’s not necessary to manually restart the server.

Deployment

Hexo provides many ways to deploy the website to your real server. You only need one single command to deploy your site to your servers.

$ npm install hexo-deployer-git --save
$ hexo deploy

Before your first deployment, you will have to modify some settings in _config.yml. A valid deployment setting must have a type field. For example:

1
2
deploy:
type: git

You can use multiple deployers. Hexo will execute each deployer in order.

1
2
3
4
5
deploy:
- type: git
repo:
- type: heroku
repo:

Git

See Git Pages for full guideline.

Create a repository

Head over to GitHub and create a new repository named username.github.io, where username is your username (or organization name) on GitHub.

If the first part of the repository doesn’t exactly match your username, it won’t work, so make sure to get it right.

Next, deploy a SSH key to this repository.

Git deploy strategy for Hexo

Install hexo-deployer-git.

$ npm install hexo-deployer-git --save

After that, edit deploy config in your _config.yml (located in project root).

1
2
3
4
5
deploy:
type: git
repo: <repository url>
branch: master
message: "Site updated: {{ now('YYYY-MM-DD HH:mm:ss') }}"

Then, deploy website to git repository

$ hexo deploy

Finally! Browse https://[your-github-username].github.io/ and enjoy your flight with Hexo!

Netlify

Netlify provides continuous deployment (Git-triggered builds), an intelligent global CDN, full DNS (including custom domains), automated HTTPS, asset acceleration, and a lot more. It is a unified platform that automates your code to create high-performant, easily maintainable sites and web apps.

There are two different ways to deploy your sites on Netlify. The most common way is to use the web UI. Go to the create a new site page, select your project repo from GitHub, GitLab, or Bitbucket, and follow the prompts.

Alternatively, you can use Netlify’s Node based CLI tool to manage and deploy sites on Netlify without leaving your terminal.

You can also add a Deploy to Netlify Button in your README.file to allow others to create a copy of your repository and be deployed to Netlify via one click.

Theme Settings

Hexo lets you define your site information, customize date/time format, pagination behaviour, language settings, etc. Most configs are not necessary, but it will make your site look more like yours if you specify them properly. You can modify most site settings in :_config.yml or in an alternate config file.

NexT is the theme now I using, one of the most popular themes for Hexo, so it has much more customization features and plugins. And the following setting will be based on NexT. Certainly, we should read NexT Docs first.

Documentation Variables
There are two main configuration files using by Hexo and both called _config.yml:

  1. The first one is under site root directory, which contains Hexo’s config.

  2. The second one is under theme root directory, which is provided by NexT and contains theme’s config.

  3. Let’s call the first one – site config file, and the second one – theme config file.

Colorfy

Body Background

Add code to theme/next/source/css/_custom/custom.styl to modify the background.

1
2
3
4
5
6
7
8
9
10
11
12
body{   
background:<url>;
background-size:cover;
background-repeat:no-repeat;
background-attachment:fixed;
background-position:center;
}
.content {
border-radius: 10px;
margin-top: 60px;
background:rgba(0,0,0,0.2);
}

Text Color

To make sure the text colormatch well with the background color, we may need to modify it. Just open theme/next/source/css/_common/scaffolding/base.styl, find out body{}, then change the color:$text-color as you want.

1
2
3
4
5
6
7
8
9
10
11
12
body {
position: relative; // Required by scrollspy
font-family: $font-family-base;
font-size: $font-size-base;
line-height: $line-height-base;
+ color: $text-color;
background: $body-bg-color;

+mobile() { padding-right: 0 !important; }
+tablet() { padding-right: 0 !important; }
+desktop-large() { font-size: $font-size-large; }
}

Code Block Style

Inline Code

1
+ #posts code {color: <color code>;background-color: <color code>;}

Background

1
2
3
4
5
6
.header {
background:rgba(0,0,0,0);
}
.footer {
background:rgba(0,0,0,0);
}

You can also add background:<url>; to set a specific background picture.

Text Color

Site-title

Open theme/next/source/css/_common/components/header/site-meta.styl, find out .brand{}, and add code:

1
+ color: <color code>;

Open menu.styl at the same folder, find out a{}, add code:

1
+ color: <color code>;
1
+ .footer-inner {color: <color code>;}
1
2
3
4
5
6
7
#sidebar {
background:<url>;
background-size: cover;
background-position:center;
background-repeat:no-repeat;
p,span,a {color: <color code>;}
}

Layout

Page Width

1
.main-inner {width: <page width>;}

###Center Layout

Title

1
2
3
4
- .post-title,
+ .post-title{
+ text-align: center;
+ }

Meta

1
2
- $site-meta-text-align = left; 
+ $site-meta-text-align = center;

Content

1
2
3
.posts-expand .post-body {
- +desktop() { text-align: justify; }
+ +desktop() { text-align: center; }

Read-More

1
2
3
4
.post-button {
margin-top: 20px;
- text-align: left;
+ text-align: center;

Pagination

1
2
3
4
//Center page number
.pagination {
text-align: center;
}

Tags

1
2
3
.posts-expand .post-body {
- +desktop() { text-align: justify; }
+ +desktop() { text-align: center; }
1
2
3
4
5
//Center footer
.footer-inner {
margin: 0 auto;
text-align: center;
}

Customization

Siderbar avatat animation

  1. Open themes\next\layout\_partials\head.swig, add code:

    themes\next\layout\_partials\head.swig
    1
    + <link href="//cdn.bootcss.com/animate.css/3.5.0/animate.min.css" rel="stylesheet">
  2. Add code in themes\next\source\css\_common\components\sidebar\sidebar-author.styl

    1
    2
    3
    4
    .site-author-image:hover {
    -webkit-animation: pulse 1s;
    animation: pulse 1s;
    };

    Here take pulse for example, you can find more animations at Animate.css as well.

1
2
3
4
5
6
// Click the sidebar avatar to return to homepage.
+ <a href="/" class="site-author-image" rel="start" style="border:none">
<img class="site-author-image" itemprop="image"
src="{{ url_for( theme.avatar | default(theme.images + '/avatar.gif') ) }}"
alt="{{ theme.author }}" />
+ </a>
  • Add following new <div> at theme/next/layout/_macro/sideebar.swig before section <div class="links-of-author motion-element">:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <!--my custom code begin-->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.5.0/velocity.min.js"></script>
    <script type="text/javascript">
    $("#sidebar").hover(function(){
    $("#mydivshow").velocity('stop').velocity({opacity: 1});
    },function(){
    $("#mydivshow").velocity('stop').velocity({opacity: 0});
    });
    </script>
    <div id="mydivshow" class="mydivshow">
    <!--my custom code end-->
  • End <div> before section <div class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">.

    1
    2
    3
    4
    <!--my custom code begin-->
    </div>
    <!--my custom code end-->
    {% if display_toc and toc(page.content).length > 1 %}

    Form <div id="mydivshow" class="mydivshow"> to </div> is the triggered area, hence you can insert them at any section as you want.

  • Initialize setting
    Add following code at theme/next/source/css/_custom/custom.styl:

    1
    #mydivshow{opacity: 0;}

Add code in themes\next\source\css\_common\components\post\post.styl

1
2
3
4
5
6
7
8
9
10
.post-body p a{

color: #0593d3;
border-bottom: none;
&:hover {
color: #ff106c;
text-decoration: underline;
}

}

404 Page

Dos 404

Custom simple 404
Create new file 404.md in Hexo/source

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<center>
对不起,您所访问的页面不存在或者已删除。
<br/>
预计将在约 <span id="timeout">5</span> 秒后返回首页。
</center>

<blockquote class="blockquote-center">
{% btn /, Home Page, Back to home page %}
</blockquote>

<script>
let countTime = 5;

function count() {

document.getElementById('timeout').textContent = countTime;
countTime -= 1;
if(countTime === 0){
location.href = '/';
}
setTimeout(() => {
count();
}, 1000);
}

count();
</script>

Hide and Encrypt Post

hexo-hide-posts

https://github.com/prinsss/hexo-hide-posts

  1. Install
    npm install hexo-hide-posts --save
  2. Config
1
2
3
4
5
6
7
8
9
10
# hexo-hide-posts
hide_posts:
enable: true
# Change the filter name to fit your need
filter: hidden
# Generators which you want to expose all posts (include hidden ones) to.
# Common generators: index, tag, category, archive, sitemap, feed, etc.
public_generators: []
# Add "noindex" meta tag to prevent hidden posts from being indexed by search engines
noindex: true

e.g. Set filter to secret, so you can use secret: true in front-matter instead.

Note: although most of generator plugins respect a naming convention that they register generator with the name in their package names, the generator name could be arbitrary. For example, hexo-generator-searchdb does not register generators with name searchdb, but xml and json. For accurate generator name, you should check their source code.

hexo-blog-encrypt

https://github.com/D0n9X1n/hexo-blog-encrypt

  1. Install
    npm install --save hexo-blog-encrypt

  2. Encrypt TOC
    If you has a post with TOC, you should change the code of your template. Take the default theme ‘NexT’ as an example, edit themes/next/layout/_macro/sidebar.swig with the following code :

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <!--noindex-->
    <div class="post-toc-wrap sidebar-panel">
    {%- if (page.encrypt) %}
    <div id="toc-div" style="display:none">
    {%- else %}
    <div id="toc-div">
    {%- endif %}

    {%- if display_toc %}
    <div class="post-toc motion-element">{{ toc }}</div>
    {%- endif %}

    </div>
    </div>
    <!--/noindex-->

    Reference

Outdated

  1. Add code:

    1
       

... //Setup passowrd for the post. +
1
2
3
4
5
6
7
8
9
10
2. Setting scaffolds:
```diff ../scaffolds/post.md
title:
date:
comments:
categories:
copyright:
+ password:
top: 100
tags:
## Modify Valine - Change post header content Edit code in `scripts\filters\comment\valine.js`
js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Add post_meta
hexo.extend.filter.register('theme_inject', injects => {
let theme = hexo.theme.config;
if (!theme.valine.enable || !theme.valine.appid || !theme.valine.appkey) return;

injects.postMeta.raw('valine', `
{% if post.comments and (is_post() or theme.valine.comment_count) %}
<span class="post-meta-item">
+- ${iconText('far fa-comment', '评论数')}
+- <a title="" href="{{ url_for(post.path) }}#valine-comments" itemprop="discussionUrl">
<span class="post-comments-count valine-comment-count" data-xid="{{ url_for(post.path) }}" itemprop="commentCount"></span>
</a>
</span>
{% endif %}
`, {}, {}, theme.valine.post_meta_order);
});

- Hide powered by valine Add code in `themes\source\css\_mixins.styl`
1
2
3
4
// hide powered by valine
.vpower.txt-right {
display: none;
}

Dynamic Title

Cratedytitle.jsinthemes/source/js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* 离开当前页面时修改网页标题,回到当前页面时恢复原来标题 */
window.onload = function() {
var OriginTitile = document.title;
var titleTime;
document.addEventListener('visibilitychange', function() {
if(document.hidden){
$('[rel="icon"]').attr('href', "/images/favicon-32x32.png");
$('[rel="shortcut icon"]').attr('href', "/images/favicon-32x32.png");
//document.title = '(#°Д°)出BUG啦!!!';
clearTimeout(titleTime);
}
else{
$('[rel="icon"]').attr('href', "/images/favicon-32x32.png");
$('[rel="shortcut icon"]').attr('href', "/images/favicon-32x32.png");
//document.title = '♪(^∇^*)又好了. . . | ' + OriginTitile;
titleTime = setTimeout(function () {
document.title = OriginTitile;
}, 2000);
}
});
}

Add code in layout/_layout.swig

1
2
<script src="https://cdn.jsdelivr.net/gh/weilain/cdn-photo/js/jquery.min.js"></script>
<script type="text/javascript" src="/js/dytitle.js"></script>

Post Pages Label

Replace the tags label # with at the bottom of the post pages.

  • Open ../themes/next/layout/_macro/post.swig
  • Search rel="tag">#
  • Replace # with <i class="fa fa-tag"></i>

Third Party Services

##Local Search
Local search no need any external 3rd-party services and can be extra indexed by search engines. That search method recommended for most users.

Sitemap

The Sitemaps protocol allows a webmaster to inform search engines about URLs on a website that are available for crawling. A Sitemap is an XML file that lists the URLs for a site. It allows webmasters to include additional information about each URL: when it was last updated, how often it changes, and how important it is in relation to other URLs in the site. This allows search engines to crawl the site more efficiently and to find URLs that may be isolated from rest of the site’s content.

Google Sitemap:

$ npm install hexo-generator-sitemap --save

Baidu Sitemap:

  $ npm install hexo-generator-baidu-sitemap --save

Edit Site _config.yml:

1
2
3
4
5
sitemap:
path: sitemap.xml

baidusitemap:
path: baidusitemap.xml

Tag Plugins

Go to Hexo Theme Next Test for more detial.

Centered Quote

1
2
{% centerquote %}Something{% endcenterquote %}
{% cq %}Something{% endcq %}

Something

Something

Include Raw

This tag include any raw content into your posts. Path is relative to your site source directory.

Usage

1
{% include_raw '_data/path/to/file.html' %}

Example

Let’s create include-raw.html file in _data directory under site root directory with following content:

1
Any <strong>raw content</strong> may be included with this tag.

Then in any post we can use this content with include_raw tag:

1
{% include_raw '_data/path/to/include-raw.html' %}

Any raw content may be included with this tag.

Note Tag

Edit Themes config file to change Note tag style

1
2
3
4
5
6
7
8
9
10
11
12
note:
# Note tag style values:
# - simple bs-callout old alert style. Default.
# - modern bs-callout new (v2-v3) alert style.
# - flat flat callout style with background, like on Mozilla or StackOverflow.
# - disabled disable all CSS styles import of note tag.
style: flat
icons: true
border_radius: 3
# Offset lighter of background in % for modern and flat styles (modern: -12 | 12; flat: -18 | 6).
# Offset also applied to label tag variables. This option can work with disabled note tag.
light_bg_offset: 0

For emample:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
{% note %}
Header
(without define class style)
{% endnote %}

{% note default %}
Default Header
Default Text
{% endnote %}

{% note primary %}
Primary Header
Primary Text
{% endnote %}

{% note info %}
Info Header
Info Text
{% endnote %}

{% note success %}
Success Header
Success Text
{% endnote %}

{% note warning %}
Warning Header
Warning Text
{% endnote %}

{% note danger %}
Danger Header
Danger Text
{% endnote %}

{% note info no-icon %}
No icon note
Note **without** icon: `note info no-icon`
{% code %}
code block in note tag
code block in note tag
code block in note tag
{% endcode %}
{% endnote %}

Header
(without define class style)

Default Header
Default Text

Primary Header
Primary Text

Info Header
Info Text

Success Header
Success Text

Warning Header
Warning Text

Danger Header
Danger Text

No icon note
Note without icon: note info no-icon

1
2
3
code block in note tag
code block in note tag
code block in note tag

Label Tag

1
2
3
4
5
6
{% label default@default %}
{% label primary@primary %}
{% label success@success %}
{% label info@info %}
{% label warning@warning %}
{% label danger@danger %}
default primary success info warning danger

Button Tag

Tab Tag

NexT Supported Tags - Button

1
2
3
4
5
6
7
8
9
10
11
{% button url, text, icon [class], [title] %}
<!-- Tag Alias -->
{% btn url, text, icon [class], [title] %}

url : Absolute or relative path to URL.
text : Button text. Required if no icon specified.
icon : FontAwesome icon name (without 'fa-' at the begining). Required if no text specified.
[class] : FontAwesome class(es): fa-fw | fa-lg | fa-2x | fa-3x | fa-4x | fa-5x
Optional parameter.
[title] : Tooltip at mouseover.
Optional parameter.

Tab Tag

Button Tag

NexT Supported Tags - Tab

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{% tabs Unique name, [index] %}
<!-- tab [Tab caption] [@icon] -->
Any content (support inline tags too).
<!-- endtab -->
{% endtabs %}

Unique name : Unique name of tabs block tag without comma.
Will be used in #id's as prefix for each tab with their index numbers.
If there are whitespaces in name, for generate #id all whitespaces will replaced by dashes.
Only for current url of post/page must be unique!
[index] : Index number of active tab.
If not specified, first tab (1) will be selected.
If index is -1, no tab will be selected. It's will be something like spoiler.
Optional parameter.
[Tab caption] : Caption of current tab.
If not caption specified, unique name with tab index suffix will be used as caption of tab.
If not caption specified, but specified icon, caption will empty.
Optional parameter.
[@icon] : FontAwesome icon name (without 'fa-' at the begining).
Can be specified with or without space; e.g. 'Tab caption @icon' similar to 'Tab caption@icon'.
Optional parameter.

Full Image (Featured Image)

1
2
3
4
5
6
7
8
9
10
11
12
{% fullimage /url [@lazy], [alt], [title], [size] %}
<!-- Tag Alias -->
{% fi /url [@lazy], [alt], [title], [size] %}

/url : Relative path to image URL.
[@lazy] : Load image only when user scroll to it.
Dependencies: https://github.com/theme-next/theme-next-jquery-lazyload
[alt] : Alternate text (for search engines).
[title] : Tooltip at mouseover.
[size] : Size of image in any ratio (%, px, em).

All parameters except /url are optional.

Auto Center Image

1
2
3
// Auto Center Image
- .post-body img { margin: 0; }
+ .post-body img {margin: 0 auto;}

Reference:

NexT User Docs
Hexo

  • 本文链接: https://chiuhum.wang/posts/blog/
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!