docs: expand project design and agent guidelines

Rewrite DESIGN.md to detail product goals, data models, and API boundaries
Update AGENTS.md with existing UI patterns, i18n rules, and strict completion criteria
This commit is contained in:
2026-05-01 14:50:05 +08:00
parent 9fece8f54f
commit ec3494ea28
2 changed files with 483 additions and 152 deletions

158
AGENTS.md
View File

@@ -6,6 +6,7 @@
* Follow the existing structure and conventions strictly.
* Make **minimal, targeted changes only**. Do not refactor unrelated code.
* Prefer clarity over cleverness. Avoid unnecessary abstraction.
* Keep `DESIGN.md` aligned with implemented product behavior when changing data models, APIs, routes, permissions, or user-facing workflows.
---
@@ -22,15 +23,91 @@ For any non-trivial task:
Do NOT skip planning.
For documentation-only tasks, still follow the planning workflow, but do not run unrelated builds or tests unless the document change depends on generated output.
---
## Project Context
* Goal: Pokopia Wiki, a community-editable game wiki.
* Repository: pnpm workspace monorepo.
* Runtime baseline: Node.js >= 22.
* Frontend:
* Vue
* Vite
* Vue Router
* Vue I18n
* Iconify
* TypeScript
* Backend:
* Node.js
* Fastify
* PostgreSQL
* `pg`
* TypeScript
* Infra:
* Docker
* docker compose
---
## Existing Product Shape
* Public users can browse Wiki content.
* Registered users must verify email before editing.
* Verified users can edit Wiki content and management data; there is no separate role system currently.
* Main public sections:
* Pokemon
* Habitats
* Items
* Recipes
* Daily CheckList
* Management covers:
* System config
* Languages
* Daily CheckList tasks
* Sorting for Pokemon, items, recipes, and habitats
* Main entity create/edit flows use route-backed modal dialogs.
* Internationalization is part of the product model, not just UI copy.
* Detailed edit history and editor attribution are part of entity detail behavior.
---
## UI Design Guidelines
* Use `DesignGuidelines.html` as the reference for UI design, visual style, and component behavior.
* Prefer reusing existing components that already match the guidelines.
* Existing shared UI patterns include:
* `AppShell`
* `PageHeader`
* `Modal`
* `FilterPanel`
* `EntityCard`
* `DetailSection`
* `EditMeta`
* `EditHistoryPanel`
* `Skeleton`
* `Tabs`
* `SwitchGroup`
* `TagsSelect`
* `TranslationFields`
* `ReorderableList`
* If a needed component does not exist, create the smallest necessary component based on `DesignGuidelines.html`.
* Existing components may be upgraded to match `DesignGuidelines.html`, but only when directly related to the task.
* Do not introduce broad UI rewrites, new design systems, or extra abstraction layers unless explicitly required.
* Use Skeleton loaders for data loading states instead of user-facing loading remarks when the existing page pattern supports it.
* Use icon-based navigation and actions consistently with the existing Iconify setup.
---
@@ -42,6 +119,8 @@ Do NOT skip planning.
* Introduce new layers (services, utils, hooks, etc.) unless clearly required
* Split files unnecessarily
* Rewrite existing modules without explicit instruction
* Change unrelated route, API, or schema behavior while working on UI-only tasks
* Prefer editing existing files over creating new ones.
* Keep functions and components small and readable.
@@ -62,31 +141,52 @@ User-facing UI must NEVER contain:
### Strict Rules
* Only render **business data** and intended UI text
* Only render **business data** and intended UI text.
* Never display:
* "Updated successfully because..."
* "Changed X to Y"
* "TODO", "NOTE", "DEBUG"
* Debug information must go to logs, not UI
* Separate internal data from API responses
* Debug information must go to logs, not UI.
* Separate internal data from API responses.
* Do not expose raw database column names in user-facing labels unless `DESIGN.md` explicitly defines that label.
Violations are considered critical errors.
---
## Data & API Design Rules
## Data, API, and i18n Rules
* Follow `DESIGN.md` as the **single source of truth**
* Follow `DESIGN.md` as the **single source of truth**.
* PostgreSQL:
* use `snake_case`
* define proper primary/foreign keys
* preserve existing audit columns on editable entities
* preserve `sort_order` behavior for sortable lists
* avoid premature optimization
* APIs:
* return only necessary fields
* do not expose internal metadata
* do not expose password hashes, verification token hashes, session token hashes, or internal metadata
* expose editor attribution with only `id` and `displayName`
* keep API response shapes consistent with `frontend/src/services/api.ts`
* i18n:
* use `languages` and `entity_translations` for entity translations
* use `X-Locale` for localized API reads
* keep base `name` / `title` fields as the default-language source
* do not let localized editing overwrite the base field unintentionally
* include translations only where the current API shape already supports them
* Editing and audit:
* create/update/delete operations on Wiki content should record editor information
* detail pages should continue to support edit metadata and edit history
* delete or update behavior must not leak internal audit payloads to normal UI
---
@@ -96,11 +196,15 @@ Violations are considered critical errors.
* Components: `PascalCase`
* Composables: `useXxx`
* General:
* variables/functions: `camelCase`
* Keep files focused and under reasonable length
* Avoid duplication
* TypeScript types/interfaces: match existing local style
* Keep files focused and under reasonable length.
* Avoid duplication.
* Prefer existing helper APIs and local patterns over introducing new abstractions.
---
@@ -110,10 +214,10 @@ This project is developed from WSL, but runtime validation is done through Docke
Agent workflow:
* Run:
* Run when practical:
* lint
* typecheck
* `pnpm lint`
* `pnpm typecheck`
* Do NOT run tests in WSL.
* Do NOT require local test execution before finishing a task.
@@ -128,12 +232,13 @@ When adding tests is clearly useful, keep them focused and minimal, but do not e
A task is complete ONLY IF:
* Matches `DESIGN.md`
* Minimal diff (no unrelated changes)
* No UI leaks of internal info
* Code is readable and concise
* Passes lint/typecheck when practical
* Docker runtime issues are handled from user-provided `docker compose up --build` output
* Matches `DESIGN.md`.
* Updates `DESIGN.md` when the implemented behavior changes product, API, schema, permission, route, or i18n expectations.
* Minimal diff, with no unrelated changes.
* No UI leaks of internal info.
* Code is readable and concise.
* Passes lint/typecheck when practical.
* Docker runtime issues are handled from user-provided `docker compose up --build` output.
---
@@ -143,6 +248,7 @@ A task is complete ONLY IF:
* Over-engineering simple features
* Creating unused files or abstractions
* Mixing internal/debug data into UI
* Exposing token/hash/internal audit data through public API responses
* Large, unfocused commits
* Silent behavior changes outside scope
@@ -150,17 +256,7 @@ A task is complete ONLY IF:
## When Unsure
* Ask for clarification
* Do not guess requirements
* Do not invent features not in `DESIGN.md`
---
## Project Context
* Goal: Pokopia Wiki
* Stack:
* Frontend: Vue
* Backend: Node + PostgreSQL
* Infra: Docker
* Ask for clarification.
* Do not guess requirements.
* Do not invent features not in `DESIGN.md`.
* If current code and `DESIGN.md` disagree, call out the mismatch before changing behavior.

473
DESIGN.md
View File

@@ -1,155 +1,390 @@
# Pokopia Wiki
## 产品目标
- Pokopia Wiki 是一个面向 Pokopia 游戏资料的社区 Wiki。
- 所有人都可以浏览 Wiki 内容。
- 已注册并完成邮箱验证的用户可以创建、编辑、删除 Wiki 内容。
- 前台以 Pokemon、栖息地、物品、材料单、每日 CheckList 为主要浏览入口。
- 管理入口用于维护全局配置、语言、列表排序和每日 CheckList。
## 技术栈
- 后端Postgresql
- 前端Vue
- 运维Docker
都要用最新的框架
- Monorepopnpm workspaceNode.js >= 22TypeScript。
- 前端Vue、Vite、Vue Router、Vue I18n、Iconify。
- 后端Node.js、Fastify、pg、PostgreSQL。
- 运维Docker / docker compose。
- 依赖版本遵循现有 `package.json`,新增依赖时优先使用当前主流稳定版本,并保持项目结构简单。
# 功能描述
## 全局设计原则
- 一个具有社区功能的 Pokopia 游戏 Wiki
- `DESIGN.md` 是产品行为、数据结构和 API 暴露边界的单一事实来源。
- API 只返回业务需要的字段不返回密码、token hash、验证 token、内部调试字段或不必要的元数据。
- 用户界面只展示业务数据和设计内的文案,不展示提示词、计划、调试信息、字段内部名或修改说明。
- 可编辑 Wiki 内容必须记录创建者、最后编辑者、创建时间、最后编辑时间和编辑历史。
- 列表顺序由 `sort_order` 控制,默认按创建时间旧到新初始化,排序值按 10 递增以便后续插入和拖拽排序。
## 数据
## 国际化
- 前端使用 Vue I18n 管理界面文案,并通过 `X-Locale` 请求头告知后端当前语言。
- 前端当前语言保存在 `localStorage``pokopia_locale`
- 后端默认语言为 `en`
- 语言配置存储在 `languages`
- `code`
- `name`
- `enabled`
- `is_default`
- `sort_order`
- 语言 code 格式为 `xx``xx-YY`,例如 `en``zh-CN`
- 系统必须且只能有一个默认语言。
- 初始语言包含:
- `en`English默认语言
- `zh-CN`:简体中文
- 实体翻译存储在 `entity_translations`
- `entity_type`
- `entity_id`
- `locale`
- `field_name`
- `value`
- 支持翻译的实体:
- Pokemon
- 特长
- 喜欢的环境
- 喜欢的东西 / 标签
- 物品分类
- 物品用途
- 入手方式
- 物品
- 地图
- 栖息地
- 每日 CheckList Task
- 支持翻译的字段:
- `name`
- `title`
- 实体仍保留基础 `name``title` 字段,默认语言内容以基础字段为准。
- API 返回展示名称时按当前语言解析,回退顺序为:请求语言翻译 -> 默认语言翻译 -> 基础字段。
- 编辑表单必须避免本地化 UI 覆盖基础名称;翻译字段只展示当前需要编辑的语言。
## 用户与认证
- 用户可注册:
- 邮箱
- 显示名
- 密码
- 邮箱保存为小写。
- 密码只保存 hash。
- 注册后必须通过邮箱验证。
- 邮件发送使用 Resend
- `RESEND_API_KEY`
- `EMAIL_FROM`
- `APP_ORIGIN``FRONTEND_ORIGIN`
- 验证邮件包含一次性验证链接。
- 验证 token 只保存 hash并带过期时间和使用状态。
- 只有邮箱已验证的用户可以登录。
- 登录成功后返回明文 session token 给前端;数据库只保存 session token hash。
- 前端将登录 token 保存在 `localStorage``pokopia_auth_token`
- 用户可退出登录,退出时删除对应 session。
- 对外用户字段只包含必要信息:
- 当前用户:`id``email``displayName``emailVerified`
- 编辑署名:`id``displayName`
## Community 编辑与审计
- 已验证用户可以通过前台或管理入口编辑 Wiki 内容。
- 新增、修改、删除 Wiki 内容时必须写入审计信息。
- 可编辑实体包含:
- Pokemon
- 栖息地
- 物品
- 材料单
- 每日 CheckList Task
- 全局配置项
- 主要可编辑表包含:
- `created_by_user_id`
- `updated_by_user_id`
- `created_at`
- `updated_at`
- `sort_order`
- 详细编辑历史存储在 `wiki_edit_logs`
- `entity_type`
- `entity_id`
- `action``create` / `update` / `delete`
- `user_id`
- `changes`
- `created_at`
- 详情页展示最后编辑者、最后编辑时间和编辑历史面板。
- 编辑历史中的用户信息只展示必要署名不暴露邮箱、token、hash 或内部元数据。
## 全局配置数据
以下配置项都支持创建、编辑、删除、翻译和拖拽排序。
### 特长
- 名称
- 是否有掉落物:`has_item_drop`
- 已移除 `subcategory` 字段。
- 当特长允许掉落物时Pokemon 编辑中可为该 Pokemon + 特长配置一个掉落物品。
### 喜欢的环境
- 名称
### 喜欢的东西 / 标签
- 名称
- 同时用于:
- Pokemon 喜欢的东西
- 物品标签
### 物品分类
- 名称
- 用于物品和材料单按结果物品分类展示。
### 物品用途
- 名称
- 物品用途可为空。
### 入手方式
- 名称
- 可关联到物品和材料单。
### 地图
- 名称
- 用于栖息地中 Pokemon 出现地点。
## Pokemon
Pokemon 可配置:
- ID
- 名字
- 特长(可多选,最多 2 个)
- 特长掉落物品(按 Pokemon + 特长 配置,单选物品)
- 喜欢的环境(单选)
- 喜欢的东西(可多选,最多 6 个)
- 出现的栖息地(可多选)
特长 可配置:
- 名称
- 是否有掉落物
- 喜欢的环境:单选
- 特长:可多选,最多 2 个
- 特长掉落物品:按 Pokemon + 特长配置,单选物品
- 喜欢的东西:可多选,最多 6 个
- 出现的栖息地:由栖息地出现配置反向展示
- 翻译
- 排序
喜欢的环境 可配置
- 名称
Pokemon 列表功能
喜欢的东西(标签) 可配置:
- 名称
- 搜索
- 按喜欢的环境筛选
- 按特长筛选:
- 满足任意条件
- 满足全部条件
- 按喜欢的东西筛选:
- 满足任意条件
- 满足全部条件
- 按自定义排序展示
Pokemon 详情页展示:
- 基本信息
- 特长
- 特长掉落物品
- 喜欢的环境
- 喜欢的东西
- 关联喜欢的东西的物品
- 出现的栖息地
- 最后编辑信息
- 编辑历史
## 物品
物品可配置:
物品 可配置:
- 名称
- 分类
- 用途
- 入手方式可多选
- 分类:必填
- 用途:可为空
- 入手方式可多选
- 客制化:
- 可染色
- 可双区染色
- 可改花纹
- 标签(多选)
- 无材料单:`no_recipe`
- 标签:使用喜欢的东西配置,可多选
- 翻译
- 排序
物品列表功能:
- 搜索
- 按分类展示为标签页
- 按用途筛选
- 按标签筛选
- 按自定义排序展示
物品详情页展示:
- 基本信息
- 分类
- 用途
- 入手方式
- 客制化
- 标签
- 关联材料单
- 作为材料出现的材料单
- 相关栖息地
- 相关 Pokemon 掉落
- 最后编辑信息
- 编辑历史
## 材料单
材料单与物品是一对一关系:
- 一个材料单必须关联一个结果物品。
- 一个物品最多只能有一个材料单。
- 标记为 `no_recipe` 的物品不能创建材料单。
- 材料单没有独立名称,展示名称来自结果物品。
材料单可配置:
- 结果物品
- 入手方式:可多选
- 需要材料:多项物品 + 数量
- 排序
材料单列表功能:
- 独立于物品列表展示
- 按结果物品分类展示
- 按自定义排序展示
材料单详情页展示:
- 结果物品
- 入手方式
- 需要材料列表
- 最后编辑信息
- 编辑历史
## 栖息地
栖息地可配置:
材料单 可配置:
- 名称
- 入手方式(可多选)
- 需要材料(可多样,多数量)
- 配方:多项物品 + 数量
- 可出现的 Pokemon
- 翻译
- 排序
物品 / 材料单分类
- 名称
Pokemon 出现配置
物品 / 材料单用途:
- 名称
- Pokemon
- 地图:可多选
- 时间:可多选
- 早晨
- 中午
- 傍晚
- 晚上
- 天气:可多选
- 晴天
- 阴天
- 雨天
- 稀有度1 到 3 星
入手方式 可配置
- 名称
栖息地列表功能
地图:
- 名称
- 按自定义排序展示
- 展示配方摘要和可能出现的 Pokemon 摘要
栖息地:
- 名称
- 配方(物品,数量)
- 可出现的宝可梦(可多选)
栖息地详情页展示
列表顺序:
- 全局配置项、Pokemon、物品、材料单、地图、栖息地均可自定义排序
- 初始排序按创建时间旧到新
- 配方列表
- 可能出现的 Pokemon 列表
- 出现时间
- 出现天气
- 稀有度
- 出现的地图列表
- 最后编辑信息
- 编辑历史
出现契机
- 时间:早晨 / 中午 / 傍晚 / 晚上
- 天气:晴天 / 阴天 / 雨天
- 稀有度1 ~ 3 星
- 地图关联
## 每日 CheckList
每日 CheckList 可配置:
- Task
每日 CheckList Task 可配置:
- Task 标题
- 翻译
- Task 顺序
## 功能
前台行为:
- Pokemon 列表
- 搜索
- 筛选
- 特长(可多选,满足任意条件 / 满足全部条件)
- 喜欢的环境
- 喜欢的东西(可多选,满足任意条件 / 满足全部条件)
- Pokemon 详情页
- 特长
- 特长掉落物品
- 喜欢的环境
- 喜欢的东西
- 栖息地
- 栖息地列表
- 栖息地详情页
- 配方列表
- 可能出现的宝可梦列表
- 出现时间
- 出现天气
- 稀有度
- 出现的地图列表
- 物品 / 材料单列表
- 根据分类显示(标签页)
- 筛选
- 用途
- 标签
- 物品详情页
- 基本信息
- 用途
- 入手方式
- 自定义
- 可染色
- 可双区染色
- 可改花纹
- 材料单信息
- 入手方式
- 需要材料列表
- 标签
- 相关栖息地
- 相关 Pokemon 掉落
- 材料单详情页
- 基本信息
- 入手方式
- 需要材料列表
- 每日 CheckList
- 展示每日做什么
- 每个 Task 可勾选
- 每天自动清空勾选状态,不删除 Task
- 管理中可新增 Task 到列表
- 管理中可通过 Handle 拖曳排序
- 展示每日要做的 Task。
- 每个 Task 可勾选。
- 勾选状态保存在浏览器本地。
- 勾选状态按本地日期自动清空,不删除 Task。
- 已删除 Task 的本地勾选状态会自动清理。
## 用户系统
管理行为:
- 用户可注册
- 邮箱
- 显示名
- 密码
- 用户注册后需要通过邮箱验证
- 使用 Resend 发送验证邮件
- 邮件内包含验证链接
- 用户可登录
- 仅允许已验证邮箱的用户登录
- 登录后可获取当前用户信息
- 用户可退出登录
- API 只返回必要用户字段,不暴露密码、验证 token、会话 token 哈希或内部元数据
- 已验证用户可新增、编辑、删除 Task。
- 已验证用户可通过 Handle 拖拽排序。
## Community 编辑
## 前端交互与 UI
- 所有人都可浏览 Wiki 内容
- 已注册并完成邮箱验证的用户都可编辑 Wiki 内容
- 每次创建、修改、删除 Wiki 内容都需要记录编辑者
- Wiki 内容展示最后编辑者和最后编辑时间
- 编辑署名只展示必要用户信息不暴露邮箱、token、hash 或内部元数据
- UI 风格以 `DesignGuidelines.html` 为准。
- 页面结构以 `AppShell``PageHeader`、列表、详情区和管理区为核心。
- 导航和主要操作使用图标增强识别。
- 数据加载状态使用 Skeleton避免裸文本 loading。
- 分类切换使用 Tabs。
- 布尔或模式选择使用 SwitchGroup、checkbox、segmented control 等合适控件。
- 多选和单选复用 `TagsSelect`,支持搜索、键盘操作和必要时的内联创建。
- 主要实体的新建和编辑使用路由驱动的 Modal
- `/pokemon/new`
- `/pokemon/:id/edit`
- `/habitats/new`
- `/habitats/:id/edit`
- `/items/new`
- `/items/:id/edit`
- `/recipes/new`
- `/recipes/:id/edit`
- 进入或关闭编辑 Modal 时应保留底层页面上下文,不进行不必要的滚动跳转。
- 用户界面不得展示内部字段名、调试数据、计划说明或“已修改某字段”一类实现说明。
## API 概览
公开浏览 API
- `GET /api/languages`
- `GET /api/options`
- `GET /api/daily-checklist`
- `GET /api/pokemon`
- `GET /api/pokemon/:id`
- `GET /api/habitats`
- `GET /api/habitats/:id`
- `GET /api/items`
- `GET /api/items/:id`
- `GET /api/recipes`
- `GET /api/recipes/:id`
认证 API
- `POST /api/auth/register`
- `POST /api/auth/verify-email`
- `POST /api/auth/login`
- `GET /api/auth/me`
- `POST /api/auth/logout`
已验证用户编辑 API
- Pokemon、栖息地、物品、材料单的创建、更新、删除。
- 每日 CheckList 的创建、更新、删除、排序。
- 全局配置项的创建、更新、删除、排序。
- 语言的创建、更新、删除、排序。
- Pokemon、物品、材料单、栖息地的列表排序。
## 开发与验证
- 本项目在 WSL 中开发,运行验证主要通过 Docker。
- 常规轻量验证:
- `pnpm lint`
- `pnpm typecheck`
- 不在 WSL 中运行测试作为完成任务的前置条件。
- Docker 运行问题以用户提供的 `docker compose up --build` 输出为准进行后续修复。