Initial commit.
This commit is contained in:
140
docs/BACKLOG.md
Normal file
140
docs/BACKLOG.md
Normal file
@@ -0,0 +1,140 @@
|
||||
# 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 `<vault>/.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 `<vault>/.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
|
||||
```
|
125
docs/STRUCTURE.md
Normal file
125
docs/STRUCTURE.md
Normal file
@@ -0,0 +1,125 @@
|
||||
# Initial Directory Structure
|
||||
|
||||
This is the proposed repository structure (application code), plus expected vault layout on disk.
|
||||
|
||||
Repository tree
|
||||
```
|
||||
.
|
||||
├─ app/
|
||||
│ ├─ __init__.py # Flask app factory and Jinja/Tailwind integration
|
||||
│ ├─ config.py # Config: vault path, debug flags, security, etc.
|
||||
│ ├─ routes/
|
||||
│ │ ├─ notes.py # List/view/create/edit/delete notes; rename/move
|
||||
│ │ ├─ search.py # Search endpoints (JSON + HTML)
|
||||
│ │ ├─ tags.py # Tags listing and per-tag view
|
||||
│ │ ├─ attachments.py # Upload/serve attachments
|
||||
│ │ └─ api.py # JSON APIs (if split from HTML routes)
|
||||
│ ├─ services/
|
||||
│ │ ├─ vault.py # Vault path mgmt, discovery, .kb paths
|
||||
│ │ ├─ notes_fs.py # Read/write Markdown + YAML; slugging; UUID mgmt
|
||||
│ │ ├─ renderer.py # Markdown-it-py + bleach sanitization
|
||||
│ │ ├─ indexer.py # SQLite FTS5 schema + indexing + queries
|
||||
│ │ ├─ links.py # Extract Markdown/[[WikiLinks]]; resolve; backlinks
|
||||
│ │ └─ watcher.py # watchdog observers to update index on changes
|
||||
│ ├─ utils/
|
||||
│ │ ├─ time.py # ISO timestamp helpers
|
||||
│ │ ├─ slugs.py # Slugify utilities
|
||||
│ │ └─ paths.py # Safe atomic writes, backups, path utils
|
||||
│ ├─ templates/
|
||||
│ │ ├─ _partials/
|
||||
│ │ │ ├─ navbar.html
|
||||
│ │ │ ├─ note_meta.html # Tags/status/aliases pills
|
||||
│ │ │ └─ search_box.html
|
||||
│ │ ├─ base.html # DaisyUI layout; theme switch; CSS/JS includes
|
||||
│ │ ├─ home.html # Recent notes; quick search
|
||||
│ │ ├─ notes/
|
||||
│ │ │ ├─ list.html
|
||||
│ │ │ ├─ view.html # Content + backlinks + outbound links
|
||||
│ │ │ └─ edit.html # CodeMirror editor + metadata form
|
||||
│ │ └─ search/
|
||||
│ │ └─ results.html
|
||||
│ ├─ static/
|
||||
│ │ ├─ css/
|
||||
│ │ │ ├─ input.css # @tailwind base; @tailwind components; @tailwind utilities;
|
||||
│ │ │ └─ app.css # Built CSS (gitignored if desired)
|
||||
│ │ ├─ js/
|
||||
│ │ │ ├─ editor.js # CodeMirror 6 init (ESM); drag-drop/paste handler
|
||||
│ │ │ └─ app.js # Small client-side helpers (palette, shortcuts)
|
||||
│ │ └─ imgs/
|
||||
│ │ └─ logo.svg
|
||||
│ └─ schema.sql # SQLite schema incl. FTS5 and backlinks tables
|
||||
├─ cli.py # CLI entrypoint: `pkm run --vault <path>`
|
||||
├─ pyproject.toml # Python project + dependencies (Flask, markdown-it-py, bleach, watchdog, pyyaml)
|
||||
├─ requirements.txt # (optional alternative to pyproject)
|
||||
├─ tailwind.config.cjs # Tailwind + DaisyUI plugin config
|
||||
├─ postcss.config.cjs # (optional, if using PostCSS plugins explicitly)
|
||||
├─ package.json # Dev deps: tailwindcss, daisyui; scripts to build/watch CSS
|
||||
├─ .gitignore
|
||||
├─ .env.example # KB_VAULT_PATH=...
|
||||
└─ README.md
|
||||
```
|
||||
|
||||
SQLite schema outline (`app/schema.sql`)
|
||||
```sql
|
||||
-- Notes catalog (lightweight metadata separate from content)
|
||||
CREATE TABLE IF NOT EXISTS notes (
|
||||
id TEXT PRIMARY KEY, -- UUID
|
||||
path TEXT NOT NULL, -- relative to vault root, e.g., notes/foo/bar.md
|
||||
title TEXT NOT NULL,
|
||||
created TEXT NOT NULL, -- ISO UTC
|
||||
updated TEXT NOT NULL, -- ISO UTC
|
||||
tags TEXT, -- JSON-encoded array or comma-separated
|
||||
status TEXT,
|
||||
aliases TEXT -- JSON-encoded array
|
||||
);
|
||||
|
||||
-- Backlinks (resolved by id)
|
||||
CREATE TABLE IF NOT EXISTS links (
|
||||
src_id TEXT NOT NULL,
|
||||
dst_id TEXT NOT NULL,
|
||||
src_anchor TEXT, -- optional: section/heading/context
|
||||
PRIMARY KEY (src_id, dst_id)
|
||||
);
|
||||
|
||||
-- FTS5 virtual table for full-text search
|
||||
CREATE VIRTUAL TABLE IF NOT EXISTS notes_fts
|
||||
USING fts5(
|
||||
title, body, tags,
|
||||
content='',
|
||||
tokenize='porter' -- or unicode61 with custom config
|
||||
);
|
||||
|
||||
-- Content-to-FTS sync tables (manual sync via triggers or code)
|
||||
CREATE TABLE IF NOT EXISTS notes_content (
|
||||
id TEXT PRIMARY KEY,
|
||||
body TEXT NOT NULL
|
||||
);
|
||||
```
|
||||
|
||||
Vault layout on disk (user-provided path; created/validated at first run)
|
||||
```
|
||||
<vault>/
|
||||
├─ notes/ # Markdown notes (nested folders allowed)
|
||||
├─ attachments/ # Images/PDFs and other assets
|
||||
└─ .kb/
|
||||
├─ index.sqlite # FTS5 index + backlinks + metadata cache
|
||||
├─ config.yml # App config/preferences (optional for v1)
|
||||
└─ cache/ # Thumbnails, temp files (optional)
|
||||
```
|
||||
|
||||
Dependencies (initial)
|
||||
- Python: Flask, Jinja2, markdown-it-py, bleach, PyYAML (or python-frontmatter), watchdog, click (for CLI).
|
||||
- System: SQLite with FTS5 enabled (commonly available).
|
||||
- Frontend: Tailwind CSS, DaisyUI (Tailwind plugin), CodeMirror 6 via ESM imports (from CDN) or npm if bundling later.
|
||||
|
||||
Scripts (suggested)
|
||||
- package.json
|
||||
- build: `tailwindcss -c tailwind.config.cjs -i ./app/static/css/input.css -o ./app/static/css/app.css --minify`
|
||||
- watch: `tailwindcss -c tailwind.config.cjs -i ./app/static/css/input.css -o ./app/static/css/app.css --watch`
|
||||
- CLI
|
||||
- `python cli.py run --vault /path/to/vault` (wraps Flask app with vault path)
|
||||
|
||||
Notes
|
||||
- Keep server-rendered pages; use minimal JS for editor and quick search.
|
||||
- Sanitize rendered HTML; set a Content Security Policy where possible.
|
||||
- For Obsidian compatibility, prefer not to modify file structure beyond `.kb` internals.
|
Reference in New Issue
Block a user