DevysonSilva/kiroku
GitHub: DevysonSilva/kiroku
Kiroku 是一款基于 Next.js 构建的私有动漫与漫画追踪应用,帮助个人用户集中记录和管理跨媒体的观看阅读历程。
Stars: 8 | Forks: 0
# Kiroku 記録
## 🧩 技术栈
- **Next.js 16** (App Router, React Server Components) · **React 19** · **TypeScript** strict (零 `any`)
- **Auth.js** (next-auth v5) — GitHub 登录,单人 *allowlist*,`httpOnly` JWT session
- **Prisma 6** · **MongoDB** (Atlas) — 独立的目录副本,仅追加的历史记录
- **Tailwind CSS 4** · **shadcn/ui** (`radix-ui`) · **lucide-react**
- **AniList** (GraphQL) — 外部 anime 数据源,在添加时本地复制
- **PWA** — 自带的 manifest 和 service worker(0 PWA 依赖),*fail-closed*(不缓存任何已登录内容)
- **Vitest** + `mongodb-memory-server` — **305 个测试** · **Vercel** — 部署
## 📱 工作原理(快速导览)
1. 使用 GitHub **登录** —— 仅所有者(在 *allowlist* 中的您的 id)可通过。
2. 通过在 AniList 中搜索来**添加 anime**:数据(封面、简介、剧集)将被**复制**到
您的数据库中。即使 AniList 随后宕机,也不会丢失任何数据。
3. 手动**添加阅读内容**(mangá/manhwa/manhua 没有外部数据源)。
4. **持续追踪**:标记剧集/章节,更改状态(想看 · 观看中 · 已完成 ·
已暂停 · 已放弃),这一切都将成为**历史记录中的事件**(不会被删除)。
5. **评分与笔记**:总评分、分类、单集评分、最爱角色、语录。
6. 使用 **tags** 和**列表**进行**整理**(“收藏夹”是必不可少的)。
7. **查找**:搜索(忽略重音)并从 7 个维度进行筛选 —— 筛选结果保留在 URL 中,因此可以
分享并能在浏览器历史记录中恢复。
8. **俯瞰全局**:**面板**汇总了一切 —— 总数、分布、时间演变,以及基于您个人合集的推荐。
9. **个性化**:选择调色板(Neon/Tinta/Sakura)和标题字体 —— 通过 cookie 记忆。
10. **安装**到手机(添加到主屏幕)并使用底部导航栏。
## 🚀 本地运行
**前置条件:** Node **20.9+**(推荐 22),一个 **MongoDB Atlas** cluster(免费版
即可)以及一个 GitHub 账号。
```
# 1. 克隆和安装
git clone https://github.com/DevysonSilva/kiroku.git
cd kiroku
npm install
# 2. secrets
cp .env.example .env.local
# 填写 5 个变量(见下方部分)
# 3. 在 MongoDB 中创建 collections(Prisma 使用 db push — 无 SQL migrations)
# ⚠ Prisma CLI 读取 .env,而不是 .env.local。请 export URL 或为此单独使用一个 .env:
DATABASE_URL="sua-connection-string" npx prisma db push
npx prisma generate
# 4. 运行
npm run dev
```
打开 **http://localhost:3000**。
### 配置 GitHub 登录
1. GitHub → **Settings → Developer settings → OAuth Apps → New OAuth App**。
2. **Authorization callback URL**:`http://localhost:3000/api/auth/callback/github`。
3. 复制 **Client ID** 并生成 **Client Secret** → `.env.local`。
4. 您的 GitHub **数字 id**(用于 `OWNER_GITHUB_ID`)可在
`https://api.github.com/users/YOUR_USERNAME` 获取 → `id` 字段。
## 🔑 环境变量
所有变量都在启动时由 Zod 验证 —— **少一个,应用就无法启动**(*fail-closed*)。
```
# --- 认证 (Auth.js v5 + GitHub OAuth) ---
# 签名会话 JWT(至少 32 个字符)。使用以下命令生成: npx auth secret
# 或者: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
AUTH_SECRET=
# 你的 GitHub OAuth App 凭据
AUTH_GITHUB_ID=
AUTH_GITHUB_SECRET=
# 你的数字 GitHub ID — 一个 allowlist(仅你能进入)
# https://api.github.com/users/SEU_USUARIO -> "id" 字段
OWNER_GITHUB_ID=
# --- 数据库 (MongoDB Atlas) ---
# 包含路径中数据库名称的 connection string:.../mongodb.net/kiroku?retryWrites=true...
DATABASE_URL=
```
## 🛠️ 命令
| 命令 | 描述 |
|---------|-------|
| `npm run dev` | 开发服务器 |
| `npm run build` | 生产环境构建 |
| `npm run start` | 提供构建后的服务 |
| `npm run lint` | ESLint |
| `npm run typecheck` | `tsc --noEmit` |
| `npm run test` | Vitest (305 个测试) |
**每次合并前的质量门禁:** `typecheck` + `lint` + `test` + `build`,全部必须零错误。
## 🏗️ 构建方式 (spec-kit)
每个 feature 都通过 [spec-kit](https://github.com/github/spec-kit) 的流程诞生,每个
feature 对应 `specs/00N-*` 中的一个文件夹。文档是**事实的唯一来源**:意图存在于规范中,代码
再据此生成。
- **宪法** ([`.specify/memory/constitution.md`](.specify/memory/constitution.md)) — 10 条
凌驾于任何代码习惯之上的原则。
- **`specify` → `clarify` → `plan` → `tasks`** — feature 转化为 spec,解决问题,生成技术计划
并排序任务。
- **RED-first 测试** — 由独立的会话编写,在实现**之前**就会失败。
- **`implement`** — 代码根据任务生成;**`analyze`** 将 spec × 计划 × 代码进行交叉比对。
- **动态文档** — 区域地图和约定位于 [`AGENTS.md`](AGENTS.md);每个
关键文件夹都有自己的 `CLAUDE.md`,在同一个 PR 中更新。
## 📂 结构(按职责划分)
| 区域 | 包含内容 |
|------|---------------|
| `app/` | 页面 (App Router, RSC) 和 `app/api/` (HTTP 路由) |
| `components/` | shadcn 基础组件 (`ui/`) 及复合组件 |
| `lib/auth/` · `lib/services/auth/` | session 基础设施 · 纯 allowlist 规则 |
| `lib/services//` | 业务逻辑(works, entries, organization, collection, stats) |
| `lib/media/` · `lib/appearance/` · `lib/anime-api/` | 按媒体划分的词汇表 · 主题 · AniList adapter |
| `prisma/` | Prisma + MongoDB 的 schema 和约定 |
| `specs/` · `.specify/` | feature 规范 · 宪法及模板 |
流程始终是 **`schema → service → route → UI`**(单向分层):UI 不直接访问
数据库,也不包含业务逻辑。
## ☁️ 部署 (Vercel)
1. 将仓库导入 **Vercel**(Next 的标准构建;无需额外配置)。
2. **Environment Variables** (Production):与 `.env.local` 中的 5 个变量相同。
3. 在 **GitHub OAuth App** 中,添加生产环境的回调:
`https://YOUR-DOMAIN.vercel.app/api/auth/callback/github`
*(OAuth App 接受多个回调 —— 请将 `localhost` 和 Vercel 的地址保留在一起。)*
4. 在 **MongoDB Atlas → Network Access** 中,放行 Vercel 的访问权限(`0.0.0.0/0` 或其 IP)——
否则应用在登录并读取数据库时会卡住。
Vercel 通过 **HTTPS** 提供服务,这使得 PWA 能够真正在手机上**安装**。
## 📜 原则(宪法摘要)
1. **单一来源类型定义** — 类型源自 schema/Zod;无 `any`,无 barrel。
2. **单向分层** — `schema → service → route → UI`。
3. **一个引擎,多种媒体** — `mediaType` 是唯一的区分点。
4. **数据主权** — 本地目录副本;仅追加的历史记录。
5. **统一的 API 契约** — 所有路由共用一个 envelope。
6. **边界验证** — 所有外部输入均使用 Zod。
7. **fail-closed 安全性** — 无密钥,应用不启动;所有操作都需要 session。
8. **Token 化与可访问的 UI** — 0 硬编码颜色,符合 WCAG AA。
9. **RED-first 测试 + 门禁** — 只有门禁通过才能合并。
10. **动态文档** — 每个区域都有自己的 `CLAUDE.md`,并在同一个 PR 中更新。
*[@DevysonSilva](https://github.com/DevysonSilva) 的个人项目,使用 spec-kit + Claude 构建。
Kiroku (記録, "记录")。*
![]() |
![]() |
![]() |
三个主题下的同一个面板 — Neon · Sakura · Tinta。Feature 009:3 种暗色调色板 × 4 种标题字体,可实时切换并通过 cookie 记忆(在首次绘制时应用,无闪烁)。
## 🤖 我的第一个结合 *spec-driven development* + Claude 的项目 这是我的**第一个基于规范驱动开发构建的项目**—— 使用 [**spec-kit**](https://github.com/github/spec-kit) 并将 **Claude (Claude Code)** 作为结对 编程伙伴。 其核心思想是颠倒“直接开始写代码”的常规顺序:**每个 feature 都源自一份规范**,代码 再根据规范生成。意图存在于文档中;代码是其结果。在实践中,每个 feature 都会经历以下流程: ``` constitution → specify → clarify → plan → tasks → (testes RED) → implement → analyze → merge ``` - 一份包含 10 条不可妥协原则的**[宪法](.specify/memory/constitution.md)**统领一切——它的优先级高于任何代码习惯。 - 每一个 feature 对应 [`specs/00N-*`](specs/) 中的一个文件夹,每一个 feature 对应一个分支。 - **优先编写测试**(RED-first),并且在实现**之前**就会失败。 - 每个区域都有自己的 `CLAUDE.md`(动态文档),并在代码变更的**同一个 PR** 中更新——过时的文档即视为 bug。 - **每次合并前的质量门禁**:`typecheck` + `lint` + `test` + `build`,全部必须零错误。 这是一种学习如何以高级工程师的严谨纪律进行开发的方式——同时也留下了清晰的痕迹,记录了*为什么*要做出每一项决策。 ## ✨ 功能特性 | # | Feature | 描述 | |---|---------|-------| | 001 | **所有者访问** | GitHub (OAuth) 登录,单人 *allowlist*,应用 100% 私有。 | | 002 | **设计系统 + 框架** | Tokens、组件 (shadcn) 以及已登录区域的导航。 | | 003 | **动漫** | 通过**复制 AniList** 添加,基于单集的状态/进度、网格视图、详情页、“继续观看”和历史记录。 | | 004 | **阅读** | 在同一引擎下处理 Mangá/manhwa/manhua —— 手动录入,按连续章节追踪进度。 | | 005 | **评分与笔记** | 总评分、各类型分类、各单元评分、三个列表(角色、最佳、语录)。 | | 006 | **整理** | 可编辑的 genre、支持无拼音音调自动补全的自由 **tags**、所有者的**列表**(包含“收藏夹”)。 | | 007 | **搜索与过滤** | 从 7 个维度切割合集并支持排序 —— 筛选状态保留在**地址** (URL) 中,搜索忽略重音符号。 | | 008 | **面板** | 统计数据与推荐 —— 宏观视角,100% 读取,缺失数据始终明确声明。 | | 009 | **主题** | 3 种暗色调色板 (Neon · Tinta · Sakura) × 4 种标题字体,可切换,通过 cookie 记忆(无闪烁)。 | | 010 | **PWA + 移动端** | 可**安装**到主屏幕,手机端底部导航栏,返回按钮,响应式布局。 | **核心理念:** anime、mangá、manhwa 和 manhua 属于**同一种通用作品** (`Work` + `UserEntry`); ~90% 的逻辑只需编写**一次**,仅通过 `mediaType` 进行区分。一个引擎,多种媒体。 ## 📸 界面截图![]() Animes — busca sem acento, filtros e grid de capas (119 obras na coleção). |
![]() Continuar — retomar de onde parou em cada obra (temporada · episódio). |
![]() Leituras — mangá / manhwa / manhua, cadastro manual, progresso por capítulo. |
![]() Listas e tags — Favoritos garantido; tags nascem do uso, sem cadastro prévio. |
标签:MongoDB, Prisma, React, Syscalls, TypeScript, 个人记录, 内容追踪, 安全插件, 自动化攻击






