Astro Theme Inkstone:给 Obsidian 写作者的一方砚台

Astro Theme Inkstone:给 Obsidian 写作者的一方砚台 封面图

我把最近这套博客主题单独抽出来,整理成了一个可以复用的开源项目:Astro Theme Inkstone

它的定位很明确:给喜欢在 Obsidian 里写作、希望用 Astro 发布静态博客的人,一个安静、耐看、中文友好,而且不需要维护复杂后端的主题起点。

项目地址:github.com/moxiaonai/astro-theme-inkstone

为什么叫 Inkstone

Inkstone 是“砚台”。

我很喜欢这个意象。一个博客主题不应该只是某种短期视觉效果,它更像一件长期放在桌上的写作器物:稳定、克制、耐看,最好还能让你愿意反复打开它,慢慢写,慢慢改,慢慢沉淀。

这个名字里有三层意思:

  • Ink 是写作、表达和知识流动。
  • Stone 是稳定、克制和长期维护。
  • Obsidian-friendly 则对应本地 Markdown 知识库和静态发布工作流。

如果你想搭一个中文技术博客,既能写文章,也能放项目、归档、标签、搜索和 RSS,Inkstone 会是一个很轻的起点。

它解决的不是“怎么建站”,而是“怎么长期写”

很多博客模板第一眼很好看,但真正写一段时间后,问题会变成这些:

  • 文章文件放在哪里才舒服?
  • 图片怎么管理,才能同时适配 Obsidian 和线上站点?
  • 标签、归档、搜索、RSS 要不要自己补?
  • 站点信息、导航、项目卡片改起来会不会散落在各处?
  • 深浅色切换、SEO、sitemap、llms.txt 这些细节要不要反复重做?

Inkstone 的目标是把这些常见问题先整理好。你可以直接把项目根目录作为 Obsidian vault 打开,在 src/content/blog 写 Markdown / MDX,把图片放进 public/images/posts,然后交给 Astro 构建成纯静态站点。

写作仍然发生在本地,发布则保持简单。

适合谁

它更适合这些场景:

  • 你习惯用 Obsidian 管理草稿、笔记和文章。
  • 你想要一个静态博客,而不是数据库驱动的 CMS。
  • 你主要写中文技术文章,希望排版、行距和阅读宽度默认舒服。
  • 你希望博客自带标签、归档、搜索、项目页、RSS 和 SEO。
  • 你不想把主题做得很重,但希望它有一点视觉记忆点。
  • 你希望未来可以部署到 Cloudflare Pages、Vercel、Netlify 或 GitHub Pages。

它不是一个大型内容平台,也不追求把每个功能都做成配置项。它更像一套清晰的博客骨架:默认能用,结构容易读,样式容易改。

核心功能

Inkstone 目前包含一套完整的个人博客页面:

  • 首页
  • 博客列表
  • 文章详情
  • 标签页
  • 年份归档
  • 项目页
  • 搜索页
  • 关于页
  • 赞助页
  • RSS
  • sitemap
  • robots
  • llms.txt
  • content-index.json

文章由 Astro Content Collections 管理,frontmatter 支持标题、摘要、发布日期、更新日期、标签、封面图、草稿状态和精选标记。

---
title: "文章标题"
description: "一句话摘要"
pubDate: 2026-09-20
updatedDate: 2026-09-20
tags: ["Astro", "Obsidian", "Markdown"]
draft: false
cover: "/images/posts/example.png"
featured: false
---

为了方便在 Obsidian 里先写草稿,缺少标题、缺少发布日期,或者设置了 draft: true 的文章不会进入公开文章列表。

Light / Dark 的视觉细节

主题内置 Light / Dark 双主题,支持系统偏好、用户手动选择和 localStorage 持久化。

我给主题切换加了一个从按钮位置展开和收起的动画。它不是简单淡入淡出,而是更像一滴墨从右上角扩散出来:切到深色时,暗色页面从按钮处铺开;切回浅色时,旧的暗色页面再收回按钮附近。

这个效果原本可以用 View Transition API 做,但我在实际调试里遇到过 dark 到 light 时短暂闪黑的问题。最后改成了自绘 DOM 遮罩:用一个临时层克隆当前页面,再通过 clip-path: circle(…) 控制圆形范围。这样动画方向可控,也避开了浏览器截图层带来的偶发闪烁。

这也是 Inkstone 视觉上比较有记忆点的一处细节:它不抢内容,但在你切换主题时,会让主题的名字和气质对上。

本地搜索和内容发现

Inkstone 的搜索是纯本地搜索。构建时生成文章索引,前端直接搜索标题、摘要、日期和标签,不需要 Algolia、数据库或第三方服务。

同时,它默认补好了面向搜索引擎、社交平台和 AI 工具的内容发现入口:

  • canonical URL
  • Open Graph
  • Twitter Card
  • 文章 JSON-LD
  • RSS
  • sitemap
  • robots
  • llms.txt
  • content-index.json

其中 llms.txt 会输出站点说明、核心页面、文章列表、标签和项目;content-index.json 则提供结构化内容索引,方便 AI 工具读取和引用。

快速开始

推荐使用 Node.js 20+ 和 pnpm 10+。

git clone git@github.com:moxiaonai/astro-theme-inkstone.git
cd astro-theme-inkstone
pnpm install
pnpm dev

启动后访问:

http://127.0.0.1:4321/

常用命令:

pnpm dev       # 本地开发
pnpm build     # 构建静态站点到 dist
pnpm preview   # 本地预览构建结果
pnpm obsidian  # macOS 下用 Obsidian 打开当前目录

怎么改成自己的博客

大多数个性化配置集中在 src/theme/site.ts。你通常先改这里,就能替换站点标题、作者、域名、导航、首页文案、项目卡片和友情链接。

常见入口如下:

想修改文件
站点标题、副标题、描述、域名src/theme/site.ts
作者名、作者页地址src/theme/site.ts
首页 Hero 文案src/theme/site.ts
导航菜单src/theme/site.ts
社交链接src/theme/site.ts
项目卡片src/theme/site.ts
颜色、字体、间距、圆角src/theme/styles/theme.css
Header、Footer、Logo、卡片组件src/theme/components/*
文章内容src/content/blog
文章图片public/images/posts
项目图片public/images/projects

部署前记得把 site.urlastro.config.mjs 里的 site 改成你的真实域名。它会影响 canonical URL、RSS、sitemap、Open Graph 图片和 llms.txt 中的链接。

项目结构

.
├── .obsidian/
│   └── app.json
├── public/
│   ├── _redirects
│   ├── favicon.svg
│   └── images/
│       ├── posts/
│       ├── projects/
│       ├── site/
│       └── theme/
├── src/
│   ├── content/
│   │   └── blog/
│   ├── layouts/
│   ├── lib/
│   ├── pages/
│   └── theme/
│       ├── components/
│       ├── styles/
│       ├── site.ts
│       └── README.md
├── astro.config.mjs
├── package.json
└── README.md

这套结构的重点是把“内容”和“主题”分清楚:文章在 src/content/blog,主题组件和样式在 src/theme,站点配置集中在 src/theme/site.ts。后面无论是写文章、换图片,还是调整视觉,都比较容易找到入口。

我希望它保持什么样

Inkstone 会尽量保持轻量。能用 Astro、Markdown、CSS 和少量原生 JavaScript 解决的事情,就不引入额外依赖。

我希望它长期保持这几个方向:

  • 中文阅读体验优先。
  • 本地写作流程优先。
  • 静态部署优先。
  • 结构清晰,方便自己二次修改。
  • 对搜索引擎、RSS 阅读器和 AI 工具友好。
  • 视觉安静,但有一点自己的性格。

如果你也想把 Obsidian 里的内容发布成一个长期维护的个人站点,可以直接拿它开始改。

项目地址在这里:Astro Theme Inkstone