Editor Quality-of-Life — Design
Status: implemented on main 2026-09-30 (not yet released). Canonical spec: docs/superpowers/specs/2026-09-30-editor-quality-of-life-design.md; plan: docs/superpowers/plans/2026-09-30-editor-quality-of-life.md. Part of the Wikantik Platform Development Hub. Grew out of a review of the editing experience against Obsidian; every item is a general improvement for any wiki user, independent of Obsidian compatibility. Companion to the Obsidian export design.
Problem
The editor is a CodeMirror 6 source editor with a side-by-side preview, but the most frequent authoring actions carry avoidable friction:
- Images cannot be pasted, and dropping a file from the desktop does nothing even though the editor shows a drop hint.
- Link completion works from a one-time snapshot capped at 1000 pages, so on a larger corpus the end of the alphabet is never offered. There is no completion for link targets or heading anchors.
- The preview and the saved page use different renderers. Broken links, plugins and citation links are invisible until after save, and code is never highlighted.
- History and diff are read-only; an old version cannot be brought back.
- Outline, backlinks and word count are only on the read view.
Decisions
- Paste and drop: clipboard images and dropped files upload through the existing attachment API with an in-text placeholder, then become the same markup an attachment drag produces. Pasted images are named by timestamp; dropped files keep a normalised name, with numeric suffixes on collision. Text edits go through the editor itself, so typing during an upload cannot lose the link. An unsaved page offers "Save and upload", because attachments need an existing page.
- Upload policy: the configured attachment size and extension limits, previously honoured only by the legacy upload servlet, move into one shared policy used by both upload entry points (413 for size, 415 for type). Admins stay exempt, as before. Connector and ingest syncs are not subject to it. Defaults stay blank.
- Link completion: live, ACL-filtered, ranked substring search on page names replaces the snapshot; typed spaces are ignored, so a title finds its CamelCase page. Completion triggers on
[[, inside a link target, and on # for heading anchors. A "Link to new page" item inserts a link to a page that does not exist yet without creating it. - Heading anchors: the ids the page view assigns are canonical. Completion reuses that slug code, and the export's slug function is brought into line with it; one shared case table is tested on both sides.
- Preview signals (browser-side, not a server render): broken links styled like the page view's create-links via a batched, ACL-filtered existence check; plugins and directives shown as labelled chips; citations shown with a target badge; code highlighted in the editor, the preview and the page view from one shared module, with language grammars loaded on demand. The preview stays instant and scroll sync is untouched.
- Restore: a Restore action in history and diff opens the editor on a copy of the old version (body and frontmatter) with a pre-filled change note. Saving goes through the normal path, so version checks and validators apply and an old version can be fixed before it is saved. No new endpoint.
- Side rail: a collapsible right-hand column in the editor with a live outline of the draft (click to jump) and the page's backlinks, plus a status bar with word count, reading time, cursor position and selection count.
- Cleanup: the unused page-locking service and its background thread are removed.
API changes
GET /api/pages gains q= (ranked substring search) and names= (existence check for up to 50 names, returning only pages the caller can view). Attachment uploads can now return 413 or 415 under a configured policy. No new servlets and no new configuration keys; the unused wikantik.lockExpiryTime is removed.
Out of scope
Rename rewrites that skip save validation and search reindexing (separate follow-up), inline live preview, templates, command palette, Mermaid, checking that a linked heading still exists, and three-way merge on conflict.