!!!安装前必读!!!

  1. 本网站已经开源:hexo-theme-Fomalhaut v1.0.0,仓库地址 hexo-theme-Fomalhaut。如果你喜欢的话,可以帮我点一个免费的 Star 🌟 哦!

  2. 这一次是结构性重写:主题从 themes/butterfly 独立成 themes/fomalhaut,站点配置与主题代码彻底分开。改配置就能搭起自己的站,而升级主题时只要覆盖 themes/fomalhaut/,你自己写的样式和脚本都不会丢。

  3. 仍然不适合纯小白:需要熟悉 Hexo 命令,以及最基础的 HTML5 / CSS3 / JavaScript。不熟悉的朋友建议先看 Hexo 中文文档 与 Butterfly 主题文档。

  4. 安装方式仍然是整个博客的替换,建议另起一个文件夹进行安装,或先备份好原来的资料。当然你也可以不直接搬走,而是借鉴里面的部分写法。

🔥 本次更新(v1.0.0)

上一版(3.22)是「整套博客直接开源」:主题还是 themes/butterfly,配置叫 _config.butterfly.yml,站点页面大多是空壳。
这一版把三年来的魔改做了一次彻底整理,几条主线:

方向变化
主题独立themes/butterfly → themes/fomalhaut,包名与配置同步改名;配置迁到站点根 _config.fomalhaut.yml
配置瘦身fomal.js 从 2973 行拆成 105 行主引导 + 10 个模块;配置里的 26 段内联样式与脚本抽成 source/css/site-inject.css 与 source/js/inject/
样式整理custom.css(近 4000 行)删掉 341 行死代码,并补上完整的文件头索引地图
新增功能AI 助手、美化设置面板、侧栏日历与倒计时(农历/节气/节日)、手机端抽屉、网站统计页、时间线归档、网址导航、天文星图
资源外链化图片与字体统一走公共 CDN(jsDelivr 的 @fontsource、picsum),不再依赖自建对象存储
字体精简11 款 → 6 款开源可商用字体(SIL OFL),面板上的名字也改成真实字体名
文档README 重写为完整文档(含架构、每一项配置示例、部署与 FAQ),并补上界面截图

🎈 这是什么

hexo-theme-Fomalhaut 是一个跑在 Hexo 上的个人博客主题 / 站点模板。它不是单纯的 themes/ 目录,而是一整套可运行站点:

  • 一套主题代码(themes/fomalhaut/,Pug + Stylus 渲染);
  • 一份站点配置(根目录 _config.yml + 根目录 _config.fomalhaut.yml);
  • 一批站点级增强(根目录 scripts/ 下的 Hexo 插件、source/js/ 与 source/css/ 下的自定义脚本与样式);
  • 若干示例页面(网址导航、画廊、八音盒、友人帐、朋友圈、网站统计、时间线归档、天文星图……)与 2 篇示例文章。

它解决的问题是:Hexo 生态里大量的美化方案都靠「直接改主题源码」,一旦主题更新就得重新抄一遍。
本仓库把主题代码与站点改动放进不同目录,站点侧的东西全部通过「配置注入 + 独立 css/js 文件」实现。

来源背景:作者从 2022 年起用 Butterfly 4.3.1 搭建这个博客,三年间持续魔改,把散落在配置与主题里的大量改动逐步抽成独立文件;2026-10 做了一次完整重构(内部代号「屎山重构」),最终整理为 v1.0.0 开源。

📸 界面预览

首页

顶部是全屏大图 + 站点名 + 打字机副标题,右侧固定悬浮按钮列(设置 / AI 助手 / 分享 / 回到顶部)。

首页文章列表与侧栏

文章卡片、侧栏日历(含农历与节气)、倒计时卡、公告栏、小站资讯、右下角交互按钮。

文章页

文章标题栏、自动生成的右侧目录、代码块(语言标签 + 一键复制 + 行号)、外挂标签渲染。

美化设置面板

点右下角齿轮打开。访客可以自己换字体、主题色、背景、特效开关,设置存 localStorage,刷新不丢。

🏗 项目架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
用户请求
│
▼
Hexo 6.3.0 ──┬─► 根 _config.yml 站点级配置(标题 / 作者 / 域名 / 部署 / 插件)
├─► 根 _config.fomalhaut.yml 主题配置(Hexo 5+ 的 _config.[theme].yml,本站实际生效)
├─► 根 scripts/*.js 站点级 Hexo 插件(构建期过滤器)
│
├─► source/ 站点内容
│ ├─ _posts/ 文章(Markdown)
│ ├─ box|life|site|social|personal/ 独立页面
│ ├─ css/*.css js/*.js 站点级样式与脚本(不进主题)
│ └─ _data/{link,widget}.yml 友链与侧栏卡片数据
│
└─► themes/fomalhaut/ 主题本体
├─ _config.yml 主题默认配置(被根 _config.fomalhaut.yml 覆盖)
├─ layout/*.pug Pug 模板
├─ source/css/*.styl Stylus 样式
├─ source/js/*.js 主题脚本
└─ scripts/ 主题级 Hexo 插件(标签、过滤器、助手函数)
│
▼
hexo generate → public/ → gulp 压缩 → 推到托管平台

三层配置优先级(Hexo 5+ 的行为):

层级文件作用
站点根 _config.yml站点名、作者、URL、部署、算法插件等
主题(生效)根 _config.fomalhaut.yml本站真正使用的主题配置,所有开关都在这里
主题(默认)themes/fomalhaut/_config.yml主题自带的默认值模板,留作参考 / 兜底

🆚 相比上一版改了什么

1. 主题独立,改名为 fomalhaut

项旧版 (3.22)新版 (v1.0.0)
主题目录themes/butterfly/themes/fomalhaut/
主题包名hexo-theme-fomalhaut v4.3.1(沿用 Butterfly 的 package.json)hexo-theme-fomalhaut v1.0.0(独立版本号)
主题配置_config.butterfly.yml_config.fomalhaut.yml
配置注入少量 inject完整 inject.head / inject.bottom 注入体系 + 独立 css/js 文件

2. 站点与主题彻底分离

  • 所有自定义样式集中到 themes/fomalhaut/source/css/_custom/custom.css(文件头带完整索引地图)与 source/css/*.css;
  • 所有自定义脚本从单文件 fomal.js(2973 行)拆成 105 行主引导 + 10 个模块(source/js/modules/)与 10 个注入脚本(source/js/inject/);
  • 配置里的 26 段内联样式与脚本抽成 source/css/site-inject.css 与独立 js,配置文件从 2037 行瘦到 1482 行。

3. 新增功能

功能位置说明
AI 助手source/js/ai-chat.js + scripts/ai-chat-inject.js + api/chat/completions.js右侧悬浮对话面板,前端可直连也可走同源代理隐藏 Key
美化设置面板source/js/modules/settings.js访客可自选字体、主题色、暗色、阅读模式、背景、特效开关
侧栏日历 / 倒计时source/js/aside-calendar.js + source/js/lunar.js带农历、节气与节日提醒
手机端抽屉source/css/mobile-drawer.css独立样式表,13 个小节:面板、字标、头像、统计胶囊、菜单、遮罩、入场动效
网站统计页source/site/census/ + source/js/census.js图表看板,配色由主题色派生
时间线归档source/site/time/ + source/js/timeline-archive.js用时间线标签写站史 / 里程碑
网址导航source/box/nav/圆形头像小卡式导航,纯 CSS 计数器
天文星图source/box/astronomy/voyager.html独立完整页面,用 iframe 引入,skip_render 不参与渲染
PWA + Service Workerthemes/fomalhaut/source/sw.js离线预缓存 + 请求分流
多平台部署.github/workflows/autodeploy.yml、vercel.json、functions/GitHub Actions / Vercel / Cloudflare Pages

4. 工程化与性能优化

  • 构建链:hexo generate → gulp(html / css 压缩),一条命令出产物;
  • 图片懒加载修复:scripts/swiper-lazyload-fix.js 处理轮播与 pjax 场景下 lazyload 失效;
  • 搜索懒加载:source/js/inject/search-lazy.js 只在点开搜索时才拉取;
  • pjax 守卫:source/js/pjax-guard.js 修复换页后状态残留;
  • CDN 预连接:配置里对首屏外部域名做 preconnect / dns-prefetch;
  • 字体:改为公共 CDN(jsDelivr 的 @fontsource/*),并精简为 6 款开源可商用字体;
  • 图片外链:封面 / 壁纸 / 站点截图全部改为公共占位图服务,不再依赖自建对象存储;
  • 配置瘦身:fomal.js 2973 → 105 行,custom.css 删掉 341 行死代码并补上索引地图。

🧰 环境要求

依赖版本说明
Node.js18 / 20 / 22 LTS(推荐 22)仓库自带的 GitHub Actions 工作流使用 22.x
npm9+随 Node 一起安装
Hexo6.3.0已写进 package.json 的 hexo.version,无需全局安装即可用 npx hexo
Git任意较新版本克隆与部署用

除此之外不需要 Python、不需要全局 hexo-cli。

🚀 快速开始

1. 克隆并安装依赖

1
2
3
git clone https://github.com/fomalhaut1998/hexo-theme-Fomalhaut.git my-blog
cd my-blog
npm install # 或 npm ci(有 package-lock.json,更快更稳)

这里绝不能使用 hexo init 初始化!一旦用了,站点的配置文件 _config.yml 内容会被重置。

2. 本地预览

1
npx hexo server      # 打开 http://localhost:4000

改 source/ 下的内容与 CSS 会自动重新渲染;改 themes/ 下的 .pug 模板需要重启 server(Hexo 只在启动时读模板)。

3. 改成你自己的站点(关键三步)

第一步:改 _config.yml(站点级)

1
2
3
4
5
6
7
8
9
10
11
12
title: 我的小站
subtitle: ''
description: '记录学习与生活'
keywords: 'Hexo,博客'
author: 你的名字
language: zh-CN
url: https://your-domain.com/

deploy:
- type: git
repository: https://github.com/yourname/yourname.github.io.git
branch: main

第二步:改 _config.fomalhaut.yml(主题级),至少改这几处:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
avatar:
img: /assets/avatar.webp # 换成你自己的头像(也可用图床外链)

social: # 社交图标,格式: 名称: 链接 || 图标类名 || 动画类名
Github: https://github.com/yourname || icon-github || faa-tada
邮箱: mailto:you@example.com || icon-youxiang || faa-tada

index_img: /assets/head.jpg # 首页大图

footer:
owner:
enable: true
since: 2022

menu: # 顶部导航(键 = 显示名,值 = 路径 || 图标)
首页: / || fas fa-home
归档: /archives/ || fas fa-archive
关于: /personal/about/ || fas fa-user

第三步:写文章

1
hexo new post "我的第一篇文章"   # 生成 source/_posts/YYYY-MM-DD-我的第一篇文章.md

4. 构建产物

1
hexo clean && hexo generate && gulp

产物在 public/,gulp 负责 HTML / CSS 压缩。

🗂 目录结构与文件地图

整体结构

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
├─ _config.yml                 站点级配置(标题/作者/域名/部署/插件)
├─ _config.fomalhaut.yml 主题配置 ★ 大部分开关在这里
├─ package.json 依赖与 npm scripts
├─ gulpfile.js 构建压缩任务
├─ vercel.json Vercel 函数配置(用 Vercel 部署时才需要)
├─ scaffolds/ 新建文章/页面的模板
├─ scripts/ ★ 站点级 Hexo 插件(构建期生效)
├─ api/ Vercel 云函数(AI 代理)
├─ functions/ Cloudflare Pages 函数(同一份逻辑)
├─ tools/ 本地脚本(一键部署 Vercel)
├─ .github/workflows/autodeploy.yml GitHub Actions 自动部署
├─ repoPic/ README 用图(不参与构建)
├─ source/ ★ 站点内容
│ ├─ _posts/ 文章
│ ├─ _data/link.yml 友链数据
│ ├─ _data/widget.yml 侧栏自定义卡片
│ ├─ assets/ 站点图片(头像、加载动画、徽章…)
│ ├─ css/*.css 站点级样式
│ ├─ js/*.js 站点级脚本
│ ├─ box/ life/ site/ social/ personal/ 各种独立页面
│ └─ categories/ tags/ 分类页与标签页
└─ themes/fomalhaut/ ★ 主题本体(升级时整体替换即可)
├─ _config.yml 主题默认配置(被根 _config.fomalhaut.yml 覆盖)
├─ layout/ Pug 模板
├─ source/css|js|img/ Stylus 样式 / 主题脚本 / 主题图
├─ scripts/ tag(外挂标签)/ filters / helpers / events
└─ languages/ 多语言文案

source/css/ —— 站点级样式,各管什么

文件负责的功能
about-page.css关于页版式(Hero、线路卡、技术栈、时间线)。选择器全以 .ab2 开头,只影响 /personal/about/
aside-calendar.css侧栏「日历卡 + 倒计时卡」外观,只作用 #aside-calendar / #aside-countdown
avatar-glow.css侧栏头像呼吸灯(颜色跟随主题色)
census.css网站统计页看板排版,只由 /site/census/ 页面引入
coin.css投币按钮样式(文章底部「投喂」区)
gitcalendar.cssGitHub 贡献日历底色与格子
kslink.css友人帐「快速申请」按钮
mobile-drawer.css手机端抽屉菜单改版(13 小节),窄屏自动生效
site-inject.css站点注入样式合集(横幅公告、PC 浅色主题、侧栏加宽、列表分页、面包屑、小站资讯卡、aplayer 音量条、页脚隐藏本站项等)
stats.css文章统计页图表排版,只由 /tags/ 页生效
timeline-archive.css「旧时光」页时间轴外观
twikoo.cssTwikoo 评论区美化(表单/列表/按钮统一到主题色)
typewriter.css首页副标题打字机观感

source/js/ —— 站点级脚本,各管什么

入口与模块(由 source/js/fomal.js 统一按顺序加载,加载清单在 _config.fomalhaut.yml 的 inject.bottom)

文件负责的功能
fomal.js站点主引导(105 行)。控制台执行 __fomal.check() 可自检各模块是否加载成功
modules/reading.js阅读进度条 + FPS 检测
modules/nav.js导航栏吸顶、首屏欢迎语、侧栏「欢迎信息」卡片、分享按钮、「随便逛逛」
modules/console-art.js控制台字符画与版权署名
modules/effects.js页面装饰特效:雪花 / 星空 / 表情放大
modules/cursor.js鼠标相关:右键菜单、小猫咪、听话鼠标
modules/shell.js站点「外壳」行为:快捷键、夜间动画、标题恶搞、搜索框、手机滚动条
modules/settings.js美化设置面板(Winbox),字体 / 主题色 / 背景 / 显示偏好四节的全部交互
modules/footer-time.js页脚「本站已运行 X 天」计时器 + 摸鱼徽章
data/holidays.js法定休息日判断(纯数据)
data/voyager1.js旅行者 1 号距离模型(纯计算)

独立功能脚本

文件负责的功能
ai-chat.jsAI 助手前端本体(对话面板、流式输出、Markdown 渲染)
aside-calendar.js侧栏日历卡 + 倒计时卡渲染(农历、节气、下一个节日)
lunar.js农历 / 二十四节气换算(1900–2100)
festival.js节日提醒通知卡片(25 个节日集中成一张表)
celebrate.js全屏礼炮 / 烟花(只在喜庆节日被 festival.js 动态插入)
author-status.js侧栏个人信息卡右上角状态胶囊
census.js网站统计页图表数据(百度统计 API)
stats.js文章统计页增强
gitcalendar.jsGitHub 贡献日历渲染
timeline-archive.js「旧时光」页时间轴行为层
notify.js轻量通知组件(替代 Vue + Element-UI 的 $notify)
pjax-guard.js修 pjax 选择器不匹配导致的换页整刷与遮罩转圈
wechat-qr.js社交二维码点击 → 同页灯箱展示
kslink.js友人帐「快速申请」表单填充
bibi.jsB 站粉丝数等数据展示
coin.js投币音效与动画
footer-music.js页脚「猜你想看」补一条「听点音乐」→ /life/music/
leaves.js落叶特效
love.js「在一起 X 天」计时
51la.js51LA 统计与灵雀监控初始化

source/js/inject/(由 inject.head / inject.bottom 以 <script> 引入)

文件负责的功能
beauty-boot.js美化模块首屏预置(把 localStorage 里的字体/主题色/背景尽早写进 :root,避免闪默认样式)
typewriter.js首页副标题打字机「丝滑版」
search-lazy.jsAlgolia 搜索按需加载
scroll-gap-fix.js锚点跳转补偿(常驻顶栏 70px)
webinfo-card.js侧栏「小站资讯」卡:KPI 数字滚动、运行天数、站点更新时间
ping-route.js + ping-route-boot.js公告栏里每条部署线路的实时延迟徽标
about-route-probe.js关于页线路卡右下角的「实时延迟」徽标
pc-local-link.js版权卡「文章链接」显示当前访问域名
right-menu-state-boot.js侧栏「右键模式」按钮的状态同步
ft-ad-extra.js页脚友链补一个「广告位招租」

scripts/ —— 站点级 Hexo 插件(构建期跑)

文件负责的功能
ai-chat-inject.js往每个页面 </body> 前注入 window.AI_CHAT_CONFIG 与 /js/ai-chat.js
gallery-pager.js相册自动分页
magnet-local-links.js修首页小冰磁贴跳到外站的问题
post-copyright-local-link.js修文章版权卡「文章链接」写死主域名的问题
sticky-post.js正文标记置顶(sticky: true → 首页置顶角标)
swiper-lazyload-fix.js修首页轮播在 pjax 往返后懒加载失效
tag-map-local.js把 hexo-tag-map 的 jsDelivr CDN 改成本站自托管
vercel-api-copy.js构建后把 api/、functions/、vercel.json 拷进 public/

💡 要不要改主题? 尽量别改。能用配置解决的走 _config.fomalhaut.yml;配置解决不了的,写进 source/css/*.css 或 source/js/,再用 inject 引入——这样升级主题时直接覆盖 themes/fomalhaut/ 就行。

⚙️ 主要功能怎么配

下面所有片段都写在站点根目录的 _config.fomalhaut.yml 里(除非特别说明)。

1. 导航菜单

1
2
3
4
5
6
7
8
9
menu:
首页: / || fas fa-home
时间轴:
归档: /archives/ || fas fa-archive
标签: /tags/ || fas fa-tags
清单:
友人帐: /social/link/ || fas fa-link
朋友圈: /social/fcircle/ || faa-tada
关于: /personal/about/ || fas fa-user

缩进一层就是二级菜单。图标可以写 fas fa-xxx(Font Awesome)或 faa-tada、faa-spin 这类动画类名。

2. 顶部图与封面

1
2
3
4
5
6
7
8
9
10
11
12
13
disable_top_img: false
index_img: /assets/head.jpg # 首页顶部大图(留空 = 露出站点背景图)
default_top_img: /assets/head.jpg # 其他页面默认顶部图
archive_img: # 归档页顶部图
category_img: # 分类页顶部图

cover:
index_enable: true # 首页文章卡片显示封面
aside_enable: true # 侧栏文章卡片显示封面
archives_enable: true # 归档页显示封面
default_cover: # 文章没写 cover 时从这里随机取一张
- https://picsum.photos/id/1015/1200/675
- https://picsum.photos/id/1018/1200/675
  • 单篇文章想指定封面:在文章 Front-matter 写 cover: 图片链接。
  • cover.default_cover 现在填的是固定的 picsum 图片 ID(不是随机 seed),所以每次刷新不会变图、也不会出现奇怪内容。换成你自己的图床地址即可。

3. 主题色与暗色模式

1
2
3
4
5
6
7
8
9
10
11
theme_color:
enable: true
main: '#49b1f5' # 主题色
link_color: '#a591e0' # 链接色
meta_color: '#858585' # 次要文字
hr_color: '#A4D8FA' # 分隔线

display_mode: light # light | dark | auto(跟随系统)
darkmode:
enable: true
button: true # 右下角显示日夜切换按钮

站点里绝大部分自定义样式的颜色都由 var(--theme-color) 派生(用了 color-mix),所以换主题色时整站会跟着变——这也是美化面板「主题色设置」能实时预览的原因。

4. 侧栏卡片

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
aside:
enable: true
card_author: # 个人信息卡
enable: true
description: '这是我的小站'
button:
enable: true
text: 关注我
link: https://github.com/yourname
card_announcement: # 公告栏(支持 HTML)
enable: true
content: 这里写公告
card_recent_post: # 最新文章
enable: true
limit: 5
card_categories: # 分类
enable: true
limit: 8
card_tags: # 标签
enable: true
limit: 40
card_archives: # 归档
enable: true
type: monthly
format: MMMM YYYY
card_webinfo: # 小站资讯(字数 / 访客 / 运行天数)
enable: true
post_count: true
last_push_date: true
card_friend_link: # 友人帐侧栏卡
enable: true
card_newest_comment: # 最新评论
enable: false

想加完全自定义的卡片:写进 source/_data/widget.yml,用 top: / bottom: 分组,html: 里写任意 HTML。侧栏的「日历卡 / 倒计时卡」就是这么做出来的。

5. 评论系统

支持 11 种:Twikoo / Waline / Valine / Giscus / Utterances / Gitalk / Disqus / Disqusjs / Livere / Remark42 / Facebook Comments。

1
2
3
4
5
6
7
comments:
use:
- Twikoo # ★ 在这里切换用哪个
text: true # 显示「评论」二字
lazyload: true # 滚动到评论区才加载(开了之后评论数会失效)
count: false # 文章顶部显示评论数
card_post_count: false # 首页卡片显示评论数

Twikoo 完整配置(推荐,无需后端服务器)

  1. 部署 Twikoo 服务端(三选一):
    • Vercel 一键部署(最省事):打开 https://twikoo.js.org/quick-start.html → 点「Vercel 部署」→ 登录 Vercel → 一路 Next → 部署完把首页那张图里的地址复制下来;
    • Docker:docker run -d -p 8080:8080 -v /data/twikoo:/data -e TWIKOO_THROTTLE=200 ikew0ng/twikoo;
    • 云函数:腾讯云 SCF / 阿里云 FC 都有 Twikoo 模板。
  2. 在配置里填地址:
1
2
3
4
5
twikoo:
envId: https://你的-twikoo-地址 # ← 就这一处必填
region: # 腾讯云 SCF 部署时才需要填(如 ap-shanghai)
visitor: false # 开启访客统计
option: # 透传给 Twikoo 初始化,如 lang、path
  1. 打开评论区:把上面的 comments.use 设成 Twikoo。
  2. (可选)美化:仓库已带 source/css/twikoo.css,由 inject.head 引入,把表单/列表/按钮统一到主题色。不需要就删掉那一行。
  3. (可选)首页显示最新评论:把 aside.card_newest_comment.enable 设为 true。

6. 搜索

1
2
3
4
5
6
7
8
local_search:            # 方案 A:本地搜索,零后端、零 Key
enable: true
trigger: auto # auto = 点开搜索才拉取(更快);manual = 手动

algolia_search: # 方案 B:Algolia 云搜索(内容多时更快、支持全文高亮)
enable: false
hits:
per_page: 10

用 Algolia 还要在根 _config.yml 补上应用信息:

1
2
3
4
5
algolia:
appId: YOUR_ALGOLIA_APP_ID # https://dashboard.algolia.com/account/api-keys
apiKey: YOUR_ALGOLIA_SEARCH_KEY
adminApiKey: YOUR_ALGOLIA_ADMIN_KEY
indexName: your_index_name

改完执行 hexo algolia 推送索引,再 hexo generate。仓库里 source/js/inject/search-lazy.js 会让 Algolia 的资源延后到点开搜索才加载。

7. 网站统计

① 不蒜子(前端 PV / UV,零配置)

1
2
3
4
busuanzi:
site_uv: true # 站点访客数
site_pv: true # 站点访问量
page_pv: true # 单页访问量

② 各平台统计脚本(填 ID 即生效)

1
2
3
4
5
baidu_analytics:                     # 百度统计 ID,https://tongji.baidu.com/web/welcome/login
google_analytics: # GA4 衡量 ID(G-XXXXXXX)
cnzz_analytics: # 友盟 CNZZ 站点 ID
cloudflare_analytics: # Cloudflare Web Analytics token
microsoft_clarity: # Microsoft Clarity ID

③ 51LA + 灵雀监控(这个不在 yml 里)——打开 source/js/51la.js,换成你自己的 ID:

1
2
LA.init({ id: "YOUR_51LA_ID", ck: "YOUR_51LA_CK", hashMode: true });
new LingQue.Monitor().init({ id: "YOUR_LINGQUE_ID", sendSpaPv: true });

④ 网站统计页 /site/census/(图表看板,用百度统计开放 API)——配置在 source/js/census.js:

1
2
3
var start_date = '20200101'                     // 统计开始日期
var access_token = 'YOUR_BAIDU_ACCESS_TOKEN' // 百度统计 access_token(30 天有效)
var site_id = 'YOUR_BAIDU_SITE_ID' // 站点 ID

⑤ GitHub 贡献日历(根 _config.yml,默认关闭,因为需要你自己搭数据源):

1
2
3
4
5
gitcalendar:
enable: true # 想用就改成 true
user: yourname # GitHub 用户名
apiurl: "https://gitcalendar.example.com" # 自建的 gitcalendar 服务
jsonurl: "https://cdn.jsdelivr.net/gh/yourname/gitcalendar-data@main/data.json"

8. 美化设置面板(每一项都干什么)

打开方式:右下角齿轮图标。所有设置存在浏览器 localStorage,不写服务器;面板底部有「恢复默认设置」。

分节项目作用
一、显示偏好卡片透明度正文卡片背景的不透明度(0–100%)
背景滤镜对全站背景图做模糊 / 饱和度 / 对比度处理
星空特效(夜间模式)夜间背景上飘的星空粒子
霓虹彩虹(夜间模式)夜间标题的霓虹发光动画
帧率监测左下角 FPS 数字(调试用,平时可关)
雪花特效(白天模式)白天飘雪
右侧部件右下角按钮列的显示/隐藏
顶栏常驻滚动时导航栏是否一直吸顶
侧栏显隐 / 侧栏位置侧栏显示隐藏、放左边还是右边
二、主题色设置13 个预设色red / orange / yellow / green / puregreen / blue / heoblue / darkblue / purple / purepurple / pink / gray / black,点一下全站换色
三、字体设置常规字体 3 款霞鹜文楷(默认)/ 思源宋体 / 霞鹜新晰黑,另有「系统默认」
代码块字体 3 款JetBrains Mono / Fira Code / Source Code Pro
四、背景设置1 风景 · 山野 / 2 风景 · 水与森林 / 3 风景 · 更多三组风景壁纸(各 8 张,走 picsum 公共 CDN)
4 渐变色 / 5 纯色免图片的渐变与纯色背景
6 适配手机竖屏比例的背景图
7 壁纸 API每次刷新随机换一张的在线壁纸接口
8 自定义背景自己粘贴图片链接

改面板本身:

  • 改默认值(访客没动过面板时用什么):改 _config.fomalhaut.yml 的 font / theme_color / background 段,以及 source/js/inject/beauty-boot.js;
  • 改可选列表(加字体、加壁纸、加主题色):改 source/js/modules/settings.js 的 FONT_LIST / CODE_FONT_LIST(第 108–111 行)与面板 HTML(第 845–1050 行),新增字体的 @font-face 写在 themes/fomalhaut/source/css/_custom/custom.css 的「字体引入」一节;
  • 直接关掉面板:beautify.enable: false,然后去掉 inject.bottom 里 settings.js 那一行。

9. 刷新与性能相关开关

1
2
3
4
5
6
7
8
9
10
11
pjax:
enable: true # 站内跳转不整页刷新
instantpage: true # 鼠标悬停在链接上时预加载
lazyload:
enable: true
field: site # site = 全站;post = 仅文章
blur: true
pangu: true # 中英文之间自动加空格
preloader: # 首屏加载动画
enable: false
source: 1 # 1~10,对应 themes/fomalhaut/layout/includes/loading/load_style/

10. AI 助手

右侧悬浮的对话面板,能总结当前页面、解释名词。前端本体在 source/js/ai-chat.js,由 scripts/ai-chat-inject.js 自动注入到每个页面(不改主题源码)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ai_chat:
enable: true # 总开关:false 则不注入按钮和面板
api_base: https://api.deepseek.com
api_key: '' # ⚠️ 直接写 Key 会随页面下发,只建议本地测试
api_key_file: .ai-chat-key # 或把 Key 写进这个文件(已在 .gitignore 里)
model: deepseek-chat # 换模型只改这一行
temperature: 0.7
max_tokens: 8192 # 单次回复上限(含思考模型的 reasoning token)
max_history: 12 # 每次带给模型的历史轮数
max_page_chars: 32000 # 页面正文上限(超长文章取开头 60% + 结尾 35%)
timeout_ms: 10000 # 首字节超时提示
welcome: 你好,我是这个页面的 AI 助手……
first_question: 请用中文总结这个页面的内容:先用一句话概括,再列 3-5 条要点。
system_prompt: |
你是这个博客的页面助手,语气自然、简洁、像朋友聊天。

用法 A:直连服务商(本地 / 内网测试用)——把 Key 放进 .ai-chat-key(站点根目录,一行纯文本)或直接写 ai_chat.api_key。这样 Key 会随页面下发到浏览器,任何人 F12 都能看到,别在公网用。

用法 B:同源代理(公网推荐,仓库已带实现)

  1. 部署平台加环境变量 DEEPSEEK_API_KEY(Vercel:Settings → Environment Variables;Cloudflare Pages:Settings → Environment variables);
  2. 构建时 scripts/ai-chat-inject.js 会自动把前端的 api_base 改成 /api、Key 换成占位符 via-proxy;
  3. 请求打到 api/chat/completions.js(Vercel)或 functions/api/chat/completions.js(Cloudflare Pages),由它在服务端读环境变量再去请求服务商。

代理函数自带:每 IP 限流、max_tokens 上限(MAX_TOKENS_CAP = 8192)、CORS 白名单。改白名单两种方式:

1
2
3
4
5
6
7
# 方式一:改两个常量(api/ 与 functions/ 两份都要改)
const DEFAULT_ORIGINS = 'https://example.com,https://www.example.com'
const DEFAULT_SUFFIXES = 'example.com'

# 方式二:不改代码,用环境变量覆盖
AI_PROXY_ORIGINS=https://your-domain.com
AI_PROXY_ALLOW_SUFFIXES=your-domain.com

换成别的大模型:api_base 改成服务商地址(如 https://api.openai.com、https://api.moonshot.cn),model 改成对应模型名;代理函数里的 Authorization: Bearer <key> 是 OpenAI 兼容格式,大多数国内厂商都通用。

关掉它:ai_chat.enable: false 即可。

11. 友人帐 / 朋友圈 / 画廊等页面

页面入口文件数据来源
友人帐(友链)source/social/link/index.mdsource/_data/link.yml
朋友圈source/social/fcircle/index.mdhexo-circle-of-friends 产出的静态 JSON
画廊source/box/gallery/index.md + wallpaper/index.md页面内 Markdown 图片
网址导航source/box/nav/index.md页面内 HTML + source/box/nav/icons/ 图标
关于source/personal/about/index.md页面内 HTML,样式在 source/css/about-page.css
旧时光(时间线)source/site/time/index.md{% timeline %} 标签
八音盒source/life/music/index.mdMeting API + 网易云歌单 ID
天文星图source/box/astronomy/voyager.html独立 HTML,skip_render 不参与渲染

友人帐怎么加人:编辑 source/_data/link.yml:

1
2
3
4
5
6
7
8
- class_name: 小伙伴们🍭
class_desc: 交换友链请在友人帐页面留言
link_list:
- name: 示例站点
link: https://example.com/
avatar: https://example.com/avatar.jpg # 建议 100x100 以内
descr: 一句话介绍
siteshot: https://example.com/shot.jpg # 可选,站点截图

友人帐有三种样式,改 flink_style: volantis(可选 butterfly / volantis / flexcard)。

12. 页脚与页脚徽标

页脚模板在 themes/fomalhaut/layout/includes/footer.pug,四块内容:

  1. 格言 + 猜你想看(第 1–31 行):文案与链接直接写在 pug 里;
  2. 推荐友链 小头像格(第 32–59 行):硬编码的展示位,换成你自己的朋友即可(头像建议 100×100 以内);source/js/inject/ft-ad-extra.js 会在末尾再补一个「广告位招租」凑成 4+4 两排;
  3. 版权行 / 已运行天数 / 摸鱼徽章(第 60–85 行):文字来自 footer.owner 与 footer.custom_text;
  4. 徽章列 p#ghbdages(第 86–113 行):两种来源——
    • 本地 SVG:放在 source/assets/badge/,用 /assets/badge/xxx.svg 引用;
    • shields.io 动态徽章:https://img.shields.io/badge/左侧文字-右侧文字-颜色.svg,文字里的空格写成 _,颜色可用十六进制(去掉 #)。

增删一行徽章的写法:

1
2
a.github-badge(target='_blank' href='https://hexo.io/' style='margin-inline:5px' title='博客框架为 Hexo')
img(src='https://img.shields.io/badge/Frame-Hexo-blue.svg' alt='')

改完 .pug 记得重启 hexo server,Hexo 只在启动时读模板。

✍️ 怎么开始写文章

新建文章

1
2
hexo new post "文章标题"        # 按 scaffolds/post.md 生成 source/_posts/YYYY-MM-DD-文章标题.md
hexo new draft "草稿标题" # 生成到 source/_drafts/,加 --publish 才进入正式列表

或者直接在 source/_posts/ 里新建一个 .md 文件——文件名建议用 YYYY-MM-DD-标题.md(由 _config.yml 的 new_post_name 决定)。

文章网址由 permalink: posts/:abbrlink.html 自动生成一串哈希(hexo-abbrlink 插件),所以改标题不会改变已发布文章的网址。

Front-matter 全字段说明

写在文件开头 --- 之间:

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
---
title: 文章标题 # 必填
date: 2026-10-01 10:00:00 # 必填,发布时间
updated: 2026-10-02 10:00:00 # 可选,更新时间(不写则按文件修改时间)

description: 一句话摘要 # 可选,首页卡片与搜索引擎摘要
keywords: 关键词1,关键词2 # 可选

categories: # 分类(可多个)
- 开始使用
tags: # 标签(可多个)
- Hexo
- Fomalhaut

cover: https://picsum.photos/id/1015/1200/675 # 卡片封面;不写则从 cover.default_cover 随机取
top_img: /assets/head.jpg # 文章页顶部大图;不写则跟随 default_top_img
randomcover: false # true = 每次刷新从 default_cover 随机换一张

sticky: 1 # 置顶(数值越大越靠前);也可在正文写 <!-- sticky -->

toc: true # 是否显示右侧目录
toc_number: true # 目录是否带序号
toc_expand: false # 目录默认是否展开
toc_style_simple: false # 简洁目录样式

comments: true # 本文是否开启评论
aside: true # 本文是否显示侧栏
highlight_shrink: false # 代码块默认折叠

copyright: true # 是否显示版权卡片
copyright_author: 你的名字
copyright_author_href: https://example.com/
copyright_url: https://example.com/posts/xxx.html
copyright_info: 转载请标明出处

mathjax: true # 本文启用 MathJax 公式
katex: false # 本文启用 KaTeX(二选一)
mermaid: true # 本文启用 Mermaid 图表
aplayer: true # 本文启用 APlayer 音乐
---

只写需要的字段即可,其余留空就是默认行为。

加一个新页面

  1. 在 source/ 下建目录(例如 source/tools/),里面放 index.md:
1
2
3
4
5
6
7
---
title: 工具箱
date: 2026-10-01 10:00:00
comments: false
---

这一页的正文……
  1. 在 _config.fomalhaut.yml 的 menu: 里加一项:工具箱: /tools/ || fas fa-toolbox。

页面里可以直接写 HTML,想让样式单独成文件就写到 source/css/xxx.css,再在 inject.head 里加一行 <link>。

图片怎么放

方式写法适用
站内相对路径![描述](/assets/pic.jpg)图片放 source/assets/
同目录相对路径![描述](./pic.jpg)需要在 _config.yml 打开 post_asset_folder: true
外链 / 图床![描述](https://your-cdn.com/pic.jpg)图片多时推荐

分类与标签

  • 分类与标签不用提前创建,Front-matter 里写了就会自动生成 /categories/xxx/、/tags/xxx/;
  • 分类页与标签页的版式由 category_ui / tag_ui 控制(留空默认,填 index 为卡片式);
  • 首页的「小冰分类磁贴」由根 _config.yml 的 magnet 段控制,display 列表里的 name 必须与文章分类名一致。

🔧 最常改的地方(速查)

我想改……去哪改
站点名 / 作者 / 域名 / 部署仓库根 _config.yml 的 title / author / url / deploy
首页标题下的副标题_config.fomalhaut.yml 的 subtitle
主题色_config.fomalhaut.yml 的 theme_color.main,或让访客用面板自己选
头像_config.fomalhaut.yml 的 avatar.img(默认 /assets/avatar.webp)
首页大图index_img;全站背景改 inject.head 里 #defineBg 那行的 --default-bg
文章默认封面池cover.default_cover
顶部导航menu
页脚文案 / 版权 / 徽章themes/fomalhaut/layout/includes/footer.pug(改完重启 server)+ footer.owner / footer.custom_text
侧栏卡片开关aside 段
评论区comments.use + 对应系统的段(如 twikoo.envId)
统计 IDbaidu_analytics 等;51LA 在 source/js/51la.js
AI 助手ai_chat 段
字体themes/fomalhaut/source/css/_custom/custom.css 的「字体引入」+ source/js/modules/settings.js 的 FONT_LIST
社交图标social(格式:名称: 链接 || 图标类名 || 动画类名)
首页轮播根 _config.yml 的 swiper 段
首屏加载动画preloader(样式在 themes/fomalhaut/layout/includes/loading/load_style/)
文章置顶文章 Front-matter 写 sticky: 1

🏷 外挂标签速查

主题注册的全部标签(实现都在 themes/fomalhaut/scripts/tag/):

标签用法说明
note{% note info flat %}文字{% endnote %}提示块。样式:default/primary/success/info/warning/danger;形状:flat/modern/simple/disabled
tabs{% tabs 组名 %} + <!-- tab 标题 -->标签页,支持 subtabs / subsubtabs 嵌套
timeline{% timeline 标题 %} + <!-- timeline 日期 -->时间线
btn{% btn 链接, 文字, 图标, 选项 %}按钮。选项:color outline center block larger
label{% label 文字 颜色 %}行内小标签
gallery{% gallery %} … {% endgallery %}相册(带灯箱)
galleryGroup{% galleryGroup '名称' '描述' '/链接' 封面图 %}相册分组入口
mermaid{% mermaid %}graph LR; A-->B;{% endmermaid %}Mermaid 图表
flink{% flink %}读取 source/_data/link.yml 渲染友人帐
hideToggle{% hideToggle 标题 %}内容{% endhideToggle %}折叠块,另有 hideInline / hideBlock
inlineImg{% inlineImg 图片链接 宽度 %}行内小图

注意标签名:是 btn 不是 button,也没有 span,写错会报 unknown block tag。

现成的例子见仓库里的 source/_posts/2026-10-02-外挂标签速查.md。

🌐 部署

方案 A:GitHub Pages + GitHub Actions(推荐,仓库已带工作流)

  1. 把仓库推到你自己的 GitHub 账号;
  2. 在仓库 Settings → Secrets and variables → Actions 里按需添加密钥;
  3. 修改 .github/workflows/autodeploy.yml 里的 repository-name 为 你的用户名/你的用户名.github.io;
  4. 推送到 main 分支,或在 Actions 页面手动 Run workflow。

方案 B:Vercel —— npx vercel,首次会引导你关联项目。仓库根目录的 vercel.json 已声明 AI 代理函数的超时与内存。

方案 C:Cloudflare Pages —— 构建命令 hexo clean && hexo generate && gulp,输出目录 public。

方案 D:本地生成 + 手动推送 —— hexo clean && hexo generate && gulp,然后把 public/ 推到任意静态托管。

❓ 常见问题

Q:执行 hexo server 报找不到主题?
确认 _config.yml 里的 theme: 值与 themes/ 下的目录名一致(默认 fomalhaut)。

Q:改了 themes/ 下的 .pug 文件没生效?
重启 hexo server。Hexo 只在启动时读取模板;改样式与文章则不需要重启。

Q:_config.fomalhaut.yml 和 themes/fomalhaut/_config.yml 改哪个?
改根目录的 _config.fomalhaut.yml。主题目录里那份只是默认值模板,会被根目录那份覆盖。

Q:首页文章列表没有封面图?
在文章 Front-matter 写 cover: 图片链接,或在 cover.default_cover 里配置封面池。

Q:字体 / 图片挂了?
默认走公共 CDN(cdn.jsdelivr.net 的 @fontsource/* 与 picsum.photos)。若网络访问不畅,把 custom.css 里的 @font-face 换成你自己的字体,把 cover.default_cover 换成你自己的图床即可。

Q:美化面板的颜色/字体改了,下次打开又变回默认?
设置存在浏览器 localStorage。换了域名、清了浏览器数据或改了 storage_key 就会重置,属于正常行为。

🙏 授权与致谢

  • 本项目基于 hexo-theme-butterfly(Apache-2.0,作者 Jerry)二次开发,继续沿用 Apache-2.0 协议,themes/fomalhaut/LICENSE 保留了上游许可证;
  • 部分美化思路参考了 Hexo 社区的公开方案(akilar、anzhiyu 等),在此致谢;
  • 示例图片来自 picsum.photos,字体来自 jsDelivr 上的 @fontsource/* 开源字体包(全部为 SIL OFL 许可);
  • 仓库里的示例数据(域名、邮箱、友链、统计 ID)均为占位内容,请替换为你自己的。

📚 相关文章

🌟 Star 概况

Star History Chart

本文章会长期更新。安装或使用中遇到问题,欢迎在评论区留言,或者直接去 GitHub 仓库 提 Issue。