Local-first educational branching-story editor — write interactive scenarios in TipTap, collaborate with local Ollama, export a static ZIP player for learners.
中文:本地优先的教育情景故事编辑器。Vue 3 + TipTap 创作 → 本地 AI → 导出静态 ZIP(Vanilla 播放器)。界面为简体中文。
Most TipTap demos stop at a toolbar. This repo shows production-shaped TipTap usage:
- Custom ProseMirror nodes (
storyNode,choiceBlock) with Vue NodeViews - Bidirectional projection between editor JSON and a shared
StoryDocumentschema - Structure checks, path glance (tree / full DAG), playtest, and offline ZIP export
- Hard split: editor ≠ player (player is Vanilla TS, no Vue / TipTap)
Useful as a portfolio piece for rich-text / document-model engineering — not just “another CMS editor”.
- Branching story authoring — stages, choices, scores, endings
- TipTap node model — accordion choice editing, insert/link new stages from the tree
- Path glance — tree view by default; full graph with ELK orthogonal routing
- Local AI (Ollama) — choice copy suggestions & skeleton generation via
AiProvider - Playtest & export — in-editor preview; download a static ZIP (
index.html+story.json) - Local-first storage — IndexedDB (Dexie); no cloud required for core flows
- Sample lessons — real workplace training scenarios (communication / compliance / support)
| Layer | Choice |
|---|---|
| Editor app | Vue 3, TipTap 3, Vite, vue-i18n (zh-CN), Dexie |
| Player app | Vanilla TypeScript + Vite (no Vue) |
| Shared contract | @story/schema — Zod + applyChoice / pickEnding |
| AI | @story/ai-provider — Ollama only in v1 |
| Graph | Vue Flow + dagre (tree) / elkjs (full graph) |
| Monorepo | pnpm workspaces |
┌─────────────────────────────────────────┐
│ apps/editor Vue 3 + TipTap + Vite │
│ authoring · AI · playtest · ZIP export │
└───────────────────┬─────────────────────┘
│ StoryDocument JSON
┌───────────────────▼─────────────────────┐
│ packages/story-schema (@story/schema) │
│ Zod · score engine · fixtures │
└───────────────────┬─────────────────────┘
│ embedded in ZIP
┌───────────────────▼─────────────────────┐
│ apps/player Vanilla TS │
│ render nodes · choices · score · end │
└─────────────────────────────────────────┘
editor → ai-provider → schema
editor → schema
player → schema ✗ player → editor / TipTap / AI
Hard rules live in docs/design.md and docs/adr/.
tiptap-story/
├── apps/
│ ├── editor/ # Authoring UI (TipTap)
│ └── player/ # Static runtime for export / playtest
├── packages/
│ ├── story-schema/ # @story/schema
│ └── ai-provider/ # @story/ai-provider
├── docs/ # Architecture, ADRs, screenshots
├── tests/ # Cross-cutting Vitest suites
├── LICENSE
└── README.md
| Path | Reason |
|---|---|
.planning/ |
Product roadmap, phase plans, internal UI reviews |
AGENTS.md / CLAUDE.md |
Local agent / coding-agent harness |
.gsd/ / .cursor/ / .claude/ |
Tooling state |
apps/editor/public/player-dist/ |
Generated player bundle (synced on pnpm dev / build) |
.env* |
Secrets (none required for default local run) |
Source under apps/, packages/, docs/, and tests/ is intended for GitHub.
- Node.js 20+ (LTS recommended)
- pnpm 10+ (
corepack enablethencorepack prepare pnpm@10.30.3 --activate) - Optional: Ollama running locally for AI features
git clone https://github.com/moyunzero/TipTap-Story.git
cd TipTap-Story
pnpm install # also builds @story/schema and @story/ai-provider (prepare)
pnpm dev # editor; syncs player into public/player-dist for ZIP exportOpen the URL printed by Vite (typically http://localhost:5173).
Suggested first path: 样例课 → 打开「沟通」→ 试玩 → 路径鸟瞰 → 导出 ZIP.
The editor Vite plugin builds / syncs the player when needed — first run may take a bit longer.
| Command | Description |
|---|---|
pnpm dev |
Start the editor (builds packages first) |
pnpm dev:player |
Start the player alone (fixture story) |
pnpm build |
Build packages, player, then editor |
pnpm build:packages |
Build @story/schema + @story/ai-provider only |
pnpm test |
Run Vitest |
pnpm typecheck |
TypeScript project references |
pnpm lint |
ESLint + Prettier check |
pnpm format |
Prettier write |
| Concern | Where to look |
|---|---|
| Custom nodes | apps/editor/src/tiptap/extensions/ |
| Vue NodeViews | apps/editor/src/tiptap/node-views/ |
| Insert / delete / link stages | apps/editor/src/tiptap/commands/ |
| Doc ↔ story projection | apps/editor/src/projection/ |
| Shared runtime contract | packages/story-schema/ |
- Install and run Ollama.
- Pull a chat model (e.g.
qwen2:7bor whatever you set in the editor settings). - Allow the editor origin in Ollama CORS, e.g.
OLLAMA_ORIGINS=http://localhost:5173(see Ollama FAQ). - Use choice “AI 补文案” or the new-story skeleton entry.
All model traffic goes through @story/ai-provider — components do not call cloud APIs directly.
pnpm test
pnpm typecheck
pnpm lintColocated *.test.ts files live next to sources; additional suites under tests/. CI runs the same checks on push/PR.
Issues and PRs that improve clarity, tests, or TipTap/schema correctness are welcome. Please keep the editor ≠ player dependency rule intact.