跳转到内容

01 · 架构与技术选型

个人站点通常有两类内容:

  1. 文档笔记 — 适合 Markdown,用 Starlight 自带 sidebar 组织
  2. 结构化导航 — 大量链接、分区、卡片分组,纯 MDX 维护成本高

书签模块解决的是第二类需求:按 Section → Card → Bookmark 三层组织链接,并提供搜索、分区 Tab、徽章等 UI。

同时希望:

  • 线上是 静态站点(GitHub Pages / Vercel / Netlify)
  • 本地有一个 可视化管理端,改完能 commit 进 Git
  • 不引入独立后端数据库服务
  • 文件夹src/bookmarks/
    • README.md — 模块目录与数据流
    • 文件夹shared/
      • types.ts — Section / Card / Bookmark 领域类型
      • 文件夹data/ — queries、page-data、serialize
      • 文件夹lib/ — 搜索、统计、Tab、favicon、badge
      • 文件夹components/ — BookmarkFavicon、BookmarkPageHeader、BookmarkSettingsIcon、StatsCards
      • 文件夹styles/ — bookmarks-theme-shared.css、bookmarks-card.css
    • 文件夹nav/
      • 文件夹components/ — NavBookmarksPage、卡片与 Tab
      • 文件夹styles/ — bookmarks-page.css
    • 文件夹admin/
      • 文件夹lib/ — 鉴权、API、拖拽 CRUD、api.server
      • 文件夹components/ — AdminApp、对话框、卡片网格
      • 文件夹styles/ — admin.css、bookmarks-app.css
    • nav/entry.astro — 导航 Astro 入口(injectRoute)→ /bookmarks/nav/
    • admin/entry.astro — 管理端 Astro 入口(injectRoute)→ /bookmarks/admin/
  • 文件夹db/
    • data/bookmarks.ts — 唯一可提交数据源
    • config.ts / seed.ts — Astro DB
  • integrations/bookmarks-admin.ts — dev /admin/api/*

文档站与书签模块 共用 @/theme 全站偏好wwlight:color-* + init.inline.js),但书签页 不走 Starlight 布局——独立 Astro 页面挂载 React 根组件,导航页可全宽布局。

sequenceDiagram
  participant File as bookmarks.ts
  participant Seed as db/seed.ts
  participant DB as Astro DB
  participant Page as Astro 页面
  participant React as React 岛屿

  File->>Seed: 构建 / dev 启动
  Seed->>DB: insert 三层表
  Page->>DB: getBookmarkSections()
  Page->>React: JSON 写入 #bookmarks-sections-data
  React->>React: readBookmarkSectionsFromPage()

关键点: 运行时 React 不直接读 DB,而是读页面内嵌的 JSON。Astro 在 SSR/SSG 阶段查 DB,序列化后注入 DOM。这保证了:

  • 导航页可以是 client:only="react",hydration 前已有数据
  • 构建产物仍是静态 HTML + JS,无服务端运行时

管理端为何「本地可写、线上只读」

Section titled “管理端为何「本地可写、线上只读」”

静态托管没有持久化磁盘。若在 production 开放 POST /admin/api/save,要么失败,要么需要额外后端。

当前方案:

环境登录编辑 UI保存到文件
astro dev
静态 build✅(门控)✅(UI 可见)403 仅开发环境可用

线上管理端页面主要用于 查看当前数据导出;真正改数据在本地 vpr dev:admin → commit → push。

astro.config.mjs 中与书签相关的集成:

integrations: [
db(), // Astro DB
react(), // React 岛屿
bookmarksAdmin(), // 开发态 /admin/api/* 中间件
starlight({ /* … */ }),
]

bookmarksAdmin 是一个自定义 Astro Integration,在 astro:config:setup 里向 Vite 注册 middleware——只在 dev server 生效。

  1. 克隆仓库并安装依赖

    Terminal window
    vp i
  2. 启动主站,访问书签页

    /bookmarks/nav/
    vpr dev
  3. 启动管理端(首次会创建 .env 并提示设密码)

    /bookmarks/admin/
    vpr dev:admin
  4. 在管理端改一条书签标题 → 保存 → 查看 db/data/bookmarks.ts 是否更新

  5. commit 该文件,push 后 CI 重新 build,线上书签页同步更新