As a fan of the Touhou Project, I have created hexo-theme-reimu, a Hakurei Reimu-themed Hexo theme. It combines elements from the landscape, Tangyuxian, and Shoka themes.
Github Repository: (If you find it useful, please give it a star. Thank you!)
Demo:
Development Log:
astro-theme-reimu Demo: Demo Website
hugo-theme-reimu Demo: Demo Website
Features
Basic Features
- ✨ Full blog functionality
- 🔄 Compatible with Hexo 6+
- 📱 Responsive layout
- 🌙 Dark mode support
- 🅰️ i18n support
Code & Math
- 🖥️ Code highlighting & copying
- ➗ KaTeX / MathJax3 math formula support
- 📊 Mermaid flowchart support
Search & Comments
- 🔍 Algolia search integration
- 🔍 Local search integration
- 💬 Multiple comment systems support:
- Valine
- Waline
- Twikoo
- Gitalk
- Giscus
- Disqus
Statistics & Analytics
- 📊 Article reading statistics (Valine / Waline)
- 👥 Visitor statistics (Busuanzi)
Media & Interactive Features
- 🎵 Music player support:
- Aplayer
- Meting
- 🖼️ Lazy loading for images
- ⚡ Loading animations
- 🖱️ Mouse effects:
- Animation effects
- Reimu cursor style
- 👾 Live2D / Live2D-widgets integration
Navigation & Structure
- 📑 Table of Contents
- 🔄 PJAX support
- 🔧 ServiceWorker implementation
- 📰 RSS feed
Design & Customization
- 🎨 Icon support:
- Iconfont
- FontAwesome7
- 🔗 Built-in tag plugins:
- Internal links
- External links
- Friend links
- Heatmap
- Tag Roulette
- 🎨 Dynamic theme color adaptation
- 🎨 Custom Containers
- ©️ Article copyright declaration
- 🌐 Custom CDN source configuration
- 📜 Custom Font Family
- 🎨 Share card functionality
Installation
Beginners can directly use reimu-template. It comes pre-installed with hexo, hexo-theme-reimu, and other functional packages. Just clone the repository, install dependencies, and modify the configuration to get a basic blog!
It already includes the following packages, and you only need to configure them:
- KaTeX / MathJax3 (@reimujs/hexo-renderer-markdown-it-plus)
- mermaid (hexo-filter-mermaid-diagrams)
- git deploy (hexo-deployer-git)
- rss (hexo-generator-feed)
Using npm
1 | npm install hexo-theme-reimu --save |
Or clone the repository directly into the /themes folder and rename it to reimu
1 | git clone https://github.com/D-Sketon/hexo-theme-reimu.git |
Then modify the theme in _config.yml
1 | theme: reimu |
Usage
Basic Structure
To ensure correct display, please refer to _example and create _data, about, and friend folders in the source directory (Note: This is the source folder in the blog root directory, not the source folder in the theme!)
_data
- Store the author’s avatar in the
avatarfolder, default nameavatar.webp, which can be configured in the inner_config.ymlas follows:
1 | avatar: "avatar.webp" |
- Store article covers in the
coversfolder - Store article cover URLs in
covers.yml
about
index.md serves as the About page
friend
index.md serves as the Friends page. Fill in the friend link information in _data.yml to display the corresponding friend cards on the page.
Cover, Banner & Favicon
Cover
The cover display logic is as follows:
- If the article’s Front matter contains a cover URL, both the article banner and the homepage thumbnail will display this URL.
1 |
|
- If the article’s Front matter contains
cover: false, the article will not display a banner (the homepage will still show a random image).
1 |
|
- If the article’s Front matter contains
cover: rgb(xxx,xxx,xxx), the article banner will be a gradient solid color (the homepage will still show a random image).
1 |
|
- Otherwise, search the
coversfolder andcovers.yml, and randomly select an image from them. - If none of the above files exist, the banner will be displayed.
Banner
The banner is stored in themes/reimu/source/images/banner.webp and can be modified in the inner _config.yml.
1 | banner: "/images/banner.webp" |
Favicon
The favicon is stored in themes/reimu/source/images/favicon.ico and can be modified in the inner _config.yml.
1 | favicon: "/images/favicon.ico" |
Sticky Posts
Add sticky: true to the article’s Front-matter.
1 |
|
Article Summary
Disabled by default. You can choose to display the article summary in the subtitle or at the beginning of the article.
1 | summary: |
Sidebar
Sidebar Position
Default on the right. You can modify it in the inner _config.yml.
1 | sidebar: right # left | right |
Additionally, you can control it through the article’s front-matter, which takes precedence over the global configuration.
1 |
|
TOC
Default enabled. You can modify it in the inner _config.yml.
1 | toc: true # true | false |
Additionally, you can control it through the article’s front-matter, which takes precedence over the global configuration.
1 |
|
You can also configure the behavior of the TOC through the following configuration:
1 | toc_options: |
Social Links
You can configure the social links in the sidebar in the inner _config.yml.
1 | social: |
Widgets
You can configure the widgets in the sidebar in the inner _config.yml.
1 | widgets: |
You can also configure the behavior of the widgets through the following configuration:
1 | archive_type: "monthly" # monthly | yearly |
Footer
Basic Information
The footer section allows you to configure basic display information and statistics.
1 | footer: |
ICP Filing
For websites hosted in mainland China, you can display ICP filing information as required by regulations.
1 | icp: |
Moe ICP Filing (v1.9.1+)
1 | moe_icp: |
Code Blocks
To ensure correct display of code blocks, please make sure the outer _config.yml has the following configuration:
(<7.0.0)
1 | highlight: |
(>=7.0.0)
1 | syntax_highlighter: highlight.js |
Code blocks also provide a copy function. Click the copy button in the upper right corner of the code block to copy the code. The copy function can be configured in the inner _config.yml.
success is the prompt when copying is successful, and fail is the prompt when copying fails. Additionally, you can configure a copyright notice. When the number of copied characters exceeds count, the copyright notice will be added after the copied content.
1 | clipboard: |
v1.1.0 added a configuration to control the default expansion state of code blocks. expand can be set to true, false, or a number. A number indicates that the code block will be collapsed by default when the number of lines exceeds this number.
1 | code_block: |
In-site Comments
In-site comments can be controlled independently for each article using the
commentsin the Front matter.
Whencommentsisfalse, comments will not be displayed. Whencommentsistrueor not specified, the display of comments will be determined by the configuration in_config_yml.
Support for multiple comment systems simultaneously after version 1.7.0+
Global comment system configuration:
1 | comment: |
If using Valine
Please refer to the official documentation to complete the LeanCloud configuration, and in the inner _config_yml, set valine.enable to true and fill in your appId and appKey.
1 | valine: |
If using Waline
Please refer to the official documentation to complete the LeanCloud configuration, and in the inner _config_yml, set waline.enable to true and fill in your serverURL.
1 | waline: |
If using twikoo
Please refer to the official documentation to complete the Tencent Cloud or Vercel deployment, and in the inner _config_yml, set twikoo.enable to true and fill in your envId.
1 | twikoo: |
If using giscus
Please refer to the documentation to complete the repository configuration, and in the inner _config_yml, set giscus.enable to true and fill in the corresponding data.
1 | giscus: |
If using gitalk
Please refer to the official documentation to complete the repository configuration, and in the inner _config_yml, set gitalk.enable to true and fill in the corresponding data.
1 | gitalk: |
If using Disqus
Please set disqus.enable to true in the inner _config.yml, and fill in your shortname
1 | disqus: |
In-site Search
If choosing Algolia, please install @reimujs/hexo-algoliasearch
1 | npm install @reimujs/hexo-algoliasearch --save |
And refer to its README to complete the configuration of the Algolia account, and add the following configuration to the outer _config.yml
Note: The search jump link is a permanent link, so please make sure the
urlin the outer_config.ymlis filled in correctly.
1 | algolia: |
In the inner _config_yml, set algolia_search.enable to true
1 | algolia_search: |
After version 1.5.0, the theme has built-in
hexo-generator-search, so there is no need to installhexo-generator-searchseparately.
This theme comes with hexo-generator-search built-in. If you choose to use local search, please set generator_search.enable to true in the inner _config.yml. For other configurations, refer to hexo-generator-search.
1 | generator_search: |
Math Formulas
Please install @reimujs/hexo-renderer-markdown-it-plus
1 | npm uninstall hexo-renderer-marked --save |
By default, it is turned off. In the inner _config.yml, set math.enable to true to enable math formula support.
Note: Do not enable both KaTeX and MathJax3 at the same time.
KaTeX
If you want server-side rendering, in the inner _config.yml, set math.katex.enable to true
1 | math: |
If you want client-side rendering, in the inner _config.yml, set math.katex.enable to true and set autoRender to true
1 | math: |
Add the following configuration to the outer _config.yml
1 | markdown_it_plus: |
MathJax3
If you want to use MathJax3, in the inner _config.yml, set math.mathjax.enable to true
1 | math: |
Add the following configuration to the outer _config.yml
1 | markdown_it_plus: |
Mermaid Flowcharts
Please install hexo-filter-mermaid-diagrams
1 | npm install hexo-filter-mermaid-diagrams --save |
In the inner _config_yml, set mermaid.enable to true
1 | mermaid: |
And add mermaid: true to the front-matter of articles that require mermaid (This is different from other configurations, please note!)
1 |
|
RSS
Please install hexo-generator-feed
1 | npm install hexo-generator-feed --save |
And refer to its README to complete the feed configuration in the outer _config.yml
Fill in the generated xml in the inner _config.yml
1 | rss: atom.xml |
i18n
This theme provides four languages by default: en, zh-CN, zh-TW, and ja. You can switch the language by modifying the language in the outer _config.yml.
1 | language: zh-CN |
The following is an experimental feature and may contain bugs.
v1.4.0+ experimentally introduced hexo-generator-i18n and added multi-language switching functionality. You can configure i18n in the inner _config.yml to add custom languages. The configuration can be referenced from hexo-generator-i18n:
1 | i18n: |
For multilingual support in posts, you can add lang in the Front-matter to specify languages other than the default language (the default language does not need to be added).
1 | lang: en |
The above will generate a page at /en/:permalink.
For multilingual support in pages, you can directly create a folder for the corresponding language in the source directory and place an index.md file inside it, such as source/en/about/index.md. This will generate a page at /en/about.
Icons
Icons default to the iconfont provided by this project (v0.1.3+)
1 | icon_font: 4552607_bq08450reo |
If you want to continue using fontawesome icons, set icon_font to false, and it will use the corresponding fontawesome in vendor
1 | fontawesome: |
Extended Features
Dark Mode
The default setting is auto, which automatically switches based on the user’s system settings. It can be set to true or false to change the default state.
1 | dark_mode: |
Pace Progress Bar
Enabled by default
1 | pace: |
Firework Mouse Effects
Enabled by default
1 | firework: |
For specific configurations, please refer to mouse-firework
pjax
Disabled by default
1 | pjax: |
pjax was introduced in v0.0.10 for users who need to add music players or other SPA features. After several iterations, it has become relatively stable, but there may still be issues such as scripts not executing, scripts executing repeatedly, or page rendering errors. Please consider carefully before enabling!
PJAX cannot be used with
relative_link: true!
ServiceWorker
Disabled by default
1 | service_worker: |
Live2D
Disabled by default
1 | live2d: |
Live2D Widgets
Disabled by default
1 | live2d_widgets: |
Reimu Mouse Pointer
Enabled by default
1 | reimu_cursor: true |
Responsive Banner (v0.2.0+)
Disabled by default. Enabling it and providing corresponding images and media queries can improve LCP on mobile devices to some extent.
1 | banner_srcset: |
Article Copyright Notice (v0.2.0+)
Disabled by default
1 | article_copyright: |
Additionally, it can be controlled via the article’s front-matter, which has higher priority than global configuration.
1 |
|
quicklink (v0.2.3+)
Enabled by default. Enabling it can preload links while the user stays on the page, improving user experience.
1 | quicklink: |
Article Outdated Notice (v0.2.4+)
Disabled by default
1 | outdate: |
Sponsorship (v0.3.2+)
Disabled by default
1 | sponsor: |
Additionally, it can be controlled via the article’s front-matter, which has higher priority than global configuration.
1 |
|
Homepage Category Cards (v1.0.0+)
Disabled by default. Enabling it can display category cards on the homepage, replacing the category widget.
1 | home_categories: |
Music Player (v1.2.0+)
It is recommended to enable Pjax before using, otherwise the player may automatically pause.
Using Aplayer + Meting (optional), disabled by default.
Music Player Position (v1.9.1+)
Default is after sidebar
1 | player: |
Pure Aplayer
Set player.aplayer.enable to true, and configure player.aplayer.options according to Aplayer Docs
1 | player: |
Aplayer + Meting
Set both player.aplayer.enable and player.meting.enable to true, and configure player.meting.options according to Meting Docs, player.aplayer.options is the Aplayer configuration.
1 | player: |
Share Links/Cards (v1.3.0+)
Disabled by default. Currently supports facebook, twitter, linkedin, reddit, weibo, qq, weixin.
1 | share: |
In weixin mode, a share card with a QR code will be generated, which can be saved locally and shared on WeChat Moments (Note: When the article cover has cross-origin issues, snapdom cannot correctly generate a card with images!)
Injector (v1.5.1+)
Used to inject custom code, similar to Hexo#Injector, supports head, body and sidebar injection
1 | injector: |
Triangle Badge (v1.10.2+)
Disabled by default. When enabled, it will display a triangle badge in the upper right corner, supporting custom links and icons.
1 | triangle_badge: |
Built-in Tag Plugins
friendLink Friend Link Card
1 | {% friendsLink path %} |
The first parameter path is the path to the friend link yaml.
postLinkCard Internal Link Card
1 | {% postLinkCard slug [cover]|"auto" [escape] %} |
The first parameter is the article’s slug; the second parameter (optional) is the cover displayed on the card, if set to auto, the blog’s banner will be used automatically; the third parameter (optional) indicates whether the article title is escaped.
slug generation algorithm: https://github.com/hexojs/hexo-util/blob/master/lib/slugize.ts
Simply put, it removes invisible characters from the article title, replaces special characters\s~!@#$%^&*()\-_+=[]{}|\;:"'<>,.?/with the separator-, merges consecutive separators, and removes leading and trailing separators.
externalLinkCard External Link Card
1 | {% externalLinkCard title link [cover]|"auto" %} |
The first parameter is the article’s title; the second parameter is the external link to the article, the third parameter (optional) is the cover displayed on the card, if set to auto, the default cover will be used.
Heat Map Card Article Heatmap (v1.7.0+)
1 | {% heatMapCard levelStandard %} |
The first parameter is the level standard for the heatmap (graded based on the word count of the articles), with the default value being "1000,5000,10000".
tagRoulette (v1.9.0+)
1 | {% heatMapCard tags icon %} |
tagRoulette is an interactive element that provides a random tag display feature. When the button is clicked, a tag is randomly selected and displayed from a predefined pool of tags.
- tags: Optional parameter specifying the tag pool. Multiple tags should be separated by English commas (,). If not provided, a few example tags will be used by default. Example:
tags="memory decline, loss of expression, increased laziness, numbness, so sleepy" - icon: Optional parameter to customize the trigger button’s icon. Default: 🕹️ (game controller emoji). Can be replaced with any emoji or text, such as 🎲, 🎯, 🔄, etc.
tabs (v1.11.0+)
1 | {% tabs [activeTab] ["center"] %} |
Adapted from the next, volantis, and stellar themes, this feature supports creating tabbed switching effects within articles.
- activeTab: Optional parameter, specifies the default active tab index (counting starts from 1). Default is 1.
- “center”: Optional parameter, specifies that tab titles should be center-aligned. Default is left-aligned.
- tabName: The title of each tab, must be wrapped in
. Supports displaying icons using@+ icon hexadecimal code. Examples:- Title only:
- Icon only:
- Icon + Title:
- Title only:
Gallery Photo Wall (v1.11.0+)
1 | {% gallery %} |
Display multiple images in a photo wall format, supporting automatic arrangement and responsive layout.
Custom Containers
This theme provides custom container functionality similar to Vitepress. Before using it, you need to install @reimujs/hexo-renderer-markdown-it-plus.
Usage is as follows:
1 | ::: info |
Customizing the Theme
hexo-theme-reimu supports high levels of customization. You can customize your theme by modifying _config.yml.
Vendor
vendor is used to store some third-party resources, such as fontawesome, iconfont, katex, mathjax, etc.
The vendor structure of hexo-theme-reimu is very flexible, supporting the following forms:
:cdn|:package@:version/:file: Use CDN acceleration, such ascdn_jsdelivr_gh|katex@0.13.11/dist/katex.min.css,:cdncan be configured invendor. Currently, the following CDN sources are included:Users can switch CDN sources based on network conditions.1
2
3
4
5
6cdn_jsdelivr_gh: https://cdn.jsdelivr.net/gh/ # Only for github acceleration
cdn_jsdelivr_npm: https://cdn.jsdelivr.net/npm/ # Only for npm acceleration
fastly_jsdelivr_gh: https://fastly.jsdelivr.net/gh/ # Only for github acceleration
fastly_jsdelivr_npm: https://fastly.jsdelivr.net/npm/ # Only for npm acceleration
unpkg: https://unpkg.com/ # Only for npm acceleration
webcache: https://npm.webcache.cn/ # Only for npm accelerationhttps://prefix: Use absolute links directly, such ashttps://cdn.jsdelivr.net/npm/katex@0.13.11/dist/katex.min.css/prefix: Local resources, you can place resources in thesourcefolder at the same level as_posts, and then use paths like/katex.min.cssto reference them.
Additionally, vendor supports SRI verification. You can use SHA-384 in vendor to verify the integrity of resources, such as:
1 | js: |
Both forms are supported. It is recommended to use SRI verification for external CDN resources to ensure resource integrity.
Appendix
Front-matter Fields
| meta | Description | Type | Value Logic | Version |
|---|---|---|---|---|
| title | Title | string | Article file name | Hexo Built-in |
| date | Creation Date | date | File creation date | Hexo Built-in |
| updated | Update Date | date | File update date | Hexo Built-in |
| tags | Tags | string[] | string[][] | - | Hexo Built-in |
| categories | Categories | string[] | string[][] | - | Hexo Built-in |
| permalink | Override the article’s permanent link | string | - | Hexo Built-in |
| excerpt | Article Excerpt | string | - | Hexo Built-in |
| description | Article Description | string | - | 0.0.1 |
| link | Directs the article to an external link | string | - | 0.0.1 |
| sticky | Whether to pin the article | boolean | false | 0.0.1 |
| photos | Article photo gallery | string[] | - | 0.0.1 |
| mermaid | Whether to enable mermaid (requires configuration with mermaid config) | boolean | false | 0.2.0 |
| copyright | Whether to enable article copyright notice | boolean | Defaults to global config if not provided | 0.3.1 |
| sponsor | Whether to enable article sponsorship | boolean | Defaults to global config if not provided | 0.3.2 |
| comments | Whether to enable article comments | boolean | Defaults to global config if not provided | 0.3.2 |
| cover | Article cover | https://example.com | false | rgb(255,117,117) | Defaults to global config if not provided | 0.0.7 |
| sidebar | Article sidebar position | false | 'left' | 'right' | Defaults to global config if not provided | 1.3.0 |
| lang | Article language (requires configuration with i18n config) | string | - | 1.4.0 |
| toc | Whether to enable article table of contents | boolean | Defaults to global config if not provided | 1.6.0 |
| outdated | Whether the article is outdated | boolean | Defaults to global config if not provided | 1.10.1 |
| author | Article author (used for article copyright and sharing cards) | string | Defaults to global config if not provided | 1.10.2 |
| keywords | Article keywords for SEO | string[] | string | Defaults to global config if not provided | 1.10.4 |
QA
Music still pauses automatically after page jumps with pjax enabled
Under investigation, v1.3.0 theoretically fixed some issues.
Avatar not displaying correctly
Refer to reimu-template to ensure the avatar is placed in /source/_data/avatar/ and the name matches the configuration (Note: This is the source folder in the blog root directory, not the source folder in the theme!)
About and Friends pages display garbled text, no styles
Refer to reimu-template to ensure about and friend are placed in /source/ (Note: This is the source folder in the blog root directory, not the source folder in the theme!)
Gitalk keeps loading
Refer to gitalk#514, some APIs that Gitalk depends on are blocked, causing it to fail to load.
The comment section mentions that replacing the Gitalk js address can solve the problem, but this theme will not provide such a solution due to potential security risks.
I still have strange issues
First, try the hexo clean method. If the problem persists, try cloning reimu-template directly and make modifications based on it. If the issue still exists, please ask a question on Github issue and provide detailed error information/reproduction steps. It is not recommended to report issues in the comment section as it is inconvenient for code formatting.


Leave a comment