尚未偵測到更新。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. |