Menu
Avatar
The menu of my blog
Quick Stats
Quests
30 Quests
Messages
2 Messages
Playback
5 Playback
Items
6 Items
Skills
2 Skills
Trace
1 Trace
Message

The Sword Art Online Utilities Project

Welcome, traveler. This is a personal blog built in the style of the legendary SAO game interface. Navigate through the menu to explore the journal, skills, and item logs.

© 2020-2026 Nagi-ovo | RSS | Breezing
← Back to Quest Log
从头写一个博客:我的 Passion 还在吗?
从头写一个博客:我的 Passion 还在吗?

圆十年前的一个梦,SAO 主题博客的制作和博文语法记录

2026年1月1日 12 min read
designmdsvexsveltekit

Human-Crafted

Written directly by the author with no AI-generated sections.

前言

还记得我真正意义上写的第一行代码就是一个单 html 文件的个人博客,仅仅是标题叫“个人博客”,然后后面经历了:

  • 2023 Hexo + Github Pages
  • 2024 - 2025 xLog

由于从 25 年年初开始 xLog 的服务越来越不稳定,我便提前导出了全部文件,随时准备迁移到别处。等我想到并下定决心“自己写一个”的时候已经还差两天就到 2026 了,这对于一个三分钟热度的 ADHD 来说在之前是真的无法完成的任务,还好 2025 是“Agent 元年”(最好是),Code Agent 比去年年底强大了太多,我已经从“trust 对话式编程 only”成功过渡到了接纳 Agent 接管编程的心态。

那还说什么,Antigravity + Cursor + Codex 启动!这些工具在 Gemini 3.0 Pro/Flash, Claude 4.5 Opus/Sonnet, GPT-5.2-Extra-High 几元大将的加持下已经到了几个月前的我无法想象的水平。

设计思路

打开 Antigravity 很突然地脑海里出现了这幅图:

kirito-2025

那就做一个刀剑神域主题的博客吧!

想到这儿大脑里就开始渲染各种设计,然后尝试靠 AI 把它的原型做出来。

技术栈

核心是 SvelteKit + MDsveX,这个组合能让我在 Markdown 里直接写 Svelte 组件,非常灵活。

代码高亮用的是 rehype-pretty-code + Shiki,支持行号、行高亮、代码折叠等功能。表格和任务列表这些 GitHub 风格的 Markdown 扩展也都支持,通过 remark-gfm 插件实现。

样式方面用的是 SCSS,没有引入 Tailwind 之类的框架。好吧其实是写 Plan 的时候忘了跟 LLM 说,那就正好试试重归刚学前端时对着 live server 一行行敲过的 css 吧


写在最后

在自己写博客框架的过程中,有无数次推倒某一个设计重来或者临时增加一个组件的念头,但我都…选择了执行那些念头,这对于立下年前迁移完博客 flag 的我来说相当痛苦,但是回过头来看也趣味无穷。本来想说这辈子应该很难有第二次类似的经历了,但又想了下,其实这都是说明我还对这些充满 passion 的证据,我肯定还会经历很多这样有趣的事!

Just for fun.

后面就全都是给我以后看的了,因为没有专门做一个写文章的入口,后面得手敲各种格式,很容易忘记。

写作指南(给未来的我)

这里是本博客(SvelteKit + MDsveX)的“写作速查表”:路径约定、frontmatter、Markdown 扩展、数学公式、代码块增强、媒体与组件,以及常见坑。

0. 快速开始(Checklist)

  • 新建文章:src/lib/content/blog/<YYYY>/<slug>.md
  • 英文版:src/lib/content/blog/<YYYY>/<slug>.en.md(同 slug,后缀是语言)
  • 资源目录:static/assets/... 会映射到站点根路径 /assets/...
  • 访问地址:/<slug>(slug=文件名;全站唯一,别在不同年份重名)
  • 本地预览:bun run dev → http://localhost:5173/<slug>

1. Frontmatter(元数据)

约定字段(按页面展示/列表排序的实际使用情况整理):

字段必填类型作用
title✅string文章标题
excerpt✅string列表卡片 + SEO 描述(建议 ≤ 180 字符)
date✅string排序依据(建议 ISO:YYYY-MM-DD 或带时区的完整时间)
tags✅string[]标签筛选
readTime✅number阅读时间(分钟,手填)
cover⭕string封面图路径(/assets/...)
creationMethod✅independent / ai-assisted文章创作方式标签
lastUpdated⭕string最近更新日期(显示“Last updated”)
translated⭕string仅翻译稿填写:会弹窗提示“该文章由 xxx 翻译”

模板:

---
title: "文章标题"
excerpt: "简短摘要(建议 ≤ 180 字符)"
date: "2026-01-01"
tags:
  - 标签一
  - 标签二
readTime: 10
cover: "/assets/images/posts/2026/my-post/cover.png"
creationMethod: independent
lastUpdated: "2026-01-01"
# translated: "GPT-5.2" # 仅翻译稿需要
---

2. Markdown 基础 + GFM 扩展

本项目启用了 remark-gfm,除了基础 Markdown 以外,还支持表格/任务列表/删除线/自动链接等 GitHub 风格语法。

标题(自动生成锚点)

标题会自动生成 id,并且整段标题可点击跳转(rehype-slug + rehype-autolink-headings)。要引用某一小节,直接复制浏览器里带 #xxx 的 URL 即可。

列表与任务列表

  • 无序列表、嵌套列表、以及有序列表都正常支持
  • 任务列表(GFM):
- [ ] TODO
- [x] Done

链接

  • 普通链接:[Svelte](https://svelte.dev)
  • 想强制新标签页打开:用 HTML(记得加 rel):
<a target="_blank" rel="noopener noreferrer" href="https://svelte.dev">Svelte</a>

表格

功能用途备注
表格数据对比来自 GFM
任务列表TODO来自 GFM
数学公式技术写作KaTeX 渲染

脚注(可选)

这里是一句话[^1]

[^1]: 这里是脚注内容。

3. 数学公式(KaTeX)

已启用 remark-math + rehype-katex-svelte,支持行内与行间公式:

  • 行内:$E = mc^2$ → E=mc2E = mc^2E=mc2
  • 行间:
Rt=∑k=0∞γkrt+kR_t = \sum_{k=0}^{\infty} \gamma^k r_{t+k}Rt​=k=0∑∞​γkrt+k​

4. 代码块增强(Shiki + rehype-pretty-code)

代码块自带语法高亮 + 复制按钮,并支持标题、行号、高亮行、折叠行:

example.js
const items = [
  { name: "Item A", price: 100 },
  { name: "Item B", price: 200 },
  { name: "Item C", price: 300 },
];
 
const total = items.reduce((sum, item) => sum + item.price, 0);
console.log(`Total: ${total}`);
  • title="example.js":代码块标题(文件名)
  • showLineNumbers:显示行号
  • {2,5}:高亮第 2 行与第 5 行(支持区间:{2-6,10})
  • 复制按钮:悬浮到代码块右上角即可看到

代码折叠(按行)

对“长配置/不重要片段”可以折叠,支持逗号与区间:

theme-tokens.css
:root {
  /* 主色调 */
  --sao-orange: #f5a623;
  --sao-blue: #0ea5e9;
  
  --blog-code-bg: #1c1b2f;
  
  /* 折叠的部分 */
  --blog-code-border: rgba(245, 166, 35, 0.32);
  --blog-inline-code-bg: rgba(245, 166, 35, 0.18);
  --blog-code-highlight: rgba(245, 166, 35, 0.16);
  --blog-code-lineno: #b5b7cd;
  --blog-code-shell: linear-gradient(135deg, rgba(28, 27, 47, 0.96), rgba(21, 23, 39, 0.9));
  --blog-code-line: rgba(255, 255, 255, 0.08);
  --blog-code-text: #eaeaf6;
}

fold={8-15} 会把第 8 到 15 行默认隐藏,读者可点击代码块左下角的提示展开/收起。

5. 图片(自动 WebP + Lazyload)

推荐把图片放在:static/assets/images/posts/<YYYY>/<slug>/...,引用时用绝对路径:

![alt](/assets/images/posts/2026/my-post/figure-1.png)

本项目会在构建阶段把本地 .png/.jpg/.jpeg 图片自动包一层 <picture>,并尝试加载同名 .webp(有就用,没有就回退原图)。批量生成 WebP:

bun run convert-webp

另外,图片默认会补上 loading="lazy" 与 decoding="async"(你手动写 <img loading="eager" ...> 可以覆盖)。

想控制居中/宽度,用 HTML 更省事:

<p align="center">
  <img src="/assets/images/posts/2026/my-post/demo.png" alt="demo" width="70%" />
</p>

6. 视频嵌入(YouTube 示例)

建议用“自适应比例”的写法,移动端不容易溢出:

只需要把视频 ID 替换到 embed/ 后面即可。

7. 音乐播放器(GeoMusicPlayer)

博客内置了一个音乐播放器组件(QQ 音乐 + YouTube 双源,会根据网络环境自动选择):

Initializing Link...

使用方法:

  1. 在文章开头的 <script> 标签里导入组件:import GeoMusicPlayer from '$lib/components/GeoMusicPlayer.svelte';
  2. 在需要的位置插入组件标签,填入相应参数

参数说明:

  • qqMusicSongId: QQ 音乐的歌曲 ID
  • youtubeVideoId: YouTube 视频 ID
  • songTitle: 歌曲标题(同时作为全局播放器的 key)
  • coverExtension: 封面图扩展名(对应 static/music-covers/<songTitle>.<ext>)
  • autoplay: 是否自动播放(布尔值)

8. 在 Markdown 里写 Svelte(MDsveX)

基本规则

  • <script> 建议放在 frontmatter 下面(越靠上越稳)
  • 正文里可以直接写组件标签/HTML(会被当成 Svelte 渲染)
  • 普通 Markdown 文本里尽量不要写 {count} 这种插值(会被当作文本转义);要用插值就包进一个节点里,例如 <span>{count}</span>

一个最小交互例子

这是一个实时计数器演示

一个坑:不要用 HTML 的 onclick

构建阶段会移除 onclick/onClick 属性(主要是为了代码块复制按钮的安全处理)。如果要交互,优先用项目里通用的 onmousedown={...}(或 Svelte 的 on:click={...})。

9. 分割线

使用三个连字符创建分割线:


10. 多语言(中文/英文)

同一篇文章的多语言版本通过文件名后缀识别:

  • 中文:<slug>.md(默认)
  • 英文:<slug>.en.md

英文版如果是“翻译稿”,在 frontmatter 里加 translated: "xxx" 会自动弹出翻译提示。

Article Info Human-Crafted
Title 从头写一个博客:我的 Passion 还在吗?
Author Nagi-ovo
URL
Last Updated No edits yet
Citation

商业转载请联系站长获得授权;非商业转载请注明出处并附上本文链接。

你可以复制、分发并改编本文,但衍生作品需采用相同许可协议。本文采用 CC BY-NC-SA 4.0 授权。

Session 00:00:00