This pillar documents every user-facing capability of vinary-viewer (vv): a reactive
ClojureScript / re-frame / Electron
desktop previewer for Markdown, Org-mode, and LaTeX documents, images, PDFs, diffs,
Office / table / log / archive files, source code, and in-app web links — opened
locally or over ssh:// / sftp://, in the desktop GUI or the terminal — with
live refresh as files are edited.
Each feature has its own page following a fixed template:
- What it is — the intuition.
- How to use it — concrete steps and an example.
- How it works internally — a literate walk of the exact code that implements it.
- Design notes / trade-offs — the relevant Architecture Decision Record (ADR).
- Forthcoming — for partially-built features, what is planned next.
- Diagram(s) — fully-colored PlantUML illustrations.
Status legend. Available now means the capability is implemented in the live ClojureScript app under
src/vinary/**andresources/**. «planned» (Forthcoming) means it is designed but not built yet.
| # | Feature | Status | What it does | How you use it | Internals |
|---|---|---|---|---|---|
| 01 | Live refresh | Available now | Re-renders the open document the instant the file changes on disk, preserving your scroll/UI position. | Just edit and save the file in any editor. | 01-live-refresh.md |
| 02 | Multi-tab previews | Available now | One tab per open document; a tab strip to switch and close. | Open files (CLI arg or file-tree click); click a tab to activate, × to close. |
02-multi-tab-previews.md |
| 03 | Watermark on empty tabs | Available now | A faint, theme-tinted Vinary Tree shield fills the content area when nothing is open. | Close all tabs (or launch with no file) to see it. | 03-watermark-empty-tabs.md |
| 04 | Git file-tree + filter | Available now | A sidebar showing the git repository of the open file as a collapsible tree, with a live text filter. | Open a file inside a git repo; click entries to open; type in the filter box to narrow. | 04-git-file-tree-and-filter.md |
| 05 | In-page find | Available now | Highlights all matches of a query within the rendered document and cycles between them. | Ctrl+F, type a query, Enter / Shift+Enter to cycle, Esc to close. |
05-in-page-find.md |
| 06 | Themes + live switching | Available now | Spacemacs-dark / -light palettes, swapped instantly at runtime. | Pick a theme from the toolbar <select>. |
06-themes-and-live-switching.md |
| 07 | Navigation history | Available now | A browser-style back/forward stack over the documents you visit. | Toolbar ← / → buttons, or Alt+← / Alt+→. |
07-navigation-history.md |
| 08 | Image view | Available now | Renders image files directly (no text read) by file:// URL. |
Open a .png / .jpg / .svg / … file. |
08-image-view.md |
| 09 | Markdown rendering | Available now | GitHub-flavored Markdown → HTML with heading slugs, syntax highlighting, MathJax SVG math, and inline Mermaid diagrams. | Open a .md / .markdown / .mdx file. |
09-markdown-rendering.md |
| 10 | Scroll-spy TOC | Available now | A right-hand table of contents that tracks which heading is at the top of the viewport. | Open a Markdown file with headings; scroll, or click a TOC entry. | 10-scroll-spy-toc.md |
| 11 | PDF preview (in-renderer) | Available now | PDFs render in the renderer DOM via pdf.js (canvas + text layer) with full parity: app keymap, smooth scroll, in-page find, themed Copy, text selection, zoom/fit, dark-invert, and bookmarks — now edge-to-edge, re-fitting on window resize, and stable across tab switches. | Open a .pdf file. |
11-native-pdf.md |
| 12 | Diagram source rendering | Available now for Mermaid | Mermaid fences and .mmd / .mermaid files render to SVG; other diagram sources remain source previews or embedded generated SVGs. |
Use a ```mermaid fence or open a .mmd / .mermaid file. |
12-diagram-rendering.md |
| 13 | Source preview (tree-sitter) | Available now | Read-only CodeMirror 6 + web-tree-sitter syntax highlighting when a grammar or filetype mapping is registered. | Open a source file in a bundled/user language, or map a filename/pattern in filetypes.edn. |
13-source-preview-tree-sitter.md |
| 14 | Grammar registry | Available now | Bundled and user-supplied tree-sitter grammars selected by extension, filename, or pattern. | Drop grammar.wasm + highlights.scm into ~/.config/vinary-viewer/grammars/<lang>/; use filetypes.edn for filenames and globs. |
14-grammar-registry.md |
| 15 | Custom keybindings | Available now | A command registry + vim/emacs keymaps + modal/chord resolver + user EDN config + command palette. | Choose a keymap or customize one from Settings > Key Bindings. |
15-custom-keybindings.md |
| 16 | In-pane directory browser | Available now | Opening a folder lists its children in the preview pane as a detailed list, with live refresh. | Open a directory: vv ~/docs, a folder in the file-tree, or a directory link; open an entry (single-click on Linux, double-click on Windows/macOS, or Enter / Alt+↓), Ctrl+click for a new tab. |
16-directory-browser.md |
| 17 | Breadcrumb + up/down navigation | Available now | A Ctrl-hover breadcrumb URI bar, Alt+↑ to the parent folder, Alt+↓ to open the highlight, and a persisted trail so Alt+↑ then Alt+↓ returns to the last-opened file. |
Hold Ctrl over the URI bar to get clickable path segments; use Alt+↑ / Alt+↓ to traverse folders. |
17-breadcrumb-and-up-down-navigation.md |
| 18 | Address-bar completion | Available now | Fish-style path auto-completion (inline ghost + ambiguous-only dropdown) for local files, and browser-history completion for web URLs. | Focus the URI bar (Ctrl+L); Tab completes the common prefix, → accepts the ghost, ↑/↓ pick, Enter opens. |
18-address-bar-completion.md |
| 19 | Web-view keyboard, Copy & cookies | Available now | The in-app web view has vim/standard scroll keys + f link hints, a right-click Copy menu, native selection, and a persistent session so logins survive restarts; local .html files open here as live pages, and any overlay freezes the page instantly (a pre-cached pushed snapshot) instead of blanking it. |
Open an http(s) link or a local .html; scroll with j/k/Space/arrows, f for hints, right-click to Copy. |
19-web-view-keyboard-and-copy.md |
| 20 | Ad & tracker blocking | Available now | Native EasyList/uBO blocking on the web session (no extension), auto-updated and toggleable, with inline Update filter lists feedback. | Settings ▸ Extensions ▸ Ad blocking. |
20-ad-blocking.md |
| 21 | Browser extensions | Available now | Install ad-blocker-class and lightweight Chrome extensions from the Web Store, with auto-update, a toolbar, and popups; an inert chrome.* polyfill keeps popup/options pages from crashing on APIs Electron lacks, while heavy MV3 password-manager workers remain a documented Electron gap. | Settings ▸ Extensions; paste a Web Store URL/ID and Install. |
21-browser-extensions.md |
| 22 | Zoom & Fit | Available now | One context-aware zoom: a bottom zoom bar (− / editable % / presets / +) plus a View ▸ Fit submenu, targeting the PDF scale, the web page, or the app window depending on the active tab. | Use the bottom zoom bar, Ctrl + / - / 0, or View ▸ Fit. |
22-zoom-and-fit.md |
| 23 | Native password-manager bridge | Available now | Fill and save web-view logins through main-process provider CLIs for 1Password, LastPass, optional Bitwarden/Proton Pass, and restricted JSON adapters. | Click the key icon on an http(s) tab, choose a matching login, or accept a save prompt after submitting a login form. |
23-password-manager-bridge.md |
| 24 | Dialogs & modals | Available now | A shared modal shell gives every dialog a defined border + theme-aware elevation, Esc / ✕ / backdrop close, autofocus, a focus trap, and true modality; the palette and menus share the same elevation tokens. Error-view text is selectable and copyable. | Open Settings ▸ Preferences / Extensions / Passwords, Help ▸ About / Command Palette; close with Esc, the ✕, or a backdrop click. |
24-dialogs-and-modals.md |
| 25 | Content previews (office · tables · logs · archives) | Available now | Office documents render as sanitized HTML, spreadsheets/CSV as a table with sheet tabs, logs with severity tinting, and archives as an in-pane listing — all parsed in main, bounded and paged for huge inputs. | Open a .docx / .xlsx / .csv / .log / .zip / .tar file. |
25-content-previews.md |
| 26 | Org-mode (.org) documents | Available now | Emacs Org files render GitHub-style through the common IR via uniorg — front matter, a Contents outline, nested #+begin_src highlighting, math, task lists, and a tree-sitter-org View Source. |
Open a .org file. |
26-org-mode.md |
| 27 | LaTeX (.tex) documents | Available now | LaTeX renders as a formatted document via unified-latex — sections, styling, tables, figures, MathJax math, and a macro preprocessor — with a Document↔PDF switch when a same-stem exported PDF sits beside it. Embedded LaTeX in Org invoices renders too. | Open a .tex file (try one with a sibling .pdf). |
27-latex-rendering.md |
| 28 | Diff / patch rendering | Available now | .diff / .patch files render as a colored unified diff (GUI HTML + terminal ANSI) and a GUI-only side-by-side split enriched with the on-disk pre/post files; standard repo filetypes (Makefile, .gitignore, …) classify correctly. |
Open a .diff / .patch file; toggle [Unified | Split]. |
28-diff-rendering.md |
| 29 | Remote files over SSH | Available now | Open remote files and directories over ssh:// / sftp:// through the same renderers, streaming, paging, and refresh as a local path — with ~/.ssh/config + agent/key/keyboard-interactive auth, known-hosts trust-on-first-use, and opt-in polling refresh. Secrets stay main-side. |
Type or pass ssh://user@host/path; authenticate at the prompt. |
29-remote-files-over-ssh.md |
| 30 | Terminal preview (CLI / TUI) | Available now | A second renderer over the shared IR: vv --cli renders once to stdout (pipe-friendly ANSI + kitty/sixel graphics), vv --tui is an interactive full-screen pager (in-page find, Contents outline, scrolling). |
vv --cli README.md | less -R, or vv --tui README.md. |
30-terminal-preview.md |
vinary-viewer is one reactive loop, not a bag of independent widgets. Most features are
derived views over a single source of truth — the
DataScript database that holds bounded
:doc content entities — plus interaction state in the re-frame app-db
(tabs, per-tab history, active tab, theme, find query, scroll-spy highlight).
This is why, for example, live refresh never disturbs your scroll
position or find state: content lives in DataScript; where-you-are lives
in app-db; a content update touches only the former.
┌─────────────────────────── Electron MAIN (Node) ───────────────────────────┐
file on disk ──▶ │ chokidar watcher (per retained path) ─▶ read + classify ─▶ vv:content / vv:tree │
└───────────────────────────────────┬──────────────────────────────────────────┘
│ IPC seam (preload contextBridge, JSON only)
┌────────────────────────────────────▼─────────────── Electron RENDERER (Chromium) ──┐
│ re-frame events ─▶ DataScript (:doc/*) ─▶ subscriptions ─▶ reagent UI │
│ │ ▲ │
│ │ markdown render fx (unified pipeline) ──┘ │
│ └─▶ app-db (tabs · per-tab history · theme · find · scroll-spy) │
└────────────────────────────────────────────────────────────────────────────────────┘
The shared mechanisms are documented once in the theory pillar and cross-referenced from the feature pages:
- The live-refresh spine — theory/03-live-refresh-spine.md (the reactive heart used by features 01, 02, 08, 09, 10, 11, 13, and 14).
- The
:ds/revreactivity bridge and state model — theory/02-state-model-datascript-app-db.md. - The Strategy renderer registry (content-view by
:doc/kind) — theory/05-strategy-renderer-registry.md. - The CSS Custom Highlight API find model — theory/06-find-css-custom-highlight.md.
- The Command-pattern navigation history — theory/07-command-history-model.md.
For the per-feature ADRs that record why each design was chosen, see ../design-decisions/README.md.
Every diagram is PlantUML, located under ../diagrams/, and reuses the shared
palette in ../diagrams/_vv-theme.iuml so a color always means the
same concept (slate = MAIN/Node-IO, teal = Renderer, amber = IPC seam, purple = DataScript,
blue-violet = ephemeral app-db, green = Markdown/unified, red = errors, dashed grey = «planned»).
Owned by this pillar:
object-watermark.puml— the watermark emblem pipeline.seq-toc.puml— scroll-spy TOC extract / spy / scroll.object-history-stack.puml— the history stack evolving.component-native-pdf.puml— the superseded main-owned PDFWebContentsView(historical; retired by ADR-0013 for the in-renderer pdf.js pipeline shown inseq-pdf-render.puml).component-diagram-rendering-planned.puml— «planned».component-source-preview.puml— read-only source preview.component-grammar-registry.puml— bundled/user grammar registry.component-keybindings-inprogress.puml— now available.seq-instant-overlay-snapshot.puml— instant, flash-free overlay compositing over the web view (features 19 + 22).component-password-bridge.puml— the password-manager secret flow, main-side only (feature 23).flow-org-pipeline.puml+activity-org-export-routing.puml— Org rendering + the math-vs-layout export routing (feature 26).flow-latex-pipeline.puml+state-doc-pdf-switch.puml— LaTeX rendering + the Document↔PDF / Preview↔Source switch (feature 27).component-diff-model.puml+seq-diff-split-enrich.puml— the diff model → unified + on-disk-enriched split (feature 28).component-remote-backend.puml,seq-ssh-open.puml,activity-ssh-auth.puml— the SSH virtual backend, open round-trip, and auth cascade (feature 29).component-terminal-renderer.puml+seq-cli-render.puml— the terminal second renderer + the one-shot CLI render (feature 30).