A minimal Electron + TypeScript desktop app for previewing Markdown files.
- Open files via native dialog or by passing a path as a CLI argument
- Live-reload — watches the open file and re-renders automatically on save
- GitHub-flavored rendering (GFM styling via
github-markdown-css) - Syntax highlighting for fenced code blocks with a declared language (
highlight.js) - Relative image paths in the Markdown source resolve correctly against the open file's directory
- External links open in your system's default browser, not inside the app
- Drag-and-drop a
.mdfile from the OS onto the window to open it — same validation as File → Open, and only the first file is opened if several are dropped - Dark Mode and Show Frontmatter toggles in the View menu control preview appearance and frontmatter visibility
- Persisted settings — View-menu toggles (Dark Mode, Show Frontmatter, Show File Tree) are saved to a
settings.jsonin the app's per-user data directory and restored on the next launch. File → Settings opens (creating it first if needed) that file in your OS's default text editor for direct inspection/editing - In-app Help window with usage documentation, available via Help → md-view Help or the F1 key
- Folder sidebar — File → Open Folder… (
Ctrl/Cmd+Shift+O) opens a folder in a sidebar tree. Clicking a folder lazily expands it; clicking a file opens it in the main pane. The tree auto-expands to and highlights whichever file is currently open. A.. (up one level)row navigates to the parent folder. Drag the divider between the tree and the document to resize the sidebar. View → Show File Tree toggles the sidebar on or off. Dropping a folder onto the window also opens it as the tree root, the same as Open Folder… - Preview and Code tabs — View → Preview and View → Code switch the main pane between the rendered Markdown and a raw-source view with syntax highlighting. The raw view always includes frontmatter, regardless of the Show Frontmatter toggle, which only affects the rendered Preview
- Copy raw source — a copy button in the document header copies the file's raw source, frontmatter included, to the clipboard regardless of which tab is active, with a brief visual confirmation on click
- What's New on update — the first time you launch md-view after an update, a small window shows that version's release notes. Shown once per version, then not again until the next update
- Close — File → Close (
Ctrl/Cmd+W) closes the open file and returns to the "No file open" view. The folder tree stays open. The item is disabled when no file is open - Mermaid diagrams — fenced code blocks tagged
mermaidrender as diagrams in the Preview and follow Dark Mode. An invalid or oversized diagram shows a notice and its source without affecting the rest of the document. Theme and security settings inside a diagram are ignored. The Code tab and the copy button still show the raw Markdown - About window and third-party notices — Help → About md-view shows the app version, the Electron/Chromium/Node.js versions, copyright, license, a repository link, and the license notices of the open-source packages bundled into md-view (Electron's and Chromium's own license files ship alongside the app)
- Copy text — select text in the Preview or Code view and copy it with
Ctrl/Cmd+Cor the right-click Copy menu item; right-click Copy All copies the whole visible view (the rendered document in Preview, including frontmatter when it's shown, or the raw Markdown source in Code). A Mermaid diagram always copies its Markdown source, never its rendered drawing, whether you right-click it directly, select across it, or include it in Copy All. There's no new top-level menu item for this — Copy and Copy All are context-menu and keyboard actions only - Skins — View → Skin picks the color scheme of the app chrome (title bar, tab strip, folder sidebar, status bar) and the code-highlighting colors. Four skins ship — Default, Claude, Obsidian, and Tokyo Night — each with independent light and dark halves; Dark Mode decides which half shows without ever changing which skin is active. View → Skin → Edit Skins… opens
skins.jsonfor hand-editing custom skins
- Electron — desktop shell (main/preload/renderer process model)
- TypeScript — compiles
src/mainandsrc/preloadto CommonJS (dist/); the renderer is plain JS, no build step - markdown-it — Markdown → HTML conversion, with raw HTML passthrough explicitly disabled
- highlight.js — syntax highlighting for fenced code blocks with an explicit, recognized language (no auto-detection). Eight of its theme stylesheets ship in
dist/renderer/— the default light/dark pair plus six more backing the Skins feature's code-highlighting halves - chokidar — file watching for live-reload
- Mermaid (11.17.2, pinned) — diagram rendering in the Preview. Shipped as a build-time asset:
npm run buildcopiesmermaid.min.jsintodist/renderer/, and the renderer loads it only when a document contains a diagram - zod — schema validation for the hand-editable
settings.jsonfile - esbuild — bundles the preload script into a single file (required to run under Electron's sandboxed preload context)
- Vitest — unit and integration tests
- Playwright (
@playwright/test,_electron) — end-to-end tests against the built, packaged app - electron-builder — packages the compiled
dist/output into distributable binaries
contextIsolation: true,nodeIntegration: false,sandbox: trueon the main window- The preload script exposes only an explicit, versioned bridge object (
window.mdview) viacontextBridge.exposeInMainWorld— never raw IPC or Node APIs - Markdown is converted with
html: false— raw HTML embedded in a source file is never rendered as live markup - Links clicked inside rendered content are intercepted and opened externally via
shell.openExternal; the app window itself never navigates away from its own content - The main window enforces a Content Security Policy (
src/renderer/index.html): scripts load only from the app itself (no inline oreval'd scripts) andconnect-src 'none'blocks script-initiated network requests (fetch/XHR/WebSocket). Remote images in a document still load. Mermaid runs with a locked configuration (securityLevel: 'strict', with theme and security keys that a diagram cannot override) - The Help, What's New, and About windows render under a no-script Content Security Policy: no
script-srcat all, and only the one embedded stylesheet, pinned by its SHA-256 hash
# Open a specific file directly
npm run dev -- path/to/file.md
# Or launch the app and use File → Open
npm run devFile → Open Folder… (Ctrl/Cmd+Shift+O) is a second way to start: it opens a folder tree in the sidebar instead of a single file.
| Command | Description |
|---|---|
npm run dev |
Build, then launch the app with electron . |
npm run build |
Compile TypeScript, bundle the preload script, and copy static renderer assets into dist/ |
npm test |
Alias for test:all |
npm run test:unit |
Run unit tests (tests/unit) |
npm run test:integration |
Run integration tests (tests/integration) |
npm run test:e2e |
Build, then run the Playwright end-to-end tests against the built app |
npm run test:all |
Run unit, integration, and e2e tests in sequence |
npm run test:coverage |
Generate a code coverage report for the unit test suite (tests/unit). Informational only — no enforced threshold |
npm run package |
Package the built app with electron-builder |
Status: v1.3.0. md-view is a small, working tool — and also a live testbed.
This app was built end-to-end under a governed, multi-agent development process: every feature went through explicit scope contracts, independent code review (including deliberate fault-injection to verify tests actually catch what they claim to), and a running decision log. The governance system itself lives in a separate, public repo — chamix/claude-blueprints — and is deployed into target repos like this one.
If you're curious about the process rather than just the app:
RUN_LOG.md— one row per completed task: cycles to green, reviewer verdict, notesbacklog.md— known follow-ups, tracked openly rather than fixed silently.agents/specs/decisions/— architecture decision records for the non-obvious callsCHANGELOG.md— release history: what changed in each version
This is part of a broader learning project comparing agentic development workflows — this app is the first thing built under the current system, used partly to stress-test the governance itself.
MIT — see LICENSE.
The license notices of the open-source packages bundled into md-view ship with the app: npm run build generates them into dist/, and they are shown in-app under Help → About md-view.