这篇文章记录我把 Hexo 博客改造成“作品展柜”的全过程:主页不再是最近文章,而是项目入口;项目页用 Stellar 的数据卡片组管理;全站换成黑 + 红的极客风;并通过 custom.css 精准覆盖主题样式(包括卡片尺寸、间距、文字行数、侧边栏变黑等)。


1. 总体结构:把博客改成“展柜”

传统博客默认首页是文章列表,但展柜更需要:

  • Projects:一眼进项目(Unity / UE / Web / Toolchain)
  • Play:可直接玩(在线 demo)
  • Tech Blog:只保留能证明工程能力的文章(性能 / 架构 / 网络 / 工具)
  • About / Resume:一页内完成“你是谁 + 联系方式 + 简历下载”

因此我做了两件事:

  1. **主页 /**:改成自定义 Landing Page(项目入口 + 精选文章 + 外链)。
  2. 文章列表:移动到 /blog/(或 /tech/),把“最近文章”从首页移走。

2. 文章列表从首页挪走:生成 /blog/

Hexo 的文章列表由 index_generator 生成(配置在站点根目录 _config.yml):

index_generator:
path: blog
per_page: 10
order_by: -date

生成物会出现在:

  • public/blog/index.html
  • 预览地址:http://localhost:4000/blog/

注意:不要盯着 source/blog/ 看——source 是源文件目录,真正生成在 public


3. 用 Stellar 的“数据卡片组”管理项目入口

3.1 数据文件位置

卡片数据写在:

  • source/_data/links/*.yml

例如 Unity 分组:

  • source/_data/links/projects_unity.yml

3.2 页面渲染

在页面里用一行即可渲染整组卡片(这里为了避免 Hexo 把模板语法当成 Swig 标签解析,我用实体字符显示):

  • {% sites projects_unity %}

projects_unity 对应 projects_unity.yml 文件名。)

3.3 一条卡片数据示例

- title: "Farmix——安卓体感街机"
url: "/projects/farmix/"
description: "Qix-like 领地占领:闭合判定+FloodFill/BFS;多敌人规则;LevelConfig 数据驱动关卡;Android 体感输入与完整游戏流。"
cover: "/images/projects/farmix_cover.jpg"
icon: "/images/icons/farmix.png"

经验总结:

  • title:项目名 + 一句话类型
  • description:先写成果/亮点,再写职责,再写关键词(面试官扫一眼就懂)
  • cover/icon:尽量统一尺寸与比例,视觉更像“展柜”

4. 自定义首页:写 source/index.md

我将首页改成自定义 Landing,核心是:

  • Projects 大入口(占整行、整块可点)
  • 下方两块并排:技术文章精选 + 外链/在线游玩

4.1 避坑:HTML 被当成代码块

Markdown 里如果 HTML 每行前面有 4 个空格,会被当成代码块显示。解决方式:

  • HTML 全部顶格写(不缩进)
  • 或者用 raw 容器包住(同样用实体字符展示,避免被 Hexo 当模板执行):
    • {% raw %} … {% endraw %}

4.2 避坑:不要在 md 里用 url_for

我曾经在 index.md 里写过类似下面的模板函数(用实体字符展示):

  • {{ url_for(‘projects/‘) }}

结果 hexo g 会报错(url_for 在页面 Markdown 的渲染上下文里不可用)。
最终我采用最稳方案:用相对链接

  • projects/
  • blog/
  • files/
  • about/

这样无论线上是 https://xxx.github.io/repo/ 还是本地,都不容易因为 root 不一致而跳错路径。


5. 全站黑红主题:优先用 _config.stellar.yml,再用 CSS 兜底

5.1 全局切暗色主题

style:
prefers_theme: dark

这样文章页、子页面、侧边栏都走深色体系,而不是只有首页“像暗色”。

5.2 改主题色为红

style:
color:
theme: 'hsl(0 90% 58%)'
accent: 'hsl(0 100% 62%)'
link: 'hsl(0 90% 60%)'

6. 为什么侧边栏会“发粉”?以及我怎么修

侧边栏发粉/发紫的根因通常是:

  • 左栏是 半透明 + blur(毛玻璃)
  • 背景有红色辉光/渐变
  • blur 会把背景颜色采样进来,饱和度一高就容易变粉

解决思路:

  1. 提高左栏不透明度(减少背景污染)
  2. 降低/关闭左栏 blur(避免采样)
  3. 必要时用 custom.css 强制覆盖

配置层(示例):

style:
leftbar:
background-image: none
background-color: 'rgba(10,10,14,0.92)'
background-opacity: 1
blur-px: 0px
blur-bg: 'rgba(0,0,0,0)'

7. CSS 覆盖:卡片间距、封面比例、文字行数、侧边栏黑化

我把所有自定义样式集中到:

  • source/css/custom.css

并通过主题的 inject 把它注入到 <head>(同理,这里用正常字符串,不写模板函数):

inject:
head:
- '<link rel="stylesheet" href="/css/custom.css">'

7.1 卡片之间留空隙

.tag-plugin.sites-wrap .grid-box {
gap: 18px !important;
}

7.2 封面比例:360×160(用 aspect-ratio 最稳)

.tag-plugin.sites-wrap .site-card .lazy-box.snapshot {
aspect-ratio: 360 / 160;
height: auto !important;
overflow: hidden;
border-radius: 14px;
}
.tag-plugin.sites-wrap .site-card .lazy-box.snapshot img {
width: 100% !important;
height: 100% !important;
object-fit: cover;
}

7.3 文字显示更多行(标题/描述)

.tag-plugin.sites-wrap .site-card span.title {
display: -webkit-box !important;
-webkit-box-orient: vertical !important;
-webkit-line-clamp: 2 !important;
overflow: hidden !important;
white-space: normal !important;
}

.tag-plugin.sites-wrap .site-card span.desc {
display: -webkit-box !important;
-webkit-box-orient: vertical !important;
-webkit-line-clamp: 3 !important;
overflow: hidden !important;
white-space: normal !important;
}

7.4 侧边栏统一成黑(兜底)

aside.l_left, .l_left {
background: rgba(10,10,14,0.92) !important;
background-image: none !important;
-webkit-backdrop-filter: none !important;
backdrop-filter: none !important;
}

8. 复现清单(给未来的我)

  • _config.yml:把文章列表生成到 /blog/
  • _config.stellar.yml:强制暗色 + 红色主题色 + 左栏背景
  • source/index.md:Landing Page(不要缩进 HTML;不要用 url_for
  • source/_data/links/*.yml:项目卡片数据源
  • source/css/custom.css:统一样式(卡片/侧边栏/暗色氛围)
  • source/files/*.pdf / *.apk:简历与下载文件(页面里用 files/xxx.pdf 相对链接)

9. 结语:为什么这也算“工程能力”

这套改造看起来是“搭站”,但本质上和客户端开发很像:

  • 把需求拆成可验证的模块(路由/内容/样式/构建)
  • 找到稳定的接口(配置优先,CSS 兜底)
  • 对不可控的环境差异(root、缓存、markdown 转义、模板变量)做降风险设计
  • 使用一致的“约束与规范”(卡片字段、封面比例、信息密度格式)

最终得到的是一个面试官友好的作品展柜:入口明确、证据集中、风格统一。