|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +JustWiki is a lightweight, self-hosted wiki for small teams. Markdown-first, single SQLite file, no external dependencies. Backend is Python/FastAPI, frontend is React/Vite. |
| 8 | + |
| 9 | +## Development Commands |
| 10 | + |
| 11 | +```bash |
| 12 | +make setup # First-time: install deps (uv + npm), create .env from .env.example |
| 13 | +make dev # Start backend (port 8000) + frontend (port 5173) concurrently |
| 14 | +make dev-backend # Backend only: uvicorn with --reload on port 8000 |
| 15 | +make dev-frontend # Frontend only: Vite dev server on port 5173 |
| 16 | +make build # Build frontend for production (vite build) |
| 17 | +make test # Run all backend and frontend tests |
| 18 | +make test-backend # Run backend tests with pytest |
| 19 | +make test-frontend # Run frontend tests with vitest |
| 20 | +make lint # Run frontend linting |
| 21 | +make backup # Copy SQLite DB to backup/ with timestamp |
| 22 | +``` |
| 23 | + |
| 24 | +Frontend linting: `cd frontend && npm run lint` |
| 25 | +Backend tests location: `backend/tests/` |
| 26 | +Frontend tests location: `frontend/src/**/*.test.{js,jsx}` |
| 27 | + |
| 28 | +## Architecture |
| 29 | + |
| 30 | +### Backend (`backend/app/`) |
| 31 | + |
| 32 | +- **Framework**: FastAPI (async), aiosqlite for SQLite access (WAL mode) |
| 33 | +- **Entry**: `main.py` — app creation, CORS, lifespan hooks, router mounting |
| 34 | +- **Auth**: `auth.py` — JWT tokens in httpOnly cookies, bcrypt passwords, rate-limited login |
| 35 | +- **Config**: `config.py` — Pydantic Settings reading from `.env` |
| 36 | +- **Database**: `database.py` — schema DDL, migrations, FTS5 search index setup |
| 37 | +- **Routers**: One file per domain — `pages.py`, `search.py`, `media.py`, `versions.py`, `tags.py`, `templates.py`, `users.py`, `diagrams.py`, `comments.py`, `bookmarks.py`, `activity.py`, `backup.py`, `export.py`, `auth_router.py` |
| 38 | +- **Services**: `search.py` (FTS5 indexing, CJK segmentation), `wikilink.py` (backlink tracking) |
| 39 | +- **Deps**: Python 3.11+, managed with `uv` |
| 40 | + |
| 41 | +### Frontend (`frontend/src/`) |
| 42 | + |
| 43 | +- **Framework**: React 19, Vite 8, Tailwind CSS 4 |
| 44 | +- **State**: Zustand stores in `store/` — one per domain (useAuth, usePages, useTags, useBookmarks, useTheme, useSearch, useActivity) |
| 45 | +- **API client**: `api/client.js` — Axios instance with interceptors, 401 redirect to login |
| 46 | +- **Routing**: React Router v7 in `App.jsx`, PrivateRoute wrapper for auth |
| 47 | +- **Keyboard shortcuts**: `hooks/useKeyboard.jsx` (Ctrl+E edit, Ctrl+K search, etc.) |
| 48 | + |
| 49 | +### Editor and Viewer (dual rendering paths) |
| 50 | + |
| 51 | +These are separate systems with independent rendering logic — changes to one do not affect the other. **Always verify both when modifying markdown-related features.** |
| 52 | + |
| 53 | +- **Editor**: `components/Editor/Editor.jsx` — Milkdown (ProseMirror-based) WYSIWYG editor with slash commands, wikilink autocomplete `[[page]]`, image paste upload, GFM support |
| 54 | +- **Viewer**: `components/Viewer/MarkdownViewer.jsx` — Custom markdown-to-HTML parser (not a library). Handles Mermaid diagrams, KaTeX math (`$$...$$`), callout blocks (`:::info`), wikilinks, tables, nested lists. Sanitized with DOMPurify. |
| 55 | + |
| 56 | +### Database (SQLite, single file at `data/just-wiki.db`) |
| 57 | + |
| 58 | +Key tables: `users`, `pages` (with `parent_id` hierarchy and `slug` URL), `page_versions`, `tags`, `page_tags`, `backlinks`, `templates`, `media`, `diagrams`, `comments`, `bookmarks`, `activity_log`. FTS5 virtual table `search_index` for full-text search with CJK support. |
| 59 | + |
| 60 | +Schema auto-migrates on startup in `database.py`. |
| 61 | + |
| 62 | +### Wikilinks |
| 63 | + |
| 64 | +Format: `[[slug]]` or `[[slug|display text]]`. Parsed on both backend (backlink tracking in `backlinks` table via `services/wikilink.py`) and frontend (navigation in viewer). Slug generation uses `pypinyin` for Chinese characters. |
| 65 | + |
| 66 | +## API Structure |
| 67 | + |
| 68 | +All endpoints under `/api/`. Vite dev server proxies `/api` to `localhost:8000`. Key routes: |
| 69 | + |
| 70 | +- Pages CRUD: `/api/pages`, `/api/pages/{slug}`, `/api/pages/tree`, `/api/pages/graph` |
| 71 | +- Versions: `/api/pages/{slug}/versions`, `/api/pages/{slug}/diff/{v1}/{v2}` |
| 72 | +- Search: `/api/search?q=...` |
| 73 | +- Media upload: `POST /api/media/upload` (20MB limit) |
| 74 | +- Auth: `/api/auth/login`, `/api/auth/me` |
| 75 | + |
| 76 | +## Themes |
| 77 | + |
| 78 | +Multiple built-in themes (light, dark, lavender, forest, etc.) via CSS variables in `frontend/src/index.css`, persisted with Zustand store `useTheme.js`. |
| 79 | + |
| 80 | +## Deployment |
| 81 | + |
| 82 | +Docker Compose: backend (uvicorn, port 8000) + frontend (nginx, port 3000). Shared `./data` volume. All config in `.env`. |
0 commit comments