Hexo + NexT Blog Maintenance Guide

This is a project-specific maintenance guide for the InterStellarAlice.github.io Hexo site. It records how the repository works as inspected on 2026-07-31. The examples marked proposed describe future changes; they have not been applied to the current configuration.

1. Project map

The site currently uses Hexo 6.0.0 and the npm-installed NexT 8.9.0 theme.

Path Purpose Edit normally?
_config.yml Main Hexo settings: site identity, URL, source/output directories, permalinks, homepage pagination, theme, and deployment Yes, but back it up and change one subject at a time
_config.next.yml NexT layout, menu, avatar, colors, dark mode, effects, PDF support, and other theme settings Yes
scaffolds/post.md Template used by hexo new post Yes
source/_posts/*.md Published Markdown posts Yes
source/_posts/Post-Slug/ Images and other files owned by Post-Slug.md Yes
source/pdf/ Site-wide PDF files Yes
source/lib/pdf/ Existing PDF.js fallback copied without rendering Only after checking PDF rendering
source/About-me/index.md About page Yes
source/tags/index.md Tags index page Yes
node_modules/ Installed packages and the installed NexT theme No; reinstalling packages can overwrite edits
db.json Hexo cache No; hexo clean recreates it
public/ Generated local website No; hexo generate recreates it
.deploy_git/ Hexo deployment cache/repository No

The themes/ directory is intentionally almost empty because NexT is loaded from node_modules/hexo-theme-next through the hexo-theme-next npm package.

2. Safe local workflow

Run commands from the blog root. Prefer the project-local Hexo version through npx; a global hexo-cli installation and sudo npm are not required.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Install exactly the versions recorded in package-lock.json when needed.
npm ci

# Delete only generated output and the Hexo cache.
npx hexo clean

# Generate the static site into public/.
npx hexo generate
# Short alias:
npx hexo g

# Preview at http://localhost:4000/.
npx hexo server
# Short alias:
npx hexo s

The generate alias is hexo g, not standalone hexo -g. In Hexo, -g is documented as an option of the deploy command. Use npx hexo g for a local-only build.

Do not run either of these unless publishing is intended:

1
2
npx hexo deploy
npx hexo d

The deployment target is currently the master branch of InterStellarAlice/InterStellarAlice.github.io. Generating and serving locally do not push anything.

3. Formatting the homepage

The homepage is assembled from site settings, NexT settings, and each post's front matter.

3.1 Site identity and post ordering

Edit these keys in _config.yml:

1
2
3
4
5
6
7
8
9
10
11
12
13
title: Yingji Zhang
subtitle: ''
description: ''
keywords:
author:
language:
- zh-CN
- en

index_generator:
path: ''
per_page: 10
order_by: -date
  • title, subtitle, description, keywords, and author provide site metadata. NexT can also display the subtitle when index_with_subtitle: true is set in _config.next.yml.
  • per_page: 10 puts ten posts on each homepage page.
  • order_by: -date places the newest dated post first.
  • The current url: http://example.com is only a placeholder and should eventually become https://interstellaralice.github.io; otherwise canonical, Open Graph, feed, and sitemap URLs are wrong.

Edit _config.next.yml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
scheme: Gemini

menu:
home: / || fa fa-home
about: /About-me/ || fa fa-user
tags: /tags/ || fa fa-tags

sidebar:
position: left
display: post

avatar:
url: /images/avatar.jpg
rounded: true
rotated: true

The active scheme is Gemini, a card-style two-column NexT layout. Available schemes are Muse, Mist, Pisces, and Gemini. Menu values use this format:

1
Label: /target/ || Font-Awesome-icon

When adding a menu page, create its source first. For example, the current tags page is source/tags/index.md and requires type: tags in its front matter.

3.3 Control each post's homepage summary

The current NexT settings are:

1
2
excerpt_description: true
read_more_btn: true

Therefore, give every post a short description in front matter:

1
description: A one-sentence summary shown on the homepage and in metadata.

For a manually chosen cutoff, put this after the introduction:

1
<!-- more -->

Keep headings hierarchical: one article title supplied by front matter, then ## for main sections and ### for subsections. NexT builds the sidebar table of contents from those headings.

4. Changing the pictures

4.1 Current picture locations

The current rendered images include:

Picture Current configured path Current source
Sidebar avatar images/avatar.jpg node_modules/hexo-theme-next/source/images/avatar.jpg
Page background /images/canvas.jpg node_modules/hexo-theme-next/source/images/canvas.jpg
16 px favicon /images/favicon-16x16-next.png NexT's package image directory
32 px favicon /images/favicon-32x32-next.png NexT's package image directory
Apple touch icon /images/apple-touch-icon-next.png NexT's package image directory
Safari pinned-tab logo /images/logo.svg NexT's package image directory

The background is enabled by a custom file inside the installed package:

1
node_modules/hexo-theme-next/source/css/_custom/styles.styl

It applies /images/canvas.jpg as a fixed, centered, cover-sized body background.

Replacing files inside node_modules works only temporarily. npm ci, npm install, or a NexT upgrade can erase those pictures and that CSS.

4.2 Proposed durable picture setup

This is the safer future structure:

1
2
3
4
5
6
7
8
9
10
source/
├── images/
│ ├── avatar.jpg
│ ├── canvas.jpg
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── apple-touch-icon.png
│ └── logo.svg
└── _data/
└── styles.styl

Files under source/images/ are copied to public/images/ and override same-named theme assets. Then point _config.next.yml at root-relative paths:

1
2
3
4
5
6
7
8
favicon:
small: /images/favicon-16x16.png
medium: /images/favicon-32x32.png
apple_touch_icon: /images/apple-touch-icon.png
safari_pinned_tab: /images/logo.svg

avatar:
url: /images/avatar.jpg

Move the background rule into source/_data/styles.styl:

1
2
3
body {
background: url('/images/canvas.jpg') center center / cover no-repeat fixed;
}

Then activate the existing custom-file hook in _config.next.yml:

1
2
custom_file_path:
style: source/_data/styles.styl

Use optimized WebP/JPEG for large backgrounds, PNG only when transparency is needed, SVG for simple logos, and meaningful dimensions to avoid layout shifts. Keep the original files outside public/; public/ is disposable.

5. Changing the color theme

NexT exposes several levels of visual customization in _config.next.yml.

5.1 Fast changes

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Whole layout family: Muse, Mist, Pisces, or Gemini.
scheme: Gemini

# Follow the operating system's dark preference when true.
darkmode: true

# Browser toolbar and NexT theme color.
theme_color:
light: '#0F77A4'
dark: '#0F77A4'

# Code colors.
codeblock:
theme:
light: default
dark: tomorrow-night

# Page-loading indicator.
pace:
enable: true
color: blue
theme: minimal

theme_color is not a complete site palette. It mainly feeds the theme/header color. Use NexT variables for link, text, background, and sidebar accents.

5.2 Proposed custom palette

Create source/_data/variables.styl:

1
2
3
4
5
6
7
8
9
10
$body-bg-color            = #f4f7fb
$body-bg-color-dark = #20242b
$content-bg-color = #ffffff
$content-bg-color-dark = #282d35
$text-color = #273142
$text-color-dark = #d8dee9
$link-color = #0f77a4
$link-hover-color = #d45b45
$selection-bg = #0f77a4
$sidebar-highlight = #0f77a4

Activate it without editing the theme package:

1
2
3
custom_file_path:
variable: source/_data/variables.styl
style: source/_data/styles.styl

Always inspect both light and dark modes, normal and hover states, code blocks, mobile layout, and text contrast before publishing a palette.

6. Adding a new article

6.1 Create the Markdown file

1
npx hexo new post "My Article Title"

The current settings create:

1
2
source/_posts/My-Article-Title.md
source/_posts/My-Article-Title/

The second path is the article's asset folder because post_asset_folder: true is enabled.

You can also create the Markdown file manually. Do not edit a generated HTML file under public/.

6.2 Front matter

Every post starts and ends its YAML front matter with exactly three hyphens:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
---
title: My Article Title
date: 2026-07-31 18:00:00
updated: 2026-07-31 18:00:00
author:
tags:
- notes
- example
categories:
- tutorials
description: A short plain-text summary for the homepage and social metadata.
lang: en
count: true
mathjax: false
comments: false
---
Property Status in this project Meaning
title Required Displayed article title
date Required in practice Publication time and current permalink date
updated Recommended Stable visible update time; otherwise filesystem modification time is used
tags Recommended One or more searchable labels
categories Optional Hierarchical topic grouping
description Strongly recommended Homepage excerpt and metadata
author Optional Overrides the site author for this post
lang Recommended for bilingual posts Changes NexT's UI strings for this page; use zh-CN or en
count Existing project convention Requests post counting where a compatible plugin supports it
mathjax Use when needed Enables or disables formula rendering for the post
comments Optional Per-post comment override
permalink Optional Gives a post a stable custom URL

YAML indentation matters. Use spaces, not tabs. Quote a value if it contains characters that YAML may interpret, especially :, #, {, or [.

6.3 Normal Markdown body

1
2
3
4
5
6
7
8
9
10
11
12
13
Opening paragraph.

<!-- more -->

## First section

Text with **bold**, *italic*, and a [link](https://example.com).

### Code example

```bash
npx hexo g
```

7. Chinese and English UI with separate Markdown folders

7.1 What the current settings do

The project already contains:

1
2
3
4
5
6
7
8
# _config.yml
language:
- zh-CN
- en
i18n_dir: :lang

# _config.next.yml
language_switcher: true

This translates NexT's interface labels, such as Home, Tags, dates, and “Read more.” It does not translate article text and does not automatically build a second, filtered homepage.

At the time of this audit, the generated homepage's selector points to /en/index.html, but that file does not exist. The current selector is therefore incomplete on the homepage.

7.2 Simple paired-post organization

For a small number of translated posts, two folders can live inside _posts:

1
2
3
4
5
source/_posts/
├── CN/
│ └── site-guide.md
└── EN/
└── site-guide.md

The folder name is for humans; Hexo uses front matter to select the UI and URL.

Chinese file:

1
2
3
4
5
6
7
---
title: 网站指南
date: 2026-07-31 18:00:00
lang: zh-CN
permalink: guides/site-guide/
description: 中文摘要。
---

English file:

1
2
3
4
5
6
7
---
title: Site Guide
date: 2026-07-31 18:00:00
lang: en
permalink: en/guides/site-guide/
description: English summary.
---

Add explicit cross-links near the top of both posts so navigation does not depend on theme behavior:

1
[中文](/guides/site-guide/) | [English](/en/guides/site-guide/)

This changes the post UI correctly, but the default index generator still mixes both languages on one homepage and does not create /en/index.html.

7.3 Proposed full two-source bilingual site

For independent CN and EN homepages, use two complete source trees and two small override configs:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
source/
├── CN/
│ ├── _posts/
│ ├── About-me/index.md
│ ├── tags/index.md
│ ├── images/
│ ├── pdf/
│ └── audio/
└── EN/
├── _posts/
├── About-me/index.md
├── tags/index.md
├── images/
├── pdf/
└── audio/

Proposed _config.cn.yml:

1
2
3
4
5
source_dir: source/CN
public_dir: public
url: https://interstellaralice.github.io
root: /
language: zh-CN

Proposed _config.en.yml:

1
2
3
4
5
source_dir: source/EN
public_dir: public/en
url: https://interstellaralice.github.io/en
root: /en/
language: en

Generate both into one deployable public/ tree. Clean only once, before both builds:

1
2
3
npx hexo clean
npx hexo generate --config _config.yml,_config.cn.yml
npx hexo generate --config _config.yml,_config.en.yml

The later config takes precedence when Hexo merges a comma-separated config list. Do not run hexo clean between the two generate commands, because that would erase the first language.

Each build has one UI language, so provide explicit links to the two homepages, for example in the menu or a custom header:

1
2
3
4
menu:
home: / || fa fa-home
中文: https://interstellaralice.github.io/ || fa fa-language
English: https://interstellaralice.github.io/en/ || fa fa-language

This full split is a proposed migration, not the current structure. Make it in a source-control branch, move a few test posts first, and verify images, tags, archives, feeds, canonical URLs, and language links before moving all content.

8. Adding pictures, PDFs, and MP3 files

8.1 Pictures owned by one post

For source/_posts/My-Article.md, place the files beside it in a same-named folder:

1
2
3
4
5
source/_posts/
├── My-Article.md
└── My-Article/
├── diagram.png
└── photo.webp

The existing posts successfully use this Markdown form:

1
![Diagram description](My-Article/diagram.png)

Hexo's asset tag is another robust option when post_asset_folder is enabled:

1
{% asset_img diagram.png "Diagram description" %}

Use descriptive alt text rather than an empty []. It improves accessibility and gives useful context if the file fails to load.

For a site-wide image, put it under source/images/ and use a root-relative URL:

1
![Site diagram](/images/site-diagram.png)

8.2 PDF files

The site already enables NexT's PDF tag and uses source/pdf/many-body-ch3.pdf like this:

1
{% pdf /pdf/many-body-ch3.pdf %}

For a new file:

1
source/pdf/my-paper.pdf

Embed it and also provide a normal download link:

1
2
3
{% pdf /pdf/my-paper.pdf %}

[Download the PDF](/pdf/my-paper.pdf)

The download link remains useful when a browser blocks embedded PDFs or the PDF.js fallback fails.

8.3 MP3 files

There is no dedicated audio plugin in the current dependencies. A normal HTML5 audio element works in Markdown.

Put the file here:

1
source/audio/example.mp3

Then add:

1
2
3
4
5
6
<audio controls preload="metadata">
<source src="/audio/example.mp3" type="audio/mpeg">
Your browser does not support HTML5 audio.
</audio>

<a href="/audio/example.mp3" download>Download the MP3</a>

Use lowercase file extensions and simple ASCII filenames when possible. Compress large media before committing it. GitHub Pages has repository, deployment, and bandwidth constraints, so very large audio or PDF collections are better stored in an external object store with stable HTTPS links.

9. Local verification checklist

1
2
3
4
5
6
# Rebuild from a clean cache.
npx hexo clean
npx hexo g

# Serve the generated result.
npx hexo s

Check the following before any deployment:

  1. The new post appears first or at the expected date position on the homepage.
  2. The title, description, tags, category, created date, and updated date are correct.
  3. The table of contents matches the heading hierarchy.
  4. Every local image loads and its browser URL points to the expected post or global asset path.
  5. PDFs render and have a working download link.
  6. MP3 playback, seeking, and download work.
  7. Both light and dark modes remain readable.
  8. Mobile width does not create horizontal scrolling.
  9. CN and EN links lead to files that actually exist.
  10. Browser developer tools show no missing local CSS, JavaScript, fonts, or media.

Ctrl+C stops the local server. Running generate or server does not deploy.

10. Improvement backlog found during this audit

No items in this section were changed while creating this guide.

Priority Finding Recommended future action
High _config.yml still uses url: http://example.com; generated social metadata already contains that hostname Set the production URL and verify root, feed, sitemap, Open Graph, and canonical links
High The blog root is not currently a Git work tree; only .deploy_git/ contains a .git directory Back up the folder, initialize or restore the source repository, and version Markdown/configuration separately from generated deployment output
High Background CSS, canvas.jpg, and avatar.jpg are inside node_modules/hexo-theme-next Move durable assets to source/images/ and CSS to source/_data/; use custom_file_path
High npm audit --omit=dev reported 61 dependency vulnerabilities on 2026-07-31, including 8 critical and 34 high findings Upgrade in a separate branch and test generation/rendering; do not run npm audit fix --force blindly
High Hexo is 6.0.0 while npm reported 8.1.2; NexT is 8.9.0 while npm reported 8.28.0 Stage upgrades and read migration notes. The installed Node 18.19.1 cannot run Hexo 8.1.2, which requires Node 20.19 or newer
High The CN/EN homepage switcher links to missing /en/index.html Choose paired-post links for a small bilingual area or implement and test the two-source build described above
Medium hexo-asset-image is an old Git/SSH dependency and pulls an old vulnerable HTML parser After the renderer upgrade, test Hexo's maintained post-asset handling and remove the plugin only when all old image URLs still render
Medium Both hexo-math and hexo-filter-mathjax are installed, alongside the Pandoc renderer Decide on one documented math pipeline after testing representative formula-heavy posts
Medium db.json is about 89 MiB and source/lib/ is about 54 MiB with 499 PDF.js files Run hexo clean when cache behavior is suspicious; later audit whether only the production PDF.js files need to be shipped
Medium NexT cache is configured on, but NexT 8.9 disables it when language_switcher is enabled Re-evaluate cache after the multilingual design is fixed, then keep only effective settings
Low scaffolds/post.md contains only title, date, and tags Later extend the scaffold with updated, description, categories, lang, and mathjax fields
Low config.txt, empty _config.landscape.yml, and several old/placeholder settings can drift from the active configuration Compare and label/archive them after source control and backups are in place
Low Package versions and the supported Node version are not documented in package.json Add an engines field and a short maintenance README after choosing the upgraded toolchain

For a dependency upgrade, first save the current site and test representative content: a Chinese math-heavy article, an English article, a post with many images, the embedded PDF post, the About page, tags, archives, and the Live2D widget. Keep the old lockfile until the new build is visually verified.

11. Official references

The safest habit is simple: edit source and configuration, generate locally, inspect the result, and deploy only as a separate deliberate action.