Skip to content

Repository files navigation

NoteGraph

A self-hosted notes app with auto-linked knowledge graph and grounded chat over your notes (RAG). React + FastAPI + SQLite + sqlite-vec.

Status: working prototype. Auth is dev-mode only — see Security before exposing this to the internet.

What it does

  • Markdown notes with autosave, search, #tag filtering, edit/preview toggle, word counts.
  • Auto-linking — every note shows related notes by embedding similarity. No manual [[wikilinks]].
  • Knowledge graph — interactive force-directed view with cluster detection.
  • Multi-pane workspace — split into up to four panes (editor / graph / chat). Drag-and-drop notes into panes. Resizable.
  • Chat (RAG) — ask questions about a team's notes. Streamed answers with inline numbered citations you can expand to see the grounding chunk.
  • Save-as-note — turn a chat answer into a new note with provenance metadata (source="llm", derived_from=[note_ids]).
  • Teams — team-scoped collections with viewer / editor / owner roles.
  • Ingestion — paste text, upload files (.txt / .md / .pdf), or just write notes. Re-ingest is idempotent.
  • 8 themes, keyboard shortcuts, mobile-responsive.

Architecture

┌──────────────┐     ┌────────────────┐     ┌─────────────────┐
│ React + Vite │ ──► │ FastAPI server │ ──► │ SQLite + vec0   │
│  (Tailwind)  │ SSE │  (uvicorn)     │     │ (sqlite-vec)    │
└──────────────┘     └────────────────┘     └─────────────────┘
                              │
                              ▼
                    ┌──────────────────┐
                    │ LLM + Embedder   │
                    │ via LlamaIndex   │
                    └──────────────────┘
  • One SQLite file (data/notes.db) holds notes, teams, members, tags, AND the chunks + chunk_embeddings (vec0) tables.
  • Pluggable LLM/embedder providers: azure_openai / openai / anthropic / ollama / huggingface — configured in config.toml.
  • Default chunker is heading-aware (backend/services/chunking.py); falls back to LlamaIndex SentenceSplitter via config flag.
  • Optional cross-encoder reranker (off by default; ~3s p50 on CPU).

See PLAN.md for the phased roadmap and ISSUES.md for the open punch list.

Quick start

Requirements: Node 20+, Python 3.12+, an LLM API key.

# 1. Install deps (creates .venv and installs Python + npm packages)
python -m venv .venv
make install

# 2. Configure
cp .env.example .env
# Edit .env to add AZURE_OPENAI_API_KEY (or another provider's key)
# Edit config.toml if you want to change the LLM/embedder

# 3. Run
make dev   # starts vite (5173) + uvicorn (3001) concurrently

Open http://localhost:5173. The Vite dev server proxies /api/* to the backend on port 3001.

For production: npm run build && npm run start — the FastAPI app serves the built SPA.

Configuration

Single config file: config.toml. Sections:

  • [llm] — provider, model, deployment, base_url, api_version, temperature
  • [embedding] — provider, model, dim (locked at first ingestion)
  • [vector_store]sqlite_vec only for now
  • [chunking]strategy (notes or sentence_splitter), chunk_size, chunk_overlap, short_note_token_threshold
  • [retrieval]top_k, optional reranker_model, rerank_fetch_k

API keys are read from env (AZURE_OPENAI_API_KEY, OPENAI_API_KEY, ANTHROPIC_API_KEY).

Note: changing [embedding].dim triggers a one-time chunk wipe — the vec0 table is dim-locked at create time.

Tests

make test       # full suite (pytest + Playwright)
make test-py    # python only
make test-e2e   # browser e2e (needs `npx playwright install chromium` once)
make test-eval  # run the RAG eval harness on the seed query set

Coverage:

  • pytest: chunker, retrieval, reranker, ingest API, chat API, sharing/permissions, write-back, eval components.
  • Playwright: smoke test runs green; richer specs are noted as drift-prone in ISSUES.md.
  • Eval harness (backend/eval/): recall@k, mrr, ndcg@k, hit@k, plus LLM-as-judge for faithfulness / answer relevance / context relevance. Reports go to backend/eval/reports/.

See backend/tests/README.md for what is and isn't covered.

Security

⚠️ This is a prototype. It is not production-multi-tenant-ready.

  • Authentication is dev-mode: the X-User-Email request header identifies the caller; missing → dev@local. There are no sessions, cookies, OAuth, CSRF protection, or rate limiting.
  • Sharing tests verify the per-collection vector-store filter (no cross-team leakage), but green tests here do not mean the auth surface is secure.
  • Run it locally or behind your own auth proxy. Don't expose it to the open internet without bolting real auth onto backend/services/users.py:resolve_current_user.

Repository layout

src/                   React frontend (components, hooks, themes)
backend/             FastAPI backend
  routers/             HTTP endpoints (notes, teams, members, chat, ingest, …)
  services/            Domain logic (chat, retrieval, chunking, permissions, …)
  models/              Pydantic schemas
  vector_store/        sqlite-vec backend
  llm/                 LlamaIndex factory (LLM + embedder providers)
  config/              TOML config loader
  eval/                RAG eval harness (metrics, judge, runner, fixtures)
  tests/               pytest suite
e2e/                   Playwright specs
scripts/               eval CLI shim, synthetic-corpus generator
public/                PWA icons + manifest + service worker

Contributing

Open an issue first for non-trivial changes. PRs that regress eval metrics need an explicit tradeoff note (see PLAN.md cross-cutting concerns).

License

MIT — see LICENSE.

About

Markdown notes app with embedding-based auto-linking, a force-directed knowledge graph, team-scoped RAG chat with inline citations, and one-click save-as-note write-back.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages