你的LeetCode数据属于你自己:一个完全离线的DSA进度追踪器,连一次云都不上

大家好,我是提米哥,提米大门的首席选品官。今天要聊的这个开源项目,让我这个常年跟工具打交道的“老油条”都眼前一亮——它解决了一个大家心知肚明但很少有人捅破的问题:你的刷题数据,到底归谁?

你有没有半夜两点刷LeetCode题,刚Accepted就暗自庆幸?你有没有用过那些号称“免费”的刷题追踪工具?醒醒吧,你的解题历史、薄弱知识点、连续天数、面试前的复习节奏——这些数据全都在别人服务器上,人家拿去“优化产品”(翻译:训练模型、卖情报、投广告)。

我自己就踩过坑:同时用三个工具,一个要Google登录,一个自动同步到“云”且不给导出,第三个直接跑路了——顺带带走了我半年的刷题记录。那一刻我决定:不玩了,我要自己造一个只属于我自己的追踪器。

这个项目叫 My DSA Buddy,一个完全跑在 localhost 上的 LeetCode 仪表盘。没有账号、没有云、没有埋点。你的数据躺在你本机的 SQLite 文件里,唯一一次网络请求是把你的解法推到你自己的 GitHub 仓库。仅此而已。

外部网络请求次数:1(推送到你自己的 GitHub)
远程存储的数据:0 字节
分析/追踪:无
第三方数据依赖:零

就这么硬核。

它怎么工作?

两个本地模块对话:

  1. 本地网页仪表盘(Astro 5 + React 19),跑在 localhost:4321
  2. Chrome 扩展,静默检测 LeetCode 上的“Accepted”提交

你做完一道题,扩展自动抓取解法、推到你 GitHub,再往本地仪表盘发个信号更新数据。整个仪表盘根本不上网。

给技术控的架构图

┌───────────┐  ┌──────────┐  ┌────────────┐  ┌───────────┐
│ LeetCode  │  │ 内容脚本  │  │ 后台任务    │  │  本地仪表盘 │
│ 页面DOM   │  │ (content) │  │ (worker)   │  │ (dashboard)│
└─────┬─────┘  └─────┬────┘  └─────┬──────┘  └─────┬─────┘
      │              │             │               │
      │ "Accepted"   │             │               │
      │─────────────>│             │               │
      │              │ sendMessage │               │
      │              │────────────>│               │
      │              │             │               │
      │              │             │─ GitHub API ─>│(唯一外部调用)
      │              │             │  PUT 解法     │
      │              │             │<─ 201 ────────│
      │              │             │               │
      │              │             │ POST /api/sync│
      │              │             │──────────────>│
      │              │             │               │ 更新 SQLite
      │              │             │               │ 重新统计
      │              │             │<──────────────│ 200 OK

技术栈一览(无表格版)

  • 框架:Astro 5(SSR,Node 适配器)—— 只有交互部分才水合,性能优秀
  • UI:React 19 孤岛组件 —— 每个仪表盘小部件独立驱动
  • 样式:Tailwind CSS v4.0 —— 工具类优先,零运行时
  • 数据库:better-sqlite3 —— 单文件,零配置,读取超快
  • 数据导入:csv-parse —— 从 CSV 加载按公司分类的题目列表
  • 扩展:Vite + CRXJS(Manifest V3)—— 现代化的 Chrome 扩展构建
  • 类型安全:TypeScript 5.9 全链路 —— 仪表盘和扩展共享类型
  • 包管理:pnpm + Turborepo —— 共享代码,并行构建,缓存
  • 动画:Motion(原 Framer Motion)—— 流畅的组件过渡

数据结构:一个 SQLite 文件搞定

-- 建立解题记录表
CREATE TABLE solved_problems (
  id INTEGER PRIMARY KEY AUTOINCREMENT,        -- 自增主键
  problem_id INTEGER NOT NULL UNIQUE,           -- LeetCode 题目编号(唯一)
  title TEXT NOT NULL,                          -- 题目标题
  difficulty TEXT NOT NULL CHECK(difficulty IN ('Easy', 'Medium', 'Hard')), -- 难度
  topics TEXT,          -- 所属标签,JSON 数组
  companies TEXT,       -- 所属公司,JSON 数组
  solved_at TEXT NOT NULL,                      -- 解题时间
  language TEXT,                                -- 编程语言
  solution TEXT,                                -- 代码解法
  github_path TEXT                              -- 在 GitHub 上的路径
);

-- 每日进度表
CREATE TABLE daily_progress (
  date TEXT PRIMARY KEY,                        -- 日期,主键
  problems_solved INTEGER DEFAULT 0,            -- 当日解题数
  time_spent INTEGER DEFAULT 0,                 -- 耗时(分钟)
  problem_ids TEXT                              -- 题目 ID 列表,JSON 数组
);

没有 ORM,没有迁移脚本,就是一个 .db 文件——你可以复制、备份、甚至直接删掉。你的数据,你说了算。

设计:像翻开一本程序员手账

我不想要又一个灰色调的 SaaS 仪表盘。所以整个设计致敬 Claude.com 的美学:暖白画布、珊瑚色点缀、衬线字体。但又贴了开发者的标签:

  • 奶油色画布 (#faf9f5) —— 温润有质感,不是那种冷冰冰的灰色
  • 珊瑚色点缀 (#cc785c) —— 进度条、连续天数、已解决徽章
  • 深海军蓝表面 (#181715) —— 代码块、题目卡片、统计面板
  • Cormorant Garamond 衬线字体用于标题 —— “手账”氛围
  • JetBrains Mono 突出显示统计数字、ID、代码 —— “开发者”信号
  • 全暗黑模式,切换时带圆形过渡动画

最终效果:不像一个杂乱的统计工具,更像一本精心整理的刷题笔记。

/* 设计系统的 CSS 变量,加中文注释 */
@theme {
  --color-canvas: #faf9f5;              /* 画布底色:暖白 */
  --color-primary: #cc785c;             /* 主色:珊瑚 */
  --color-surface-dark: #181715;        /* 深色表面:深海军蓝 */
  --color-difficulty-easy: #5db872;     /* 简单题:绿色 */
  --color-difficulty-medium: #d4a017;   /* 中等题:金色 */
  --color-difficulty-hard: #c64545;     /* 困难题:红色 */
}

目前已完成的

  • 完整设计系统(CSS 变量、暗黑模式、组件类、动画)
  • 完整 TypeScript 类型定义(Problem、Roadmap、Progress、Settings、SyncPayload)
  • 单仓架构:仪表盘和扩展共享代码
  • Chrome 扩展骨架(Manifest V3,内容脚本、后台任务、弹出窗口)
  • 基础布局和首页
  • 扩展与仪表盘的通信协议

正在进行的

  • 仪表盘小部件(ProgressOverview、StreakCalendar、StatsPanel)
  • SQLite 数据库层和 API 路由
  • 带过滤的题目列表(难度、标签、公司、状态)
  • 按公司分类的路线图卡片

后续计划

  • 完整的扩展 DOM 提取(LeetCode 爬取)
  • GitHub 推送集成
  • 设置页面(PAT 配置、主题、同步偏好)
  • 数据导出/导入
  • 连续天数追踪和里程碑徽章

这就是你需要登场的地方。

为什么这么早就开源?

因为最好的开源项目不是一个人闭门造出来的,而是从第一天就有社区一起塑造。我现在把架构和设计系统放出来,就是想找到能一起打磨的人:

  • 在 UX 锁定前给出反馈
  • 带来领域专长(LeetCode DOM 结构、Chrome 扩展最佳实践、SQLite 优化)
  • 挑战我的决策(比如:扩展本地缓存用 IndexedDB 还是 SQLite?Astro 是不是过重了?连续算法该不该改?)

适合新手的任务(无表格版)

  • 构建 ProgressRing SVG 组件:难度易,技能要求 React + SVG
  • 实现连续天数日历(365天热力图):难度中,技能要求 React + CSS Grid/SVG
  • 编写 SQLite 初始化脚本:难度易,技能要求 SQL + Node.js
  • 构建 /api/sync 端点:难度中,技能要求 Astro API 路由 + better-sqlite3
  • 实现 LeetCode DOM 提取(内容脚本):难度难,技能要求 DOM API + Chrome 扩展
  • 添加 CSV 题目列表(Google, Amazon, Meta 等):难度易,技能要求数据收集
  • 构建带滚动动画的浮动导航栏:难度中,技能要求 React + CSS 过渡
  • 用 View Transition API 实现暗黑模式切换:难度中,技能要求 React + CSS + Web API

我想问社区的几个问题

  1. SQLite 还是 IndexedDB 作为扩展的本地缓存?
    当前仪表盘用 better-sqlite3,但扩展自己也可能需要缓存。用 Dexie.js 的 IndexedDB 多一份复杂度,但值不值得?还是说扩展干脆直接 ping localhost?

  2. “唯一一次网络请求”这条约束是不是太死?
    目前只允许推送 GitHub。但如果想要可选功能,比如从 LeetCode API 拉取题目元数据,或者可选云备份,这些是否应该作为“可选”加入?加入后会不会稀释隐私承诺?

  3. Astro SSR 跑在 localhost 上是不是杀鸡用牛刀?
    我选 Astro 是因为孤岛架构和服务端数据加载。但对于纯本地应用,一个 Vite + React SPA 再加一个 Express API 会不会更简单?你的看法呢?

  4. 什么功能能让你从现在的追踪工具切换过来?
    认真问——什么东西能让你每天都愿意打开这个工具?

快速上手

# 克隆并本地运行
git clone https://github.com/Ritanjit/My_DSA_Buddy.git
cd my-dsa-buddy
pnpm install
pnpm dev

# 仪表盘跑在 localhost:4321
# 扩展构建目录在 apps/chrome-extension/dist/

链接

直达网址:https://github.com/Ritanjit/My_DSA_Buddy.git

项目 MIT 协议,Issues 区欢迎吐槽。如果你也曾为数据归属发过愁,给个 star 或者挑个 issue 提个 PR。架构就位,设计就位,只差你了。

“隐私不是一个功能,而是一种权利。你的 DSA 刷题之路不应该以放弃它为代价。”

不管你是提交代码、在评论区丢个建议还是只点个 star,都是帮助。咱们一起造一个默认就尊重开发者数据的工具,而不是事后才想起来补救。


用 Astro 5、React 19、TypeScript、Tailwind CSS v4.0、better-sqlite3 以及对“免费”云服务的一丝不信任构建。

类似文章