过去一段时间,我把自己的个人网站逐步扩展成了三个可以真实使用的阅读终端:面向公开访问与搜索的 PC / 移动网站、适合微信内快速浏览的 微信小程序,以及强调沉浸阅读、收藏与离线能力的 原生 macOS 桌面应用。
它们不是三份各自维护的内容,也不是把网页简单套进不同尺寸的壳。文章只在网站项目中维护一次,再由不同客户端通过边界清晰的只读 API 获取适合自己的数据。共享的是内容事实,分开的是交互、信息密度、缓存方式与产品职责。
现在就使用
访问 houhuiyang.com · 下载“代码与产品札记”macOS 1.0.0(macOS 14+)
macOS 安装包 SHA-256:7a45940a1278f366f452467b766372e5a693f1d144b0be525c902461d38511e9
为什么要做三个版本
同一位读者在不同场景里的需求并不相同。
在电脑浏览器中,他可能从搜索引擎进入,希望看到完整文章、项目背景、个人经历和可分享链接;在微信里,他更需要几秒内打开、快速了解内容并继续转发;坐在 Mac 前准备认真阅读时,他可能希望搜索、收藏、记录进度,并在网络不稳定时继续打开最近读过的文章。
因此,这套产品没有追求“所有终端完全一样”,而是给三个终端分配不同职责:
| 终端 | 首要任务 | 内容形态 | 关键体验 |
|---|---|---|---|
| 网站 | 公开发布与长期沉淀 | 完整中英文内容 | SEO、链接分享、响应式布局 |
| 微信小程序 | 微信内快速发现 | 中文摘要与精选段落 | 快速打开、文章与项目导航、扫码进入 |
| macOS | 桌面深度阅读 | 完整 Markdown | 搜索、收藏、双页阅读、进度与离线缓存 |
网站:内容的唯一来源,也是公开入口
网站是整套系统的内容源。文章以 Markdown 保存在同一个仓库中,标题、摘要、日期、标签、封面与正文一起版本化;Next.js 在构建时生成中英文页面、元数据、站点地图和结构化的文章路由。
PC 版本承担完整的信息表达。首页同时展示“现在、方法与系统、我如何思考、走过的路、AI 实践与技术札记”,让一篇文章能够回到作者长期关注的问题,而不是成为孤立的信息碎片。
PC 首页顶部预览,点击图片查看完整长图。
移动网站使用同一套内容,但不是机械缩小桌面布局。导航折叠为移动菜单,横向卡片重排为纵向信息流,标题、正文、按钮和时间线重新建立适合窄屏的阅读节奏。这样,从搜索、聊天或社交平台打开链接时,读者不需要安装任何客户端。
移动网站顶部预览,点击图片查看完整长图。
网站保持最高的信息完整度,也承担公开 URL、canonical、Open Graph、sitemap 和搜索引擎收录。小程序与桌面端可以提升阅读体验,但不取代开放网页。
微信小程序:把发现路径放进微信
微信小程序面向的是另一种使用状态:用户往往不是准备长时间阅读,而是从聊天、二维码或个人主页快速进入。因此首页只保留身份简介、当前关注方向、精选项目以及文章入口,并使用底部导航把“首页、文章、项目”固定为三个主要目的地。

小程序没有直接读取网站页面 HTML,而是调用独立的 /api/articles 接口。接口返回适合小程序展示的标题、摘要、标签、阅读时间和精选段落;客户端只负责渲染,不复制网站正文,也不拥有文章编辑能力。
这条边界有两个价值:一是网站改版不会让小程序解析失效;二是接口可以主动控制移动场景的信息量。公开网站负责完整表达,小程序负责低摩擦发现,两者不必被迫使用相同版式。
微信扫码打开小程序

macOS:把文章变成桌面上的一本书
macOS 版本不是 WebView 外壳,而是使用 Swift 6 与 SwiftUI 构建的原生阅读器。左侧是个人栏目导航,中间是可搜索的文章书架,右侧使用双页书本布局展示正文。窗口尺寸、侧栏、列表选择和阅读区都遵循桌面端的空间关系。

桌面端通过 /api/reader 命名空间读取个人栏目、文章列表与完整 Markdown。它与小程序接口隔离,因为两个客户端对内容的要求本来就不同:小程序需要轻量摘要,macOS 阅读器需要完整正文、目录和图片清单。
当前版本支持:
- 中英文文章与个人栏目;
- 标题和标签搜索;
- 收藏与本地阅读进度;
- 最近内容缓存与离线回退;
- Markdown、表格、引用、代码块和公开图片;
- 接近纸书的双页阅读布局。
下载 macOS 版本
系统要求为 macOS 14 Sonoma 或更高版本。当前安装包使用 ad-hoc 签名;首次打开如果被系统拦截,可在 Finder 中右键应用选择“打开”,或在“系统设置 → 隐私与安全性”中确认打开。
下载后可以校验文件:
shasum -a 256 houhuiyang-notes-macos-1.0.0.dmg
预期结果:
7a45940a1278f366f452467b766372e5a693f1d144b0be525c902461d38511e9
一份内容如何到达三个终端
这套系统的核心不是客户端数量,而是内容所有权足够清楚:
Markdown 文章与个人资料
│
▼
Next.js 内容与页面层
│ │
│ ├── 公开网站:完整页面、SEO、分享链接
│ │
├── /api/articles:小程序摘要与精选段落
│
└── /api/reader:macOS 完整 Markdown、目录与资源
所有客户端接口都是只读的。新增、修改和删除文章仍然只发生在内容仓库;客户端不会把本地状态反写成网站内容。收藏、阅读进度和缓存属于终端自己的用户体验数据,不污染文章事实。
接口也使用版本和稳定标识来降低耦合。文章以 slug + locale + updated 组成缓存版本键;客户端忽略未来新增的未知字段,并在服务不可用时读取最近一次成功缓存。网站可以继续迭代视觉,小程序和 macOS 应用也可以按自己的节奏发布。
我从这次跨端实践中得到的结论
第一,多端不等于多份内容。只要源头唯一、接口职责清楚,新增一篇文章就能自然到达多个阅读终端。
第二,响应式网页与原生客户端解决的是不同问题。网页拥有最低访问门槛和最好的开放性;小程序缩短微信生态内的发现路径;原生 macOS 应用则利用更大的屏幕、本地存储和系统交互,提供更完整的阅读状态。
第三,API 不是为了“前后端分离”而存在,而是为了稳定产品边界。小程序不应依赖网页 DOM,桌面端也不应复制文章数据库。接口让终端共享事实,同时保留各自的产品判断。
我希望“代码与产品札记”最终不只是一个展示作品的个人主页,而是一套可以持续写作、发布、阅读和演进的小型内容系统。网站、小程序和 macOS 只是当前的三个入口;真正值得长期维护的,是它们背后那份统一、可迁移、不会被单一平台锁住的内容。

