Search
How full-text search works in WitWiki — from the Wiki list page in the web UI through the REST API to PostgreSQL.
What you search
Search matches page title and markdown body (everything stored in wiki_pages). It does not match path segments alone (e.g. searching only product may miss pages whose title and body never contain that word). Paths still appear in results for navigation.
Web UI (/wiki)
The wiki index uses a search field above the page list. Your input is debounced (about 300 ms) so each keystroke does not hit the network.
| Input | HTTP call | Result |
|---|---|---|
| Empty | GET /api/pages?limit=100 | Recently updated pages, newest first |
| Non-empty | GET /api/search?q=…&limit=100 | Full-text hits, ranked |
The browser sends the same Authorization: Bearer token as the rest of the app (NEXT_PUBLIC_WITWIKI_API_KEY in local dev).
REST API
- List / browse:
GET /api/pages?limit=…— optionalprefix=filters by path prefix; no full-text query. - Search:
GET /api/search?q=…&limit=…—qis required; emptyqreturns 400.
Responses are JSON: { "pages": [ { "path", "title", "updated_at" }, … ] }.
Default limit is 100; the server caps at 500.
Database (PostgreSQL)
Each row in wiki_pages has a generated tsvector column (fts) built from English text of title + content. Search uses:
websearch_to_tsquery('english', $1)— web-style query syntax (phrases, etc., per PostgreSQL).fts @@ …— match predicate.ts_rank_cd(fts, …)— relevance ordering, thenupdated_at DESCas a tie-break.
So this is full-text search, not a simple SQL LIKE on path.
MCP (agents)
Agents use wiki_listPages with optional q for the same full-text behavior as /api/search. Optional prefix narrows by path prefix; limit follows the same cap.
Related
- architecture — where HTTP and MCP attach to the same wiki service
- development — env vars and local URLs
- mcp-tools — tool reference
← index