# Personal Knowledge Manager (PKM) — Concrete Backlog Scope for v1 (agreed) - Single vault folder on disk (user-provided path). - Files are Markdown with YAML front matter; Obsidian-compatible (front matter, [[WikiLinks]], relative links, optional inline #tags). - Flask backend; Tailwind + DaisyUI frontend; server-rendered pages with light JS. - CodeMirror 6 editor from the start. - Search/index via SQLite FTS5 stored under .kb/index.sqlite within the vault. - No Git versioning and no graph view in v1 (reserved for later). Non-goals for v1 - Multi-user auth, sync, remote deployment concerns. - Git auto-commit/history UI. - Graph visualization. - Plugin system. Definitions and conventions - Note file naming: slugified from title, e.g., `notes/event-sourcing-overview.md`. - Front matter includes: id (UUID), title, created, updated; optional aliases, tags, status, summary, template. - Backlinks stored in index (not written into files). - [[WikiLinks]] resolve by title/alias/slug; Markdown links preserved and resolved relatively. - Vault internals live under `/.kb/` (SQLite index, config, cache). Milestone 0 — Project scaffolding - Tasks - Initialize Flask app scaffolding and configuration. - Tailwind + DaisyUI build pipeline via Tailwind CLI. - Base Jinja templates and minimal layout with DaisyUI theme. - Environment/config management (vault path, debug). - Acceptance criteria - App starts with `flask run` (or a `python -m` entrypoint). - Tailwind builds and serves CSS; DaisyUI classes render correctly. - Config reads vault path from env/config and shows a welcome page. Milestone 1 — Vault and note model - Tasks - Filesystem repository for notes (read/write Markdown + YAML front matter). - Create new note with required metadata; slugify filenames from `title`. - Validate and normalize metadata (UUID, ISO timestamps). - Resolve note identity by `id` independent of filename changes. - Acceptance criteria - Can create a note; it is saved to disk with valid front matter. - Can read an existing note and get parsed metadata + body. - Tests for slug generation and metadata normalization. Milestone 2 — Rendering and viewing - Tasks - Markdown rendering via markdown-it-py with plugins (tables, task lists, footnotes, admonitions). - HTML sanitization (bleach) with a safe allowlist. - Obsidian-compatible rendering: [[WikiLinks]] clickable, resolve to note routes; render relative links and attachments; optionally parse inline #tags. - Basic note view page: title, metadata pills (tags/status), content, attachments preview. - Acceptance criteria - Visiting a note route renders sanitized HTML. - [[WikiLinks]] and relative links resolve; unknown links are indicated. - Attachment links/images load from the vault. Milestone 3 — Editor with CodeMirror 6 - Tasks - Note edit page using CodeMirror 6 (Markdown extensions, basic shortcuts). - Front matter editor (simple form for title/tags/status; syncs with file). - Save flow: update `updated`; create if new; optimistic UI. - Drag-and-drop/paste image => save under `attachments/` and insert relative path. - Acceptance criteria - Can create, edit, and save notes from the browser. - Pasting/dragging an image adds a file and inserts a link. - Title change updates slug/filename on save (see Milestone 6 for link rewrites). Milestone 4 — Indexing and search (SQLite FTS5) - Tasks - SQLite schema under `/.kb/index.sqlite`. - Initial indexing pass: ingest existing notes (title, body, tags, path, id). - File watching (watchdog) for incremental index updates on add/edit/delete/rename. - Search API with filters (q=, tag=, status=, path=) and boosting (title > tags > body). - Search UI with instant results (debounced) and simple filters. - Acceptance criteria - Searching returns relevant notes quickly. - Edits trigger index updates without manual rebuild. - Tag list and per-tag results available. Milestone 5 — Links and backlinks - Tasks - Outbound link extraction (Markdown links + [[WikiLinks]]); store in index. - Backlinks computation and storage; display backlinks in note view. - Handle aliases/title collisions deterministically (id/slug precedence). - Acceptance criteria - Each note shows backlinks (with context snippet if available). - Creating a link updates backlinks after save. Milestone 6 — Rename/move and link maintenance - Tasks - Rename/move note (on title or folder change): update slug/path on disk. - Inbound link rewrite: update Markdown files that link to the old path/slug. - Safe operations (backup to temp, atomic writes) and dry-run option (internal). - Acceptance criteria - Renaming a note updates its filename and maintains working links in other notes. - Index reflects new paths; no broken links in backlinking notes. Milestone 7 — UX polish - Tasks - Command palette / quick open (fuzzy search) and keyboard shortcuts. - DaisyUI theme switch (light/dark/system) and remember preference. - Empty states, loading states, toasts for save operations. - Acceptance criteria - Keyboard-driven navigation works end-to-end. - Theme switch persists and is applied. Milestone 8 — Packaging and quality - Tasks - CLI launcher: `pkm run --vault /path/to/vault` (or `python -m pkm`). - Basic error pages and diagnostics (e.g., FTS5 availability, permission errors). - Unit tests for core services (parsing, indexing, link rewrite). - Minimal Dockerfile (optional) for local use with volume mount. - Acceptance criteria - One-command startup with vault path. - Tests for core logic pass in CI (if configured). Deferred items (post-v1) - Git auto-commit/history and diffs. - Graph view. - Auth for remote hosting. - Templates/daily notes generator; import/export UI; plugin hooks. Risks and mitigations - FTS5 availability: detect and warn at startup; fall back to basic search read-path if unavailable (optional). - Large vault performance: chunked indexing, debounced file watcher, background tasks with status UI. - Link rewrite safety: transactional writes with backups; verify before replace. ```mermaid flowchart LR A[Vault] -->|Parse| B[Note Model] B --> C[Render Markdown] B --> D[Index FTS5] D --> E[Search API/UI] B --> F[Link Extract] F --> G[Backlinks] B --> H[Editor (CM6)] H -->|Save| A H -->|Save| D H -->|Save| F ```