Karakeep 源码仓库目录结构全解析:从 Apps、Shared Packages 到 Toolings 的 Monorepo 架构导览
【免费下载链接】hoarderA self-hostable bookmark-everything app (links, notes and images) with AI-based automatic tagging and full text search项目地址: https://gitcode.com/GitHub_Trending/ho/hoarder
本文以官方开发文档 02-directories.md 为骨架,结合 Karakeep(原 Hoarder)当前仓库的源码、配置文件与工程化实践,逐一拆解 monorepo 中每个顶层目录的职责、内部布局与依赖关系,帮助开发者在接手代码前快速建立"该改哪里、该看哪里"的全局地图。读完本文,你将能够准确判断一次功能改动应该落在
apps还是packages、业务逻辑到底在哪个包里、共享的 tsconfig 与 Tailwind 配置从何而来。
仓库顶层概览:pnpm + Turbo 的多包工作区
在深入每个目录之前,先看两个决定整个仓库形态的根级文件。
根目录的 pnpm-workspace.yaml 定义了工作区的收录范围:packages/*、apps/*、tooling/*、tools/*以及docs全部属于同一个 pnpm workspace。也就是说,除了文档里列出的apps、packages、tooling三大类,仓库还额外包含tools(如 tools/seed-snapshot 快照工具、tools/compare-models 模型对比工具)和docs(Docusaurus 文档站本身)两个顶层目录。同一份文件还声明了nodeLinker: hoisted、若干patchedDependencies(如对react-native@0.85.3、playwright-extra@4.3.6的补丁)以及全局overrides(将vite固定为 7.0.6、react固定为 19.2.3),这些约束保证所有包在构建时对依赖版本达成一致。
根目录的 package.json 是工作区的指挥中枢,通过 turbo.json 编排所有子包的build、dev、lint、test、typecheck等任务。常用的根级脚本包括:
pnpm dev:turbo dev --parallel,并行启动所有应用的开发模式;pnpm build:按拓扑顺序(dependsOn: ^build)构建全部包;pnpm test/pnpm lint/pnpm typecheck:全仓库的质量门禁;pnpm db:generate/pnpm db:migrate/pnpm db:studio:数据库相关操作,实际委托给@karakeep/db包执行;pnpm seed:apply/pnpm seed:snapshot:快照数据的应用与生成;pnpm workers/pnpm web:单独启动 workers 与 web 应用。
Apps:五个(加上 CLI/MCP 共七个)面向用户的交付物
apps/下每个目录都是一个可独立部署或分发的应用。官方文档列出了五个核心应用,而当前仓库实际还包含cli与mcp两个附加应用,下面一并说明。
| Directory | 官方描述 | 技术栈与入口 |
|---|---|---|
apps/web | 主 Web 应用 | Next.js 16 + tRPC,入口见 apps/web/package.json |
apps/workers | 后台 Worker 逻辑 | Node 进程 + 多 Worker 队列,入口见 apps/workers/index.ts |
apps/mobile | React Native 移动端 | Expo 56 + expo-router,见 apps/mobile/package.json |
apps/browser-extension | 浏览器扩展 | Vite + CRXJS,见 apps/browser-extension/package.json |
apps/landing | 官网落地页 | Astro + React,见 apps/landing/package.json |
apps/cli | 命令行工具 | Commander,产出karakeep可执行文件 |
apps/mcp | MCP 服务器 | 基于@modelcontextprotocol/server,产出karakeep-mcp |
apps/web:承载几乎所有 UI 的主应用
apps/web是用户与系统交互的主界面。从 apps/web/package.json 的依赖清单可以清晰看到它的角色:
- 框架:Next.js 16 + React 19.2,配合
next-auth处理认证,next-i18next做国际化(语言资源位于 apps/web/lib/i18n,共 30 余个 locale JSON); - 状态与数据层:
@tanstack/react-query+@trpc/tanstack-react-query,通过@karakeep/trpc、@karakeep/api等 workspace 依赖调用服务端; - UI 体系:Radix UI 全家桶 + shadcn(apps/web/components/ui)+ Tailwind,还集成了 Lexical 富文本编辑器(用于笔记编辑);
- 服务端能力:直接依赖
better-sqlite3与drizzle-orm,说明 Web 应用自身也承担部分服务端职责;同时依赖@karakeep/shared-server与@karakeep/db。
目录内部按路由组织:app/下是 Next.js App Router 页面(dashboard、settings、admin、signin、signup、reader等),components/下按dashboard、settings、admin、ui等模块拆分组件,lib/存放 hooks、store、国际化与工具函数,server/存放服务端 API 与认证逻辑。
apps/workers:系统的"后台发动机"
apps/workers是所有异步与重活的执行地。其入口 apps/workers/index.ts 展示了完整的工作者注册表:
| Worker 名称 | 职责(依据 apps/workers/workers 目录与入口代码) |
|---|---|
crawler/lowPriorityCrawler | 链接抓取(高/低优先级两条队列),见 crawlerWorker.ts |
embeddings | 向量嵌入生成,见 embeddingsWorker.ts |
inference | AI 推理(自动打标签、摘要),见 inference |
search | 全文搜索索引,见 searchWorker.ts |
adminMaintenance | 后台维护任务 |
video | 视频元数据提取 |
feed | RSS 订阅源刷新 |
assetPreprocessing | 附件预处理(如图片压缩) |
webhook | Webhook 通知 |
ruleEngine | 自动化规则引擎 |
backup | 定时备份 |
import | 导入轮询(非队列式,单独启动) |
入口代码里还体现了两个关键设计:一是 Worker 可按需启停,通过serverConfig.workers.enabledWorkers/disabledWorkers(环境变量WORKERS_ENABLED_WORKERS/WORKERS_DISABLED_WORKERS,见 packages/shared/config.ts)过滤;二是index.ts末尾会buildServer()启动一个 Hono HTTP 服务(依赖里含hono与@hono/prometheus),对外暴露指标接口。
从 apps/workers/package.json 可以看出其技术纵深:Playwright 无头浏览器抓取、metascraper 元数据提取、@mozilla/readability正文提取、pdf2json/pdfjs-distPDF 解析、tesseract.jsOCR、rss-parser订阅解析,以及 liteque 队列(liteque依赖)。这些能力共同支撑"书签一切"的核心体验。
apps/mobile:Expo 驱动的跨端 App
apps/mobile/package.json 显示其基于 Expo 56 与 React Native 0.85,采用 expo-router 文件路由(app/目录即路由,如 app/dashboard、app/signin.tsx)、NativeWind 做样式、expo-share-intent处理系统分享。它与 Web 端共享@karakeep/shared、@karakeep/shared-react、@karakeep/trpc,意味着两端复用同一套 tRPC 客户端与业务类型,并内置离线缓存能力(apps/mobile/lib/offlineCache.ts)。
apps/browser-extension:浏览器端的收藏入口
扩展基于 Vite + CRXJS 构建(@crxjs/vite-plugin),UI 复用 Radix 与 Tailwind。从 apps/browser-extension/src 可见其页面构成:SavePage(保存书签)、OptionsPage(设置)、BookmarkSavedPage、BookmarkDeletedPage、SignInPage等,并通过single-file-core支持整页归档(SingleFile 集成)。它是用户"随手收藏"的最短路径。
apps/landing:官网与定价页
apps/landing/package.json 表明其使用 Astro 6 + React 组件(@astrojs/react),页面位于 apps/landing/src/pages(含Homepage、Pricing、Privacy、Terms等),定价数据独立维护在 apps/landing/src/pricing-data.ts。
apps/cli 与 apps/mcp:命令行与 AI 生态接入
- apps/cli/package.json 产出一个名为
karakeep的 bin,基于 Commander 实现 12 个命令,通过@karakeep/trpc与@trpc/client远程调用服务器; - apps/mcp/package.json 产出一个
karakeep-mcpbin,基于@modelcontextprotocol/server暴露书签、高亮、标签、列表等 MCP 工具(对应 apps/mcp/src 下的bookmarks.ts、highlights.ts、tags.ts、lists.ts及其同名测试),让 Claude 等 AI Agent 可以直接读写 Karakeep。
Shared Packages:业务逻辑与基础设施的"泵站"
packages/是架构的承重墙——Web、Workers、Mobile 等所有应用都通过workspace:*依赖指向这里。官方文档列了五个核心包,下面结合源码逐一展开。
| Directory | 官方描述 | 实际职责 |
|---|---|---|
packages/db | 数据库 schema 与迁移 | Drizzle ORM schema + 25 个 SQL 迁移 + drizzle-kit 工具链 |
packages/trpc | 大部分业务逻辑所在的 tRPC 路由 | 16 个 router 模型 + 36 个路由文件 + 认证/邮件/统计 |
packages/shared | 各应用共享代码(日志、配置等) | 环境变量 schema、日志、搜索解析、推断、队列、限流等 |
packages/shared-server | 仅服务端共享的服务(队列、资产存储) | 队列封装、插件加载、资产存储接口 |
packages/plugins | 可插拔服务的实现(文件系统与 S3 存储等) | 资产存储插件、搜索/向量/队列/限流插件 |
packages/db:单一数据源
packages/db/schema.ts 定义了全系统唯一的数据模型(用户、书签、列表、标签、高亮、资产、规则、订阅源等),packages/db/drizzle 下是 25 个按顺序编号的 SQL 迁移文件。根目录脚本db:generate、db:migrate、db:studio分别对应 schema 生成迁移、执行迁移、打开 Drizzle Studio。所有应用读写同一份 SQLite 数据,这是架构"单库"设计的关键。
packages/trpc:业务逻辑的心脏
packages/trpc是官方文档明确指出的"大部分业务逻辑所在"。从 packages/trpc/routers 可以看到按领域拆分的路由族:bookmarksAppRouter(书签 CRUD 与搜索)、listsAppRouter、tagsAppRouter、highlightsAppRouter、assetsAppRouter、backupsAppRouter、feedsAppRouter、invitesAppRouter、adminAppRouter等,最终在 routers/_app.ts 聚合为appRouter供各端消费。配套的models/存放数据访问层,lib/存放跨路由的公共服务,另有独立的 auth.ts、email.ts、stats.ts。Web、Mobile、CLI、MCP 四端共用这份路由定义,是"一套业务逻辑,多端复用"的基石。
packages/shared:无 UI 的通用层
packages/shared 的内容远超"日志与配置":config.ts是全部环境变量的 zod schema(638 行的权威配置清单,如PORT、WORKERS_ENABLED_WORKERS、OPENAI_API_KEY、MEILI_*等);此外还有logger.ts、search.ts与searchQueryParser.ts(搜索查询语法解析)、inference.ts(AI 推理抽象)、prompts.ts(提示词模板)、queueing.ts、ratelimiting.ts、signedTokens.ts、readOnlyMode.ts、import-export/(导入导出格式)与types/(共享 TypeScript 类型)。由于它同时被 Web 与 Workers 依赖,任何"两端都需要"的工具都应放这里。
packages/shared-server:仅服务端可见的封装
与shared的差异在于:shared-server的代码绝不能进入浏览器(如better-sqlite3、队列句柄等 Node 依赖)。它提供@karakeep/shared-server给 Web 与 Workers 使用,封装了各 Worker 队列(LinkCrawlerQueue、OpenAIQueue、SearchIndexingQueue等,从 apps/workers/index.ts 的 import 可见)、资产存储抽象以及loadAllPlugins插件加载入口。
packages/plugins:可插拔后端服务
packages/plugins将外部依赖做成可选插件,避免核心包被具体实现"绑架"。当前仓库包含:
- 资产存储:assetstore-filesystem 与 assetstore-s3;
- 搜索:search-meilisearch;
- 向量库:vectorstore-meilisearch;
- 队列:queue-liteque 与 queue-restate;
- 限流:ratelimit-memory 与 ratelimit-redis。
每种插件都提供同一接口的不同实现,由配置决定启用哪一套——这正是"自托管可定制"架构的体现。
其他 packages
除官方文档列出的五个包外,packages/还包含:
packages/api:API 层(中间件如 apiKeyScopes.ts、rateLimit.ts,路由如 routes/bookmarks.ts),Web 的app/api背后即调用它;packages/sdk:面向第三方的 TypeScript SDK;packages/shared-react:跨 Web/Mobile 的 React hooks 与组件(packages/shared-react/hooks);packages/open-api:OpenAPI 规范生成(karakeep-openapi-spec.json);packages/e2e_tests:Playwright 端到端测试(tests 下 20 个用例);packages/benchmarks:性能基准测试。
Toolings:统一的工程化底座
tooling/存放跨包复用的开发配置。官方文档提到四个目录,当前仓库实际用 oxlint + oxfmt 取代了 ESLint/Prettier 传统组合:
| Directory | 官方描述 | 实际内容 |
|---|---|---|
tooling/typescript | 共享 tsconfig | base.json 与 node.json |
tooling/prettier | Prettier 配置 | 现以 oxfmt 为主(tooling/prettier/index.js 仍保留) |
tooling/tailwind | 共享 Tailwind 配置 | base.ts、web.ts、native.ts 区分 Web 与 RN 场景 |
tooling/oxlint | (新增)Lint 规则 | oxlint-base.json、oxlint-react.json、oxlint-nextjs.json |
观察各 app 的 package.json 可以发现统一模式:几乎每个包都声明@karakeep/tsconfig、@karakeep/tailwind-config为 devDependencies,并以oxlint --ignore-path=../../.gitignore、oxfmt --ignore-path=../../.gitignore作为 lint/format 脚本,配合根级pnpm lint/pnpm format实现"一处配置、全仓生效"。此外tooling/github存放 GitHub Actions 相关配置。
目录与运行时架构的对应关系
把上面拆开的模块重新组装,就能得到系统的运行时全貌。官方架构图 docs/static/img/architecture/arch.png 直观展示了各模块的连接:
对应关系可以概括为:
- 入口层:
apps/web、apps/mobile、apps/browser-extension、apps/cli、apps/mcp是五个面向用户的入口,全部通过@karakeep/trpc的appRouter调用同一套业务逻辑; - 业务层:
packages/trpc承载 CRUD 与业务编排,packages/api提供 REST/OpenAPI 风格接口; - 异步层:Web 把抓取、推理等重任务投递到队列,由
apps/workers中的各 Worker 消费执行;队列实现本身来自packages/plugins的 queue 插件; - 数据层:
packages/db统一管理 SQLite schema 与迁移,搜索结果依赖packages/plugins中的搜索插件(默认 Meilisearch); - 配置层:
packages/shared/config.ts是唯一的环境变量权威来源,apps/workers与apps/web共享同一份配置契约,这也是根级turbo.json将.env声明为全局依赖(globalDependencies: ["**/.env"])的原因——任何配置变更都会触发相关任务重建。
一份快速导航清单
把本文内容浓缩成一张速查表,方便日常开发时"按图索骥":
- 要改 UI / 页面→
apps/web/components、apps/web/app; - 要改移动端体验→
apps/mobile/app、apps/mobile/components; - 要改业务规则 / 增删接口→
packages/trpc/routers(配合packages/trpc/models); - 要改数据模型 / 加字段→
packages/db/schema.ts+ 生成迁移; - 要改环境变量 / 配置项→
packages/shared/config.ts; - 要改后台任务 / 抓取逻辑→
apps/workers/workers(各 Worker 文件); - 要换存储 / 搜索引擎 / 队列实现→
packages/plugins对应插件目录; - 要改 TS / Tailwind / Lint 规则→
tooling/对应配置目录; - 要跑全仓质量检查→ 根目录
pnpm lint、pnpm typecheck、pnpm test。
这份清单与官方文档 08-development/02-directories.md 的目录表格一一对应,是从"看文档"过渡到"动手改代码"最直接的索引。开发者文档的其他部分(如 01-setup.md 的搭建步骤、04-architecture.md 的架构说明)可以与本目录结构互为补充,共同构成完整的开发入门路径。
【免费下载链接】hoarderA self-hostable bookmark-everything app (links, notes and images) with AI-based automatic tagging and full text search项目地址: https://gitcode.com/GitHub_Trending/ho/hoarder
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考