Spaces:
Running
Implementation Plan: Multi-Tenant Obsidian-Like Docs Viewer
Branch: 001-obsidian-docs-viewer | Date: 2025-11-15 | Spec: spec.md
Input: Feature specification from /specs/001-obsidian-docs-viewer/spec.md
Note: This template is filled in by the /speckit.plan command. See .specify/templates/commands/plan.md for the execution workflow.
Summary
Build a multi-tenant Obsidian-like documentation viewer with AI-first workflow (AI writes via MCP, humans read/edit via web UI). System provides per-user vaults with Markdown notes, full-text search, wikilink resolution, tag indexing, and backlink tracking. Backend exposes FastMCP server (STDIO + HTTP transports) and HTTP API with Bearer auth (JWT). Frontend is React SPA with shadcn/ui, featuring directory tree navigation and split-pane editor. Deployment targets: local PoC (single-user, STDIO) and Hugging Face Space (multi-tenant, OAuth).
Technical Approach: Python backend with FastAPI + FastMCP, SQLite per-user indices, filesystem-based vault storage, JWT authentication. React + Vite frontend with react-markdown rendering. Incremental index updates on writes, optimistic concurrency for UI, last-write-wins for MCP.
Technical Context
Language/Version: Python 3.11+ Primary Dependencies: FastAPI, FastMCP, python-frontmatter, PyJWT, huggingface_hub, SQLite (stdlib) Storage: Filesystem (per-user vault directories), SQLite (per-user indices) Testing: pytest (backend unit/integration), Vitest (frontend unit), Playwright (E2E) Target Platform: Linux server (HF Space), local dev (Windows/macOS/Linux) Project Type: Web application (Python backend + React frontend) Performance Goals:
- MCP operations: <500ms (read/write/search) for vaults with 1,000 notes
- UI rendering: <2s directory tree load, <1s note render, <1s search results
- Index rebuild: <30s for 1,000 notes Constraints:
- 1 MiB max note size
- 5,000 notes max per vault
- 256 char max path length
- 100% tenant isolation (security requirement)
- 409 Conflict on concurrent edits (UI only) Scale/Scope:
- MVP: 10 concurrent users (HF Space), 5,000 notes per user
- Local PoC: single user, unlimited notes (within filesystem limits)
Constitution Check
GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.
Status: No project constitution file found at .specify/memory/constitution.md. Constitution check skipped.
Justification: This is a new project without established architectural principles. Design decisions will be documented in research.md and can form the basis of a future constitution if needed.
Project Structure
Documentation (this feature)
specs/001-obsidian-docs-viewer/
βββ plan.md # This file (/speckit.plan command output)
βββ research.md # Phase 0 output (/speckit.plan command)
βββ data-model.md # Phase 1 output (/speckit.plan command)
βββ quickstart.md # Phase 1 output (/speckit.plan command)
βββ contracts/ # Phase 1 output (/speckit.plan command)
β βββ http-api.yaml # OpenAPI 3.1 spec for HTTP API
β βββ mcp-tools.json # MCP tool schemas (JSON Schema)
βββ tasks.md # Phase 2 output (/speckit.tasks command - NOT created by /speckit.plan)
Source Code (repository root)
# Web application structure (Python backend + React frontend)
backend/
βββ src/
β βββ models/ # Pydantic models (Note, User, Index, Config)
β βββ services/
β β βββ vault.py # Filesystem vault operations
β β βββ indexer.py # Full-text search, tags, link graph
β β βββ auth.py # JWT + HF OAuth integration
β β βββ config.py # Configuration management
β βββ api/
β β βββ main.py # FastAPI app + middleware
β β βββ routes/ # API endpoints (notes, search, auth, index)
β β βββ middleware/ # Auth middleware, error handlers
β βββ mcp/
β βββ server.py # FastMCP server (STDIO + HTTP)
βββ tests/
β βββ unit/ # Service-level tests
β βββ integration/ # API + MCP integration tests
β βββ contract/ # Contract tests for MCP tools + HTTP API
βββ pyproject.toml # Python dependencies (Poetry/pip)
frontend/
βββ src/
β βββ components/
β β βββ ui/ # shadcn/ui components
β β βββ DirectoryTree.tsx
β β βββ NoteViewer.tsx
β β βββ NoteEditor.tsx
β β βββ SearchBar.tsx
β β βββ AuthFlow.tsx
β βββ pages/
β β βββ App.tsx # Main app layout
β β βββ Login.tsx # HF OAuth landing
β β βββ Settings.tsx # User profile + token management
β βββ services/
β β βββ api.ts # HTTP API client (fetch wrapper)
β β βββ auth.ts # Token management, OAuth helpers
β βββ lib/
β β βββ wikilink.ts # Wikilink parsing + resolution
β β βββ markdown.ts # react-markdown config
β βββ types/ # TypeScript types (Note, User, SearchResult)
βββ tests/
β βββ unit/ # Component tests (Vitest + Testing Library)
β βββ e2e/ # Playwright E2E tests
βββ package.json # Node dependencies
βββ vite.config.ts # Vite build config
data/ # Runtime data (gitignored)
βββ vaults/
βββ <user_id>/ # Per-user vault directories
.env.example # Environment template (JWT_SECRET, HF OAuth, etc.)
README.md # Setup instructions, MCP client config examples
Structure Decision: Web application structure selected based on spec requirements for Python backend (FastAPI + FastMCP) and React frontend (shadcn/ui). Backend and frontend are separate codebases to support independent development/testing cycles, with backend serving frontend as static files in production (HF Space). Data directory is runtime-only (vaults + SQLite indices), not version controlled.
Complexity Tracking
No constitution violations to track (no project constitution exists yet)
Phase 0: Research & Technical Decisions
Status: Research required for technology integration patterns and best practices.
Research Topics:
- FastMCP HTTP transport authentication patterns (Bearer token validation)
- Hugging Face Space OAuth integration best practices (attach/parse helpers)
- SQLite schema design for per-user multi-index storage (full-text + tags + links)
- Wikilink normalization and resolution algorithms (slug matching, ambiguity handling)
- React + shadcn/ui directory tree component patterns (collapsible, virtualization)
- Optimistic concurrency implementation patterns (ETags vs version counters)
- Markdown frontmatter parsing with fallback strategies (malformed YAML handling)
- JWT token management in React (localStorage vs memory, refresh strategies)
Output: See research.md for detailed findings and decisions.
Phase 1: Data Model & Contracts
Prerequisites: research.md complete
Data Model
Entities (see data-model.md for full schemas):
- User:
user_id,hf_profile(optional),vault_path,created_at - Note:
path,title,metadata,body,version,created,updated - Wikilink:
source_path,link_text,target_path(nullable),is_resolved - Tag:
tag_name,note_paths[] - Index:
user_id,note_count,last_full_rebuild,last_incremental_update - Token:
jwt(claims:sub,exp,iat)
API Contracts
HTTP API (see contracts/http-api.yaml):
- Authentication:
POST /api/tokens,GET /api/me - Notes CRUD:
GET /api/notes,GET /api/notes/{path},PUT /api/notes/{path},DELETE /api/notes/{path} - Search:
GET /api/search?q=<query> - Navigation:
GET /api/backlinks/{path},GET /api/tags - Index:
GET /api/index/health,POST /api/index/rebuild
MCP Tools (see contracts/mcp-tools.json):
list_notes:{folder?: string}β[{path, title, last_modified}]read_note:{path: string}β{path, title, metadata, body}write_note:{path, title?, metadata?, body}β{status, path}delete_note:{path: string}β{status}search_notes:{query: string}β[{path, title, snippet}]get_backlinks:{path: string}β[{path, title}]get_tags:{}β[{tag, count}]
Quickstart
Output: See quickstart.md for:
- Local development setup (Python venv, Node install, env config)
- Running backend (STDIO MCP + HTTP API)
- Running frontend (Vite dev server)
- MCP client configuration (Claude Code STDIO example)
- Testing workflows (unit, integration, E2E)
Phase 2: Task Generation
Not included in this command - run /speckit.tasks to generate dependency-ordered implementation tasks based on this plan and the data model.
Execution Summary
Phase 0: Research & Technical Decisions β COMPLETE
Generated: research.md (1,407 lines)
Researched and Resolved:
- β
FastMCP HTTP transport authentication patterns β Bearer token with
BearerAuth, JWT validation - β
Hugging Face Space OAuth integration β
attach_huggingface_oauth+parse_huggingface_oauthhelpers - β SQLite schema design β FTS5 contentless + separate tags/links tables with per-user isolation
- β Wikilink normalization β Case-insensitive normalized slug matching, same-folder preference
- β React + shadcn/ui directory tree β shadcn-extension Tree View with TanStack Virtual virtualization
- β
Optimistic concurrency β Version counter in SQLite +
if_versionparameter, 409 on mismatch - β
Markdown frontmatter parsing β
python-frontmatterwith try-except fallback for malformed YAML - β JWT token management β Memory storage (MVP) or memory + HttpOnly cookie (production)
Key Decisions:
- FTS5 with porter tokenizer and
prefix='2 3'for autocomplete - shadcn-extension tree handles 5,000+ notes with <200ms render
- Version counter is simpler and faster than content hashing
- Hybrid JWT approach (memory + HttpOnly) is 2025 security best practice
Phase 1: Data Model & Contracts β COMPLETE
Generated:
data-model.md- Complete entity definitions, Pydantic models, TypeScript types, SQLite schema, validation rules, state transitionscontracts/http-api.yaml- OpenAPI 3.1 spec with 11 endpoints, auth, all error responses, examplescontracts/mcp-tools.json- 7 MCP tool schemas with JSON Schema validation, usage examplesquickstart.md- Complete setup, run, test, deploy guide for local PoC and HF Space
Data Model Highlights:
- 7 core entities (User, Vault, Note, Wikilink, Tag, Index, Token)
- Complete Pydantic models with validators
- TypeScript types for frontend
- SQLite DDL with 5 tables (metadata, FTS, tags, links, health)
- State machines for note lifecycle and index updates
API Contract Highlights:
- HTTP API: 11 endpoints (auth, CRUD, search, navigation, index)
- MCP Tools: 7 tools (list, read, write, delete, search, backlinks, tags)
- All error codes documented (400, 401, 403, 409, 413, 500)
- Request/response examples for all operations
Agent Context Updated:
- β
Updated
/home/wolfe/Projects/Document-MCP/CLAUDE.mdwith Python 3.11+, FastAPI, FastMCP, SQLite tech stack
Constitution Re-Check β N/A
Status: No project constitution exists. Design decisions documented in research.md can form future constitution baseline.
Next Steps
Run /speckit.tasks to generate dependency-ordered implementation tasks based on this plan, data model, and contracts.
Planning Phase Complete: 2025-11-15