尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 README ↗A novel-writing and world-building platform with an AI-aware Codex (story bible).
Linear project: novel-writing-app.
| Layer | Choice | Why |
|---|---|---|
| Framework | Next.js 16 (App Router) + React 19 | Server Components, Server Actions, src/proxy.ts session refresh |
| Language | TypeScript (strict) | Type safety across the Codex domain model |
| Database | Supabase Postgres | Auth + Postgres; Prisma 8 talks to it via DIRECT_URL |
| ORM | Prisma 8 (Prisma Next, contract-first) | prisma/contract.prisma + @prisma/orm-postgres |
| Auth | Supabase Auth (cookie session) | Email + password; Codex APIs require a session |
| Styling | Tailwind CSS 4 | Utility-first |
| Tooling | bun + vite-plus (vp) | CI/Vercel install with bun; lint/format/test via vp |
| Hosting | Vercel | vercel.json runs bun install / bun run build |
bun run dev or npm run dev)/dashboard/codex)User, Series, Novel, Act, Chapter, Scene (STO-1150)CodexEntry, CodexAlias, CodexTag, CodexRelation, CodexProgression (STO-1167)bun run db:seed)Signup/login still has an open tracking issue (#60); confirm email settings in the Supabase project if local auth fails.
CI and Vercel use bun. npm scripts in package.json are equivalent.
bun install
postinstall runs prisma contract emit. If install used --ignore-scripts (as CI does), emit manually:
bun run contract:emit
DIRECT_URL.DATABASE_URL for runtime queries.NEXT_PUBLIC_SUPABASE_URL and anon public → NEXT_PUBLIC_SUPABASE_ANON_KEY.SUPABASE_SERVICE_ROLE_KEY. Never expose this to the browser..env.example to .env (or .env.local) and fill in the values.prisma.config.ts prefers DIRECT_URL, then DATABASE_URL.
Prisma 8 is contract-first. There is no db:migrate or db:studio script.
bun run db:update # apply the contract to the database (use DIRECT_URL)
bun run db:seed # optional: demo series / novel / Codex fixtures
Related: bun run db:verify, bun run db:sign, bun run contract:emit.
bun run dev
Visit http://localhost:3000, sign up, and you should land on /dashboard. Codex UI: /dashboard/codex.
src/
├── app/
│ ├── api/health/ # GET /api/health
│ ├── api/codex/ # Session-authed Codex REST
│ ├── dashboard/ # Authed dashboard + Codex UI
│ ├── login/ / signup/
│ ├── layout.tsx / page.tsx
│ └── globals.css
├── lib/
│ ├── prisma.ts # Prisma 8 client (`db.orm.public.*`)
│ ├── codex/ # Domain service, actions, engines, types
│ └── supabase/ # Browser/server clients, session helper, user sync
└── proxy.ts # Next 16 session refresh (not middleware.ts)
prisma/
├── contract.prisma # Prisma 8 data contract (source of truth)
├── schema.prisma # Legacy Prisma 7 schema (not the runtime contract)
└── seed.ts
Hierarchical story model: User → Series → Novel → Act → Chapter → Scene.
Codex entries are the story bible: character / location / item / lore / faction / concept / other. Book-scoped entries bind to one novel; series-scoped entries are shared across books in that series. Soft-delete via deletedAt (pass ?hard=true to hard-delete).
| Concern | Where |
|---|---|
| Domain API | src/lib/codex/service.ts (CodexError, CRUD, mentions, resolveCodexEntryAtScene) |
| Server Actions | src/lib/codex/actions.ts ({ success, data } or { success: false, error, code, status }) |
| Types | src/lib/codex/types.ts (CodexType, CodexTrackingMode, ProgressionMode) |
| Mentions | src/lib/codex/mention-detection.ts — case-insensitive, word-boundary, longer-match wins |
| Progressions | src/lib/codex/progression-engine.ts (STO-1153) — reading order Act→Chapter→Scene; ADDITION appends, REPLACEMENT replaces |
| Relations | src/lib/codex/relation-engine.ts (STO-1154) — pure RelationEngine: BFS graph expansion from a seed entry, cycle detection, depth limit (default 2), dedupe; DB-agnostic edge input; unit-tested in tests/relation-engine.test.ts |
Tracking modes: ALWAYS, DETECTED, NEVER.
There is no HTTP endpoint for “resolve entry at scene”; use resolveCodexEntryAtScene in the service layer. Relation CRUD is on the API, and the graph expansion engine (STO-1154, RelationEngine) ships on main as a pure library — call it from the service layer; there is no dedicated HTTP endpoint for expansion.
| Method | Path | Role |
|---|---|---|
| GET | /api/health | Liveness { status, service, version, time } |
| GET | /api/codex/entries?novelId|seriesId&type&trackingMode&search&seriesOnly | List |
| POST | /api/codex/entries | Create (CreateCodexEntryInput) |
| GET/PATCH/DELETE | /api/codex/entries/[id] | Read / update / delete (?hard=true) |
| POST | /api/codex/entries/[id]/aliases | Add alias |
| DELETE | /api/codex/aliases/[id] | Remove alias |
| POST | /api/codex/entries/[id]/tags | Add tag |
| DELETE | /api/codex/tags/[id] | Remove tag |
| POST | /api/codex/relations | Create relation |
| PATCH/DELETE | /api/codex/relations/[id] | Update / delete |
| POST | /api/codex/progressions | Create progression |
| PATCH/DELETE | /api/codex/progressions/[id] | Update / delete |
| POST | /api/codex/mentions | { text, novelId? | sceneId? } |
Error payload: { error, code }. Codes: NOT_FOUND, FORBIDDEN, VALIDATION_FAILED, SCOPING_ERROR, CONFLICT, INVALID_JSON (malformed body → 400, not 500).
| Script | Purpose |
|---|---|
bun run dev | Next.js dev server |
bun run build / start | Production build / serve |
bun run lint | oxlint via vp lint --fix |
bun run format / format:check | vp fmt |
bun run typecheck | vp check --no-fmt --no-lint |
bun run test / test:cov | Vitest via vp test |
bun run test:e2e | Playwright (tests/e2e, Chrome at /usr/bin/google-chrome) |
bun run contract:emit | prisma contract emit |
bun run db:update / db:verify / db:sign | Prisma 8 schema apply / verify / sign |
bun run db:seed | Demo data |
bun run test # unit / integration (Vitest)
bun run test:e2e # Playwright; sets NEXT_PUBLIC_E2E=true and starts `npm run dev`
E2E launches Chromium with executablePath: /usr/bin/google-chrome. Codex tests that share a database can race; isolate fixtures rather than pointing every suite at one live DB.
| Symptom | Likely cause |
|---|---|
db:update / seed hangs | Transaction pooler (port 6543) blocks DDL. Point DIRECT_URL at the session pooler (port 5432). Direct hostnames can be IPv6-only. |
command not found: db:migrate / db:studio | Those Prisma 7 scripts were removed. Use db:update and the contract files. |
| Seed never exits | Historical: undrained pg.Pool. Current prisma/seed.ts should exit; if it hangs, check the pooler URL first. |
| Server Components look logged-out | src/proxy.ts must refresh the Supabase cookie; do not reintroduce a separate middleware.ts that skips @supabase/ssr. |
| Codex API 401 | No session cookie. Sign in via /login; there is no API-key auth. |
| Playwright cannot find Chrome | Config expects /usr/bin/google-chrome. |
prisma contract emit missing after install | CI uses bun install --ignore-scripts; run bun run contract:emit. |