forming / System Design Archive

Object Layer

Object Layer 把 Markdown、EPUB、PDF、图片、项目、人物、时间线和阅读痕迹统一为 KnowledgeObject projection;OpenList/COS 管 blob,Directus / MySQL 管 metadata 与关系,MyBlog 只渲染对象的一种公开投影。

KnowledgeObjectBookObjectVisualObjectPersonObjectTimelineObjectRelation GraphProjection Layer
Inspiration

借鉴对象

  • Anytype Objects
  • AFFiNE local-first workspace
  • Paperless-ngx document objects
  • Obsidian Graph
  • Plex media objects
Rejected

拒绝的方案

  • 把文件路径当长期对象 ID,因为文件会移动、重命名和迁移存储。对象 ID 必须稳定。
  • 让 Markdown 成为所有关系 authority,因为 Markdown 更适合作为 serialization format,不适合承载动态关系、状态和多源 metadata。
  • 把 OpenList/COS 变成知识数据库,因为对象存储只应该保存原件和派生缓存,不保存语义关系。
  • 让 MyBlog 页面成为真源,因为页面只是对象投影,不能反过来决定对象边界。
Runtime

运行方式

  • KnowledgeObject 是统一协议:id、type、title、summary、sources、relations、tags、createdAt、updatedAt、snapshotVersion。
  • apps/web/src/lib/knowledge/objects.ts 是当前 MyBlog-native 对象投影层:RuntimeMarkdownObject、Astro notes/projects、OpenList books-index、music、visuals 和 GitHub repo 先转成 KnowledgeObject,再派生 KnowledgeSearchDoc、KnowledgeRelationSource 和 KnowledgeGraphNode。
  • KnowledgeCollection 是对象进入 Surface 前的阅读上下文层:Object -> Collection -> ReadingSession -> View。首页 canonical shape 是 Runtime Surface v2:混合对象瀑布流、feed tabs、drawer peek、search、OpenList/Pinterest shell 和 runtime refresh 同时活着;Collection 只能作为 runtime lens 插入 feed,不能接管首页、不能变成 collection-only feed,也不能驱动 full route takeover。首页 Drawer 使用 .home-reader-session:当前文章正文是前景,集合标题只在 context rail 中弱化出现,TOC / 上一篇 / 下一篇是高密度导航;不得回退成 collection hero、stats、summary card、object card grid 或 .home-drawer-summary 卡片递归。/collections/ 与 /collections/[slug]/ 是备用 / permalink surface,不得替代首页 runtime surface;topic collection 只作为 metadata / search / Graph 维度;topic collections are dimensions, not static collection pages。
  • BookObject 连接 openlist:// EPUB/PDF/MOBI、cover asset、author、topic、reader memory、highlight 和 collection;当前书籍由 apps/web/src/lib/books/staticManifest.ts 只读加载 books-index,再通过 bookToKnowledgeObject 进入 /data/knowledge-index.json 和 /knowledge Graph。
  • VisualObject 连接 OpenList/COS/Immich/Pinterest preview、palette、mood、source URL、related books、related posts 和 graph node。
  • PersonObject、TimelineObject、PlaceObject 和 TopicObject 是后续扩展的实体类型,不能被临时 tag 完全替代。
  • OpenList/COS 只保存 blob 和 path;Directus 目标上承接人工 metadata overlay;MySQL runtime 承接阅读状态、关系、注释和动态事件。
  • Meilisearch 目标索引 KnowledgeObject snapshot,而不是只索引 Markdown 正文;Pagefind 在 Meilisearch 部署前继续负责静态公开页面搜索。
  • Astro/MyBlog 是 Projection Shell:Feed、Drawer、Reader、Graph、Visual Collection 和 Codex 页面都从对象 snapshot / content collection 渲染,不拥有对象真源。
Tradeoff

取舍

  • 对象层会增加 schema 和同步成本,但能避免 books.metadata.json、visuals.ts、OpenList index、MySQL runtime 各自生成一套不可合并的 ID。
  • Markdown 退回 serialization format 会降低“文件即一切”的简单感,但换来跨书籍、图片、项目、人物和阅读痕迹的稳定关系。
  • 早期可以先用 JSON manifest 表达 KnowledgeObject / KnowledgeCollection snapshot,等 Directus / Meilisearch 就绪后再升级为服务化对象索引。
Future Direction

后续方向

  • 定义 public-data/knowledge/knowledge-objects.schema.json,覆盖 BookObject、VisualObject、PostObject、ProjectObject、HighlightObject 和 KnowledgeCollection。
  • 从 books.metadata.json、visualCollections、OpenList index、reader_highlights 和 posts frontmatter 生成 KnowledgeObject snapshot。
  • 把 Graph、Search、Timeline 和 Drawer 的数据入口统一到 KnowledgeObject projection。
  • 用 Directus 管人工 metadata overlay,用 Meilisearch 管 object-first search,用 MySQL 管动态事件和关系。