pagedex 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/README.md +9 -0
- package/docs/development.md +34 -0
- package/docs/getting-started.md +52 -0
- package/docs/mcp-and-api.md +58 -0
- package/docs/security.md +25 -0
- package/docs/supported-files.md +33 -0
- package/package.json +2 -1
package/docs/README.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# pagedex Documentation
|
|
2
|
+
|
|
3
|
+
User, integration, and developer guides for **pagedex**.
|
|
4
|
+
|
|
5
|
+
- [Getting Started](./getting-started.md) — CLI flags, environment variables, UI features, wikilinks, Git sync, and mobile gestures.
|
|
6
|
+
- [Supported File Types](./supported-files.md) — Markdown/MDX, sandboxed HTML + sibling assets, PDF, audio/video, CSV/TSV, SVG, code, and binaries.
|
|
7
|
+
- [MCP & REST API](./mcp-and-api.md) — Connecting AI clients to `/mcp`, the 5 vault tools, REST endpoints, `/raw/*`, and SSE live reload.
|
|
8
|
+
- [Security Model](./security.md) — Sandboxed HTML iframes, CSP/CORS behavior, `Origin: null` guard, and path protection.
|
|
9
|
+
- [Development & Release](./development.md) — Running `pnpm dev`, unit & smoke tests, and npm packaging.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Development & Release
|
|
2
|
+
|
|
3
|
+
## Running in Development
|
|
4
|
+
|
|
5
|
+
Start both the Hono API/MCP/Raw server (`:4321`) and Vite HMR dev server (`:5173`):
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm install
|
|
9
|
+
PAGEDEX_ROOT=~/vault HOST=0.0.0.0 pnpm dev
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
- **Dev UI:** `http://<host>:5173` (Vite proxies `/api/v1`, `/raw`, and `/mcp` with `xfwd: true` to `127.0.0.1:4321`)
|
|
13
|
+
- **API / Production UI:** `http://<host>:4321`
|
|
14
|
+
|
|
15
|
+
## Build & Test
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pnpm build # Build production React bundle into dist/
|
|
19
|
+
pnpm test # Run node:test suite (test/api-mcp.test.js)
|
|
20
|
+
pnpm smoke # Run REST + multi-era MCP smoke checks against :4321
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## npm Package Contents
|
|
24
|
+
|
|
25
|
+
`package.json` restricts the published tarball via `"files"` and runs `prepublishOnly: "vite build"`:
|
|
26
|
+
|
|
27
|
+
- **Included:** `package.json`, `README.md`, `docs/**`, `bin/pagedex.js`, `src/server/**`, and compiled `dist/**`.
|
|
28
|
+
- **Excluded:** `src/client/**`, `.agents/`, `AGENTS.md`, `test/`, `vite.config.js`, `.github/`.
|
|
29
|
+
|
|
30
|
+
Verify exact tarball contents before publishing with:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm pack --dry-run
|
|
34
|
+
```
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Getting Started
|
|
2
|
+
|
|
3
|
+
`pagedex` turns any local folder of notes, code, media, and HTML into a fast web catalog with full-text search, backlinks, Git sync, and an MCP server on a single port.
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
- **Node.js `>= 22.5.0`** (uses built-in `node:sqlite` for FTS5 trigram search)
|
|
8
|
+
|
|
9
|
+
## Running with `npx`
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# Serve the current directory on http://127.0.0.1:4321
|
|
13
|
+
npx pagedex
|
|
14
|
+
|
|
15
|
+
# Serve a specific folder and open it in your browser
|
|
16
|
+
npx pagedex ~/vault --open
|
|
17
|
+
|
|
18
|
+
# Expose on your LAN / Tailscale IP
|
|
19
|
+
npx pagedex ~/vault --host 0.0.0.0 --port 4321
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### CLI Options
|
|
23
|
+
|
|
24
|
+
| Flag | Env Var | Default | Description |
|
|
25
|
+
|---|---|---|---|
|
|
26
|
+
| `[dir]` | `PAGEDEX_ROOT` / `VAULT_ROOT` | `process.cwd()` | Root directory to serve |
|
|
27
|
+
| `-p, --port <port>` | `PORT` | `4321` | HTTP port |
|
|
28
|
+
| `-H, --host <host>` | `HOST` | `127.0.0.1` | Bind address (`0.0.0.0` for LAN/Tailscale) |
|
|
29
|
+
| `-o, --open` | — | `false` | Open browser on startup |
|
|
30
|
+
| `-v, --version` | — | — | Print version |
|
|
31
|
+
| `-h, --help` | — | — | Print CLI help |
|
|
32
|
+
|
|
33
|
+
### Search Index Cache
|
|
34
|
+
|
|
35
|
+
The SQLite FTS5 trigram index is stored **outside** your target folder at `~/.cache/pagedex/<sha256>.db`, so running `pagedex` never creates untracked files in your Git repository.
|
|
36
|
+
|
|
37
|
+
Override the cache location with:
|
|
38
|
+
- `PAGEDEX_INDEX_DIR` — directory for `<hash>.db` files
|
|
39
|
+
- `PAGEDEX_INDEX_PATH` — exact `.db` file path
|
|
40
|
+
|
|
41
|
+
## Web UI Highlights
|
|
42
|
+
|
|
43
|
+
- **View Modes (top-right `⋮` menu):**
|
|
44
|
+
- **Download** — downloads any open file via `/api/v1/file?path=...&download=1`
|
|
45
|
+
- **Preview** — rendered Markdown, sandboxed HTML, PDF, audio/video, CSV/TSV tables, or images
|
|
46
|
+
- **Edit** — lazy-loaded Tiptap WYSIWYG editor for Markdown (`.md`, `.markdown`, `.mdx`)
|
|
47
|
+
- **Diff** — line-by-line Git diff with per-line, per-hunk, and per-file discard
|
|
48
|
+
- **Raw** — syntax-highlighted source (including SVG XML, HTML, CSV, and code)
|
|
49
|
+
- **Wikilinks & Backlinks:** `[[note]]` and relative links resolve across the folder, and the outline panel lists incoming backlinks.
|
|
50
|
+
- **Git Integration:** Browse changed files in the Changes tab, inspect hunks, discard changes, or commit & push directly from the UI.
|
|
51
|
+
- **Live Reload (SSE):** External edits on disk (e.g. from your editor or an AI agent via MCP) refresh open files and the sidebar tree automatically via `/api/v1/events`.
|
|
52
|
+
- **Mobile Friendly:** Edge-swipe gestures open the left file drawer and right outline drawer, with long-press context actions in the tree.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# MCP & REST API
|
|
2
|
+
|
|
3
|
+
`pagedex` exposes both a multi-era **Model Context Protocol (MCP)** server and a **REST API** on the same port (`4321` by default).
|
|
4
|
+
|
|
5
|
+
## MCP Server (`/mcp`)
|
|
6
|
+
|
|
7
|
+
The `/mcp` endpoint supports three MCP protocol eras simultaneously:
|
|
8
|
+
- **`2026-07-28`** (`server/discover` + Streamable HTTP)
|
|
9
|
+
- **`2025-11-25`** (legacy Streamable HTTP `initialize`)
|
|
10
|
+
- **`2024-11-05`** (legacy HTTP+SSE)
|
|
11
|
+
|
|
12
|
+
### Example Client Config
|
|
13
|
+
|
|
14
|
+
Point any HTTP-capable MCP client (Claude Code, Cursor, VS Code, etc.) at:
|
|
15
|
+
|
|
16
|
+
```json
|
|
17
|
+
{
|
|
18
|
+
"mcpServers": {
|
|
19
|
+
"pagedex": {
|
|
20
|
+
"url": "http://127.0.0.1:4321/mcp"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Exposed MCP Tools
|
|
27
|
+
|
|
28
|
+
| Tool | Purpose |
|
|
29
|
+
|---|---|
|
|
30
|
+
| `list_vault` | List files/folders and metadata in the served root |
|
|
31
|
+
| `read_note` | Read file contents and backlinks |
|
|
32
|
+
| `search_vault` | Run SQLite FTS5 trigram full-text search |
|
|
33
|
+
| `write_note` | Create, overwrite, append, or patch (`target` → `replacement`) files |
|
|
34
|
+
| `delete_note` | Delete a file from disk and update the search index |
|
|
35
|
+
|
|
36
|
+
## REST API (`/api/v1/*`)
|
|
37
|
+
|
|
38
|
+
| Method & Path | Description |
|
|
39
|
+
|---|---|
|
|
40
|
+
| `GET /api/v1/health` | Health check and resolved `root` path |
|
|
41
|
+
| `GET /api/v1/tree` | Full directory tree, `flatFiles`, `fileStats`, `backlinks` (`?sort=mtime\|name`, `?limit=`) |
|
|
42
|
+
| `GET /api/v1/files` | Paginated file listing (`?sort=`, `?offset=`, `?limit=`, `?q=`) |
|
|
43
|
+
| `GET /api/v1/search` | Full-text search (`?q=`, `?limit=`) |
|
|
44
|
+
| `GET /api/v1/file` | Read/stream a file (`?path=`, optional `?download=1`, supports HTTP `Range`) |
|
|
45
|
+
| `PUT / POST / PATCH /api/v1/file` | Create, append (`append: true`), or partial-edit (`target`, `replacement`) |
|
|
46
|
+
| `DELETE /api/v1/file` | Delete file (`?path=`) |
|
|
47
|
+
| `POST /api/v1/file/upload` | Multipart file upload into a target folder |
|
|
48
|
+
| `POST /api/v1/file/rename` | Rename/move a file |
|
|
49
|
+
| `POST /api/v1/dir/rename` | Rename/move a directory |
|
|
50
|
+
| `GET /api/v1/changes` | Git working-tree changes |
|
|
51
|
+
| `GET /api/v1/git/diff` | Parsed diff hunks for a file (`?path=`) |
|
|
52
|
+
| `POST /api/v1/git/discard` | Discard line, hunk, or entire file changes |
|
|
53
|
+
| `POST /api/v1/git/commit` | Commit selected files (and optional push) |
|
|
54
|
+
| `GET /api/v1/events` | Server-Sent Events stream for live filesystem changes |
|
|
55
|
+
|
|
56
|
+
## Static / Raw Route (`/raw/*`)
|
|
57
|
+
|
|
58
|
+
`GET /raw/<relPath>` serves files by URL path rather than query string so HTML previews can load sibling assets (`style.css`, `app.js`, `data.json`) with relative URLs. See [Security Model](./security.md) for isolation details.
|
package/docs/security.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Security Model
|
|
2
|
+
|
|
3
|
+
## Sandboxed HTML Previews
|
|
4
|
+
|
|
5
|
+
When previewing `.html` / `.htm` files:
|
|
6
|
+
|
|
7
|
+
1. **Iframe isolation (`sandbox="allow-scripts"`):**
|
|
8
|
+
- `allow-same-origin` is intentionally omitted.
|
|
9
|
+
- The iframe runs with an opaque (`null`) origin, so scripts inside vault HTML cannot access `window.parent`, `localStorage`, cookies, or pagedex's DOM.
|
|
10
|
+
- Top-level navigation, popups, and form submissions are disabled.
|
|
11
|
+
|
|
12
|
+
2. **`Origin: null` API guard (`src/server/index.js`):**
|
|
13
|
+
- Mutating requests (`POST`, `PUT`, `PATCH`, `DELETE`) to `/api/v1/*` with `Origin: null` are rejected with `403 Forbidden`, preventing CORS simple-request CSRF from sandboxed iframes.
|
|
14
|
+
|
|
15
|
+
3. **Origin-scoped Content-Security-Policy (`src/server/routes/files.js`):**
|
|
16
|
+
- Responses for `/raw/*.html` and `/raw/*.htm` include a `Content-Security-Policy` header scoped to the request's origin (`x-forwarded-host` / `host` / `referer`), plus `'unsafe-inline' 'unsafe-eval' data: blob:`.
|
|
17
|
+
- This allows local sibling assets (`style.css`, `app.js`, `data.json`, images) while blocking outbound requests to external domains.
|
|
18
|
+
|
|
19
|
+
4. **Path Guards (`src/server/paths.js`, `src/server/routes/files.js`):**
|
|
20
|
+
- All file access passes through `resolveSafe()` (prevents `..` traversal outside `VAULT_ROOT`).
|
|
21
|
+
- `/raw/*` blocks protected segments (`.git`, `node_modules`, `dist`) and `.env*` files.
|
|
22
|
+
|
|
23
|
+
## Notes on LAN / Tailscale Hosting
|
|
24
|
+
|
|
25
|
+
`pagedex` has no built-in user authentication. Bind to `127.0.0.1` (default) for local-only use, or use `--host 0.0.0.0` only on trusted private networks / Tailscale.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Supported File Types
|
|
2
|
+
|
|
3
|
+
`pagedex` selects the viewer and search behavior by file extension and active view mode (`Preview`, `Edit`, `Diff`, `Raw`, plus `Download` in the top-right `⋮` menu).
|
|
4
|
+
|
|
5
|
+
| Type | Extensions | Preview Mode | Raw / Edit | Search Indexed |
|
|
6
|
+
|---|---|---|---|---|
|
|
7
|
+
| **Markdown** | `.md`, `.markdown`, `.mdx` | Rendered HTML, wikilinks, backlinks, outline | WYSIWYG (`TiptapEditor`), Raw, Diff | Yes (FTS5) |
|
|
8
|
+
| **HTML** | `.html`, `.htm` | Sandboxed `<iframe src="/raw/...">` | Syntax-highlighted XML/HTML | Yes |
|
|
9
|
+
| **PDF** | `.pdf` | Built-in browser PDF `<iframe>` + Download | — | No |
|
|
10
|
+
| **Audio** | `.mp3`, `.wav`, `.m4a`, `.ogg` | `<audio controls>` with HTTP `Range` seeking | — | No |
|
|
11
|
+
| **Video** | `.mp4`, `.webm`, `.mov` | `<video controls>` with HTTP `Range` seeking | — | No |
|
|
12
|
+
| **Tables** | `.csv`, `.tsv` | Styled HTML `<table>` | Raw text | Yes |
|
|
13
|
+
| **Images** | `.png`, `.jpg`, `.jpeg`, `.gif`, `.webp`, `.ico` | Inline `<img>` | — | No |
|
|
14
|
+
| **SVG** | `.svg` | Inline `<img>` | Raw XML toggle | No |
|
|
15
|
+
| **Text / Code** | `.txt`, `.js`, `.ts`, `.py`, `.json`, `.yaml`, etc. | Syntax-highlighted raw view | Raw / Diff | Yes (≤ 2 MB) |
|
|
16
|
+
| **Other Binaries** | `.epub`, `.zip`, `.docx`, `.sqlite`, `.db`, etc. | Download card | — | No |
|
|
17
|
+
|
|
18
|
+
## HTML + Sibling Files (`style.css`, `data.json`, `app.js`)
|
|
19
|
+
|
|
20
|
+
HTML files in Preview mode are loaded from `/raw/<path>` rather than `srcDoc`, so relative paths inside your HTML resolve naturally against the same folder:
|
|
21
|
+
|
|
22
|
+
```html
|
|
23
|
+
<link rel="stylesheet" href="style.css" />
|
|
24
|
+
<script src="app.js"></script>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
```js
|
|
28
|
+
fetch('data.json').then((r) => r.json())
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Audio & Video Seeking
|
|
32
|
+
|
|
33
|
+
`/api/v1/file` and `/raw/*` support HTTP `Range` (`206 Partial Content` / `Accept-Ranges: bytes`), allowing smooth scrubbing in `<audio>` and `<video>` players without buffering the entire file up front.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pagedex",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Local-first Markdown knowledge viewer, editor, Git bridge, and MCP v2 server for any directory.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"bin/",
|
|
19
19
|
"src/server/",
|
|
20
20
|
"dist/",
|
|
21
|
+
"docs/",
|
|
21
22
|
"README.md"
|
|
22
23
|
],
|
|
23
24
|
"scripts": {
|