Software Requirements Specification (SRS)
markdown-reader — Native Desktop Markdown Reader
Version: 1.0.0
Status: Draft
License: MIT
Repository: github.com/your-org/markdown-reader
npm: npx markdown-reader
Date: April 2026
Tagline: "The PDF reader experience, but for Markdown files."
Table of Contents
- Introduction
- Overall Description
- Functional Requirements
- Non-Functional Requirements
- System Architecture
- UI and UX Specification
- Release Roadmap
- Success Metrics
- Appendix
1. Introduction
1.1 Purpose
This document specifies the complete requirements for markdown-reader — a
native desktop application for reading Markdown files, built entirely on the
JavaScript/TypeScript ecosystem using Electrobun or Electron as the desktop
runtime.
markdown-reader is to Markdown what Adobe Acrobat Reader is to PDF:
a dedicated, native, first-class desktop viewer for .md files.
1.2 The Problem
Markdown is the most widely used plain-text writing format in the world.
Developers, writers, and teams produce millions of .md files daily.
Yet there is no dedicated desktop reader for Markdown that:
| Missing Capability |
Current Workaround |
Pain Level |
Opens .md files natively on double-click |
No default handler — opens as raw text |
High |
| Renders beautifully like a document |
VS Code preview pane feels like a dev tool |
Medium |
| Has a sidebar TOC like a PDF reader |
Manual heading scanning |
Medium |
| Supports all Markdown features |
GitHub renders some, browsers render none |
High |
| Works fully offline |
Must open a browser manually |
High |
| Feels like a reader, not an editor |
Every tool adds edit affordances |
Medium |
| Is small, fast, and native |
No such FOSS tool exists in JS ecosystem |
High |
VS Code is an editor. GitHub is a web interface. Obsidian is a note-taking vault.
None of them are just a reader — a clean, dedicated app for opening and
reading Markdown files.
1.3 The Solution
markdown-reader is a dedicated native desktop Markdown reader:
- Double-click any
.md file and it opens in markdown-reader
- Registered as the system default application for
.md files on install
- Beautiful readable typography — not a developer tool aesthetic
- Full Markdown support: code, diagrams, math, tables, task lists, callouts
- Auto-generated table of contents sidebar like a PDF reader
- File watching — live reload when the file is edited externally
- Multiple built-in themes
- Fully offline — zero cloud, zero telemetry, zero accounts
- Built entirely on the JS/TS ecosystem — no Rust, no Go, no C++
1.4 Runtime Strategy
markdown-reader is built on the JavaScript/TypeScript ecosystem only.
Primary runtime: Electrobun
- Pure TypeScript main process powered by Bun
- Uses the OS native webview — no bundled Chromium
- App bundle: approximately 12–68 MB
- Type-safe IPC via TypedRPC between main process and renderer
- macOS + Linux support (Windows in progress as of April 2026)
Secondary runtime: Electron
- Used for Windows builds and stable cross-platform v1.0 releases
- Identical frontend codebase — only the IPC adapter differs
- App bundle: approximately 120–180 MB
- Full Windows, macOS, and Linux support from day one
The renderer (React + TypeScript) is 100% shared across both runtimes.
Switching runtimes requires changing one adapter file only.
1.5 Intended Audience
- Developers reading project documentation, READMEs, and specs
- Writers and technical writers previewing drafts
- Students reading Markdown notes
- Anyone who works with
.md files regularly
1.6 Scope
Included:
- Opening and rendering
.md files
- Auto-generated table of contents sidebar
- Full Markdown feature rendering (GFM + extensions)
- File watching and live reload
- Multiple themes
- In-document and folder-wide search
- Export to HTML and PDF
- Folder and file browser panel
- Recent files history
- Keyboard-first navigation
- OS default
.md file handler registration
- Native menus, dialogs, and OS integration
Excluded:
- Editing Markdown content
- Cloud sync or storage
- Git integration
- Note-taking vault or knowledge base features
- Presentation mode (use
mdslide from this org for that)
- Collaboration or real-time sharing
1.7 Definitions
| Term |
Definition |
| Renderer |
The React + TypeScript frontend running in the native webview |
| Main process |
The Bun or Node.js backend managing filesystem and OS integration |
| IPC |
Inter-process communication between main process and renderer |
| Electrobun |
Desktop runtime: Bun main process + OS native webview |
| Electron |
Desktop runtime: Node.js main process + bundled Chromium |
| File watcher |
OS-level file change listener that triggers live reload |
| TOC |
Table of Contents — auto-generated from document headings |
| GFM |
GitHub Flavored Markdown — the dominant extended Markdown spec |
2. Overall Description
2.1 Product Vision
User double-clicks README.md
|
v
markdown-reader opens in under 800ms
|
v
+------------------+--------------------------------------+
| | |
| TOC Sidebar | Rendered Content Area |
| | |
| # Overview | # My Project |
| ## Install | |
| ## Usage | A fast tool for doing things. |
| ## API | |
| ## License | ## Installation |
| | |
| | ```bash |
| | npm install my-tool |
| | ``` |
| | |
+------------------+--------------------------------------+
| ~/README.md GitHub Light 100% dark |
+----------------------------------------------------------+
Clean. Fast. Dedicated. Like opening a PDF in Acrobat Reader.
2.2 Comparison With Alternatives
| App |
Dedicated Reader |
Offline |
Small Bundle |
Full MD Support |
FOSS |
JS Only |
| VS Code |
No (editor) |
Yes |
No — 200MB+ |
Partial |
Yes |
No |
| Obsidian |
No (vault) |
Yes |
No — 200MB+ |
Good |
No |
No |
| Typora |
No (editor) |
Yes |
Medium |
Good |
No |
No |
| GitHub web |
No (web) |
No |
N/A |
Good |
No |
No |
| markdown-reader |
Yes |
Yes |
Yes — 12–68MB |
Yes — Full |
Yes |
Yes |
2.3 User Personas
Persona A — The Developer
- Opens READMEs, changelogs, API docs, and specs daily
- Wants fast file open, great code rendering, and file watching for live reload
- May have multiple Markdown files open at once
- Success metric: any
.md file opens in under 800ms and reads comfortably
Persona B — The Writer
- Writes documentation and tutorials in Markdown
- Wants a beautiful reading experience to review finished work
- Cares about typography and readability
- Success metric: opens draft, sees clean rendering, exports to PDF easily
Persona C — The Student
- Uses Markdown for lecture notes and study material
- Wants TOC navigation, search, and dark mode
- Success metric: navigates a large notes file quickly using TOC and search
3. Functional Requirements
3.1 File Opening
FR-01: OS Default File Association
markdown-reader MUST register as the default application for .md and
.markdown files on install across macOS, Windows, and Linux.
Double-clicking any .md file in the OS file manager MUST open it in the app.
FR-02: File Open Dialog
The app MUST provide a File Open dialog (Cmd/Ctrl+O) filtered to .md files.
FR-03: Drag and Drop
The app MUST accept .md files dragged and dropped directly onto the window.
FR-04: Command Line Open
The app MUST support opening a file from the terminal:
markdown-reader README.md
markdown-reader ~/docs/notes.md
FR-05: Recent Files
The app MUST maintain a recent files list of the last 20 files accessed.
Accessible from:
- File menu → Recent Files submenu
- Welcome screen when no file is open
- OS Jump List (Windows) and Dock menu (macOS)
FR-06: Multiple File Tabs
The app MUST support opening multiple .md files as tabs in one window.
Tab requirements:
- Each tab shows the file name
- Modified/updated indicator when file changes externally
- Close tab: Cmd/Ctrl+W
- Drag tabs to reorder
- Reopen last closed tab
3.2 Markdown Rendering
FR-07: GitHub Flavored Markdown (GFM)
The renderer MUST fully support the GFM specification:
- Headings H1 through H6
- Bold, italic, strikethrough
- Unordered and ordered lists
- Nested lists up to 4 levels deep
- Task checkboxes — [ ] and [x]
- Inline code and fenced code blocks
- Blockquotes including nested
- Tables with column alignment
- Horizontal rules
- Images — local and remote
- Links — internal anchors and external URLs
- Inline HTML passthrough
- Footnotes
- Autolinks
- Definition lists
- Superscript and subscript
FR-08: Syntax Highlighted Code Blocks
Code blocks MUST render with syntax highlighting for 100+ languages using Shiki.
Requirements:
- Language-aware highlighting using the same tokenizer as VS Code
- Highlighting theme follows the active app theme (light or dark)
- Language label shown in the top-right corner of each block
- Copy-to-clipboard button visible on hover
- Line numbers toggleable in settings
- Long lines wrap or scroll horizontally without breaking layout
FR-09: Mermaid Diagrams
The renderer MUST support Mermaid diagram fenced blocks.
Supported diagram types:
- Flowchart
- Sequence diagram
- ER diagram
- Gantt chart
- Pie chart
- Class diagram
- State diagram
- Git graph
FR-10: Math Rendering
The renderer MUST support KaTeX math expressions.
- Inline math wrapped in single dollar signs
- Block math wrapped in double dollar signs
- Renders without network dependency
FR-11: Callout Blocks
The renderer MUST support GitHub and Obsidian style callout blocks:
> [!NOTE]
> [!WARNING]
> [!TIP]
> [!IMPORTANT]
> [!CAUTION]
Each type renders with a distinct icon, border color, and background color.
FR-12: Emoji Shortcodes
The renderer MUST convert emoji shortcodes to Unicode characters.
Examples: 🚀 renders as the rocket emoji, :check_mark: renders as the
checkmark emoji.
FR-13: Local and Remote Images
- Local images MUST render when the path is relative to the
.md file location
- Local images MUST render when the path is absolute
- Remote images MUST render when network is available
- A visible placeholder MUST appear when an image fails to load
FR-14: Link Behavior
- External URLs MUST open in the system default browser — never inside the app
- Internal anchor links MUST scroll smoothly to the target heading
- Relative
.md file links MUST open the target file as a new tab
3.3 Table of Contents Sidebar
FR-15: Auto-Generated TOC
The sidebar MUST display a table of contents auto-generated from H1, H2,
and H3 headings in the document.
TOC behavior:
- Indented to reflect heading hierarchy
- Active heading highlights as the user scrolls
- Clicking a TOC item smoothly scrolls to that section
- Items below H2 are collapsed by default and expandable
FR-16: TOC Panel Toggle
- Default state: visible
- Toggle shortcut: [ key or View menu → Table of Contents
- Panel is resizable by dragging the divider between TOC and content
3.4 File Browser Panel
FR-17: Folder View
The app MUST support opening a folder and displaying a file tree of .md files.
File tree behavior:
- Shows
.md and .markdown files by default
- Option to show all files in settings
- Folder structure is preserved in the tree
- Clicking a file opens it as a new tab
- The currently open file is highlighted in the tree
FR-18: Folder Open Methods
- File menu → Open Folder
- Drag a folder onto the window
- Command line:
markdown-reader ~/docs/
3.5 Live File Watching
FR-19: Auto Reload on External Change
When a currently open file is modified by an external process such as a text
editor, markdown-reader MUST automatically re-render it without losing
scroll position.
Requirements:
- Debounce reload 150ms after the last detected file change
- Preserve scroll position across reloads
- Show a subtle non-blocking toast notification: "File updated"
- No user action required
FR-20: Watch Indicator
A visible indicator in the status bar MUST show that file watching is active
for the current file.
3.6 Search
FR-21: In-Document Search
The app MUST support full-text search within the currently open document.
- Trigger: Cmd/Ctrl+F
- All matches are highlighted simultaneously
- Navigate between matches with Enter, Shift+Enter, or arrow buttons
- Match counter shown: "3 of 12"
- Case-insensitive by default with a case-sensitive toggle
- Dismiss with Escape
FR-22: Folder-Wide Search
When a folder is open, the app MUST support searching across all .md files
in the folder.
- Trigger: Cmd/Ctrl+Shift+F
- Results show file name and a text excerpt for each match
- Clicking a result opens the file and scrolls to the match
3.7 Themes
FR-23: Built-In Themes
The app MUST ship six built-in themes:
| Theme Name |
Background |
Character |
| GitHub Light |
White |
Clean and familiar |
| GitHub Dark |
Dark grey |
Dark mode GitHub style |
| Notion |
Warm white |
Soft and spacious |
| Nord |
Cool dark blue |
Developer-popular palette |
| Minimal |
Pure white |
Maximum reading focus |
| Dracula |
Deep purple |
Classic dark theme |
FR-24: Theme Switching
- Accessible via View menu → Theme submenu
- Keyboard shortcut: Cmd/Ctrl+T cycles through themes
- Option to auto-detect OS dark/light mode preference
FR-25: Custom CSS Injection
Users MUST be able to inject custom CSS via Settings → Custom Style to
override any visual aspect of the rendered content.
3.8 Export
FR-26: Export to HTML
The app MUST export the rendered document as a self-contained HTML file.
Requirements:
- All styles inlined
- Images embedded as base64
- Math, diagrams, and code highlighting preserved
- Matches the appearance of the currently active theme
- Accessible via File → Export → HTML
FR-27: Export to PDF
The app MUST export the rendered document to PDF using headless browser
rendering via Playwright.
Requirements:
- High-fidelity rendering of all content types
- Current theme applied
- Images, code blocks, diagrams, and math all preserved
- Accessible via File → Export → PDF
3.9 Reading Aids
FR-28: Reading Position Memory
When re-opening a previously viewed file, the app MUST restore the last
known scroll position automatically.
FR-29: Font Size Control
The user MUST be able to adjust the reading font size.
- Cmd/Ctrl+Plus — increase
- Cmd/Ctrl+Minus — decrease
- Cmd/Ctrl+0 — reset to default
- Supported range: 12px to 24px
FR-30: Reading Width Presets
The maximum content width MUST be configurable:
- Narrow: 640px — optimal for sustained reading
- Default: 768px
- Wide: 1024px
- Full width: no maximum
FR-31: Focus Mode
A distraction-free reading mode MUST hide all UI chrome except the content area.
Hidden in focus mode:
- Title bar (collapsed to minimal bar)
- TOC sidebar
- File browser panel
- Status bar
Trigger: Cmd/Ctrl+Shift+F or View menu → Focus Mode
3.10 OS Integration
FR-32: Native Menu Bar
The app MUST provide a native OS menu bar with the following structure:
File
Open File Cmd+O
Open Folder Cmd+Shift+O
Open Recent submenu
Close Tab Cmd+W
Export
Export as HTML
Export as PDF
Quit Cmd+Q
View
Table of Contents [
File Browser backslash
Focus Mode Cmd+Shift+F
Theme submenu
Zoom In Cmd++
Zoom Out Cmd+-
Reset Zoom Cmd+0
Navigate
Next Tab Ctrl+Tab
Previous Tab Ctrl+Shift+Tab
Search in Document Cmd+F
Search in Folder Cmd+Shift+F
FR-33: Native File Dialogs
All file open and save dialogs MUST use native OS-provided dialogs.
FR-34: macOS Spotlight Indexing
On macOS, opened files MUST be registered with the OS for Spotlight search.
FR-35: Drag and Drop onto Dock or Taskbar
On macOS and Windows, dragging a .md file onto the app icon in the Dock
or Taskbar MUST open that file.
3.11 Keyboard Navigation
FR-36: Full Keyboard Control
| Shortcut |
Action |
| Cmd/Ctrl+O |
Open file |
| Cmd/Ctrl+Shift+O |
Open folder |
| Cmd/Ctrl+W |
Close current tab |
| Cmd/Ctrl+T |
Cycle themes |
| Cmd/Ctrl+F |
Search in document |
| Cmd/Ctrl+Shift+F |
Search in folder / Focus mode |
| Cmd/Ctrl+Plus |
Zoom in |
| Cmd/Ctrl+Minus |
Zoom out |
| Cmd/Ctrl+0 |
Reset zoom |
| [ |
Toggle TOC sidebar |
| Backslash |
Toggle file browser |
| Ctrl+Tab |
Next tab |
| Ctrl+Shift+Tab |
Previous tab |
| Space |
Scroll down one screen |
| Shift+Space |
Scroll up one screen |
| Escape |
Dismiss search or overlay |
4. Non-Functional Requirements
4.1 Performance
| ID |
Requirement |
| NFR-01 |
Cold start MUST complete in under 800ms on mid-range hardware |
| NFR-02 |
File open and render MUST complete in under 300ms for files under 1MB |
| NFR-03 |
Live reload after file change MUST complete in under 300ms |
| NFR-04 |
Scrolling MUST maintain 60fps |
| NFR-05 |
Memory usage MUST stay under 150MB for a single open file |
| NFR-06 |
Memory usage MUST stay under 300MB with 10 tabs open simultaneously |
4.2 Bundle Size
| Build Target |
Maximum Size |
| Electrobun build (macOS/Linux) |
70MB |
| Electron build (all platforms) |
200MB |
| Installer download size |
80MB |
4.3 Platform Compatibility
| ID |
Requirement |
| NFR-07 |
MUST support macOS 12 and later on ARM and Intel |
| NFR-08 |
MUST support Windows 10 and Windows 11 |
| NFR-09 |
MUST support Ubuntu 22.04+ and Fedora 38+ |
| NFR-10 |
MUST handle .md files up to 50MB without crashing |
| NFR-11 |
MUST scroll smoothly on files with 10,000 or more lines |
4.4 Accessibility
| ID |
Requirement |
| NFR-12 |
All rendered content MUST meet WCAG 2.2 AA contrast in all themes |
| NFR-13 |
The app MUST be fully navigable using only the keyboard |
| NFR-14 |
Semantic heading structure MUST be preserved in rendered output |
4.5 Privacy
| ID |
Requirement |
| NFR-15 |
Zero telemetry — no analytics, crash reporting, or user tracking |
| NFR-16 |
Zero network calls during normal operation |
| NFR-17 |
All user data stored locally — no cloud sync |
| NFR-18 |
No account or login required |
4.6 Reliability
| ID |
Requirement |
| NFR-19 |
The app MUST NOT crash on malformed or invalid Markdown |
| NFR-20 |
The app MUST NOT crash on files with invalid UTF-8 sequences |
| NFR-21 |
The file watcher MUST recover gracefully if the watched file is deleted |
| NFR-22 |
The recent files list MUST persist correctly across app restarts |
5. System Architecture
5.1 Runtime Architecture
+--------------------------------------------------+
| Electrobun or Electron |
| |
| +----------------------------------------------+ |
| | Main Process (Bun or Node.js) | |
| | | |
| | file.ts File read and watch | |
| | ipc.ts IPC handlers | |
| | menu.ts Native OS menu bar | |
| | dialog.ts Native file dialogs | |
| | export.ts HTML and PDF export | |
| | recent.ts Recent files store | |
| | updater.ts Auto updater | |
| +---------------------+------------------------+ |
| | TypedRPC |
| +---------------------+------------------------+ |
| | Renderer (React + TypeScript) | |
| | | |
| | Reader.tsx Main content pane | |
| | Sidebar.tsx TOC panel | |
| | FileBrowser.tsx Folder file tree | |
| | Toolbar.tsx Top bar and tabs | |
| | Search.tsx Search overlay | |
| | Welcome.tsx Empty state screen | |
| | Settings.tsx Settings panel | |
| | | |
| | markdown.ts Marked + all plugins | |
| | shiki.ts Code syntax highlighting | |
| | mermaid.ts Diagram rendering | |
| | katex.ts Math rendering | |
| | toc.ts TOC extraction from AST | |
| | themes.ts CSS variable management | |
| +----------------------------------------------+ |
| OS Native Webview |
+----------------------------------------------------+
5.2 Tech Stack
| Layer |
Technology |
| Desktop runtime — primary |
Electrobun (Bun + OS native webview) |
| Desktop runtime — Windows/fallback |
Electron (Node.js + Chromium) |
| Main process language |
TypeScript running on Bun |
| Renderer framework |
React 19 + TypeScript |
| Build tool |
Vite |
| Markdown parser |
marked.js + GFM extensions |
| Code highlighting |
Shiki |
| Math rendering |
KaTeX |
| Diagram rendering |
Mermaid |
| File watching |
Bun.watch (Electrobun) / chokidar (Electron) |
| PDF export |
Playwright headless |
| UI components |
bare (this org's UI library) |
| Settings storage |
Plain JSON at app config directory |
5.3 File Structure
markdown-reader/
├── src-main/ Main process
│ ├── index.ts App entry point
│ ├── ipc.ts IPC handler registry
│ ├── file.ts File read and watch logic
│ ├── menu.ts Native OS menu definitions
│ ├── dialog.ts Native file dialog wrappers
│ ├── export.ts HTML and PDF export engine
│ ├── recent.ts Recent files persistence
│ └── updater.ts Auto updater logic
│
├── src-renderer/ Renderer (React)
│ ├── App.tsx
│ ├── components/
│ │ ├── Reader.tsx
│ │ ├── Sidebar.tsx
│ │ ├── FileBrowser.tsx
│ │ ├── Toolbar.tsx
│ │ ├── Search.tsx
│ │ ├── Welcome.tsx
│ │ └── Settings.tsx
│ ├── renderer/
│ │ ├── markdown.ts
│ │ ├── shiki.ts
│ │ ├── mermaid.ts
│ │ ├── katex.ts
│ │ └── toc.ts
│ ├── hooks/
│ │ ├── useFile.ts
│ │ ├── useTOC.ts
│ │ ├── useSearch.ts
│ │ ├── useTheme.ts
│ │ └── useWatcher.ts
│ └── themes/
│ ├── github-light.css
│ ├── github-dark.css
│ ├── notion.css
│ ├── nord.css
│ ├── minimal.css
│ └── dracula.css
│
├── src-shared/
│ └── types.ts Shared TypedRPC interface types
│
├── electron.vite.config.ts
└── package.json
5.4 TypedRPC IPC Bridge
The full typed API surface between main process and renderer:
export type MarkdownReaderAPI = {
readFile(path: string): Promise<string>
watchFile(path: string): Promise<void>
unwatchFile(path: string): Promise<void>
openFileDialog(): Promise<string | null>
openFolderDialog(): Promise<string | null>
readFolder(path: string): Promise<FileTree>
exportHTML(html: string, outputPath: string): Promise<void>
exportPDF(html: string, outputPath: string): Promise<void>
getRecentFiles(): Promise<RecentFile[]>
addRecentFile(path: string): Promise<void>
clearRecentFiles(): Promise<void>
getSettings(): Promise<AppSettings>
saveSettings(settings: AppSettings): Promise<void>
getAppVersion(): Promise<string>
}
6. UI and UX Specification
6.1 Window Layout
+----------------------------------------------------------+
| markdown-reader [README.md] [CHANGELOG.md x] _ [] X |
+------------------+---------------------------------------+
| | |
| TOC Sidebar | Content Area |
| (resizable) | (max-width: 768px, centered) |
| | |
| H1 Title | Rendered Markdown |
| H2 Section | Beautiful typography |
| H3 Sub | Code blocks with highlighting |
| H2 Section | Diagrams, math, images |
| | Tables, callouts, task lists |
| | |
+------------------+---------------------------------------+
| ~/docs/README.md GitHub Light 100% dark |
+----------------------------------------------------------+
6.2 Typography
| Element |
Font Stack |
Size |
Line Height |
| Body text |
Merriweather, Georgia, serif |
16px |
1.75 |
| H1 |
Inter, system-ui, sans-serif |
32px |
1.2 |
| H2 |
Inter, system-ui, sans-serif |
24px |
1.3 |
| H3 |
Inter, system-ui, sans-serif |
20px |
1.3 |
| Code |
JetBrains Mono, ui-monospace |
14px |
1.6 |
| UI chrome |
system-ui, sans-serif |
13px |
1.4 |
6.3 Welcome Screen
When no file is open:
markdown-reader
Open a Markdown file to start reading.
[ Open File ] [ Open Folder ]
Recent Files
README.md ~/projects/my-app/
notes.md ~/docs/
spec.md ~/work/
6.4 Status Bar Items (left to right)
[file icon] [full file path] [theme name] [zoom %] [dark/light toggle]
7. Release Roadmap
v0.1 — Core Reader (Week 1–2)
v0.2 — Reading Experience (Week 3)
v0.3 — Rich Content (Week 4)
v0.4 — OS Integration (Week 5)
v0.5 — Export and Polish (Week 6)
v1.0 — Public Launch (Week 7–8)
8. Success Metrics
| Metric |
Target |
Timeframe |
| GitHub Stars |
1,000 |
Month 1 |
| GitHub Stars |
5,000 |
Month 3 |
| Total downloads |
10,000 |
Month 3 |
| Cold start time |
Under 800ms |
v1.0 |
| Bundle size (Electrobun) |
Under 70MB |
v1.0 |
| GFM feature coverage |
100% |
v1.0 |
| Platforms shipped |
macOS + Windows + Linux |
v1.0 |
| Crash rate in production |
Under 0.1% |
v1.0 |
9. Appendix
9.A Supported Markdown Features
| Feature |
Supported |
| GitHub Flavored Markdown (GFM) |
Yes |
| Task lists |
Yes |
| Tables with alignment |
Yes |
| Strikethrough |
Yes |
| Fenced code blocks |
Yes |
| Syntax highlighting — 100+ languages |
Yes |
| Mermaid diagrams |
Yes |
| KaTeX math — inline and block |
Yes |
| Callout blocks (NOTE, WARNING, TIP, etc.) |
Yes |
| Emoji shortcodes |
Yes |
| Footnotes |
Yes |
| Definition lists |
Yes |
| Superscript and subscript |
Yes |
| Inline HTML passthrough |
Yes |
9.B Installation Methods
# macOS — Homebrew Cask
brew install --cask your-org/tap/markdown-reader
# All platforms — direct download
https://markdown-reader.app/download
# macOS — .dmg
# Windows — .exe installer
# Linux — .AppImage or .deb
# Command line open after install
markdown-reader README.md
9.C Why Electrobun + Electron (Not Just Electron)
Electrobun — primary build (macOS + Linux):
Pure TypeScript, no Rust or Go required
OS native webview — no bundled Chromium
Bundle approximately 12–68MB
Bun runtime — fast startup
Type-safe IPC via TypedRPC
Electron — secondary build (Windows + fallback):
Stable and mature, battle-tested in production
Full Windows support (Electrobun Windows still in progress)
100% shared frontend code
Auto updater ecosystem is mature
Strategy:
Electrobun build -> macOS + Linux (primary)
Electron build -> Windows (v1.0)
Frontend React code is 100% shared between both runtimes.
Switching runtimes = swapping one IPC adapter file.
9.D The One-Sentence Pitch
"PDF Reader — but for Markdown files."
End of SRS — markdown-reader v1.0.0
Generated: April 2026
License: MIT
Software Requirements Specification (SRS)
markdown-reader— Native Desktop Markdown ReaderVersion: 1.0.0
Status: Draft
License: MIT
Repository: github.com/your-org/markdown-reader
npm: npx markdown-reader
Date: April 2026
Tagline: "The PDF reader experience, but for Markdown files."
Table of Contents
1. Introduction
1.1 Purpose
This document specifies the complete requirements for
markdown-reader— anative desktop application for reading Markdown files, built entirely on the
JavaScript/TypeScript ecosystem using Electrobun or Electron as the desktop
runtime.
markdown-readeris to Markdown what Adobe Acrobat Reader is to PDF:a dedicated, native, first-class desktop viewer for
.mdfiles.1.2 The Problem
Markdown is the most widely used plain-text writing format in the world.
Developers, writers, and teams produce millions of
.mdfiles daily.Yet there is no dedicated desktop reader for Markdown that:
.mdfiles natively on double-clickVS Code is an editor. GitHub is a web interface. Obsidian is a note-taking vault.
None of them are just a reader — a clean, dedicated app for opening and
reading Markdown files.
1.3 The Solution
markdown-readeris a dedicated native desktop Markdown reader:.mdfile and it opens inmarkdown-reader.mdfiles on install1.4 Runtime Strategy
markdown-readeris built on the JavaScript/TypeScript ecosystem only.Primary runtime: Electrobun
Secondary runtime: Electron
The renderer (React + TypeScript) is 100% shared across both runtimes.
Switching runtimes requires changing one adapter file only.
1.5 Intended Audience
.mdfiles regularly1.6 Scope
Included:
.mdfiles.mdfile handler registrationExcluded:
mdslidefrom this org for that)1.7 Definitions
2. Overall Description
2.1 Product Vision
Clean. Fast. Dedicated. Like opening a PDF in Acrobat Reader.
2.2 Comparison With Alternatives
2.3 User Personas
Persona A — The Developer
.mdfile opens in under 800ms and reads comfortablyPersona B — The Writer
Persona C — The Student
3. Functional Requirements
3.1 File Opening
FR-01: OS Default File Association
markdown-readerMUST register as the default application for.mdand.markdownfiles on install across macOS, Windows, and Linux.Double-clicking any
.mdfile in the OS file manager MUST open it in the app.FR-02: File Open Dialog
The app MUST provide a File Open dialog (Cmd/Ctrl+O) filtered to
.mdfiles.FR-03: Drag and Drop
The app MUST accept
.mdfiles dragged and dropped directly onto the window.FR-04: Command Line Open
The app MUST support opening a file from the terminal:
markdown-reader README.md markdown-reader ~/docs/notes.mdFR-05: Recent Files
The app MUST maintain a recent files list of the last 20 files accessed.
Accessible from:
FR-06: Multiple File Tabs
The app MUST support opening multiple
.mdfiles as tabs in one window.Tab requirements:
3.2 Markdown Rendering
FR-07: GitHub Flavored Markdown (GFM)
The renderer MUST fully support the GFM specification:
FR-08: Syntax Highlighted Code Blocks
Code blocks MUST render with syntax highlighting for 100+ languages using Shiki.
Requirements:
FR-09: Mermaid Diagrams
The renderer MUST support Mermaid diagram fenced blocks.
Supported diagram types:
FR-10: Math Rendering
The renderer MUST support KaTeX math expressions.
FR-11: Callout Blocks
The renderer MUST support GitHub and Obsidian style callout blocks:
Each type renders with a distinct icon, border color, and background color.
FR-12: Emoji Shortcodes
The renderer MUST convert emoji shortcodes to Unicode characters.
Examples: 🚀 renders as the rocket emoji, :check_mark: renders as the
checkmark emoji.
FR-13: Local and Remote Images
.mdfile locationFR-14: Link Behavior
.mdfile links MUST open the target file as a new tab3.3 Table of Contents Sidebar
FR-15: Auto-Generated TOC
The sidebar MUST display a table of contents auto-generated from H1, H2,
and H3 headings in the document.
TOC behavior:
FR-16: TOC Panel Toggle
3.4 File Browser Panel
FR-17: Folder View
The app MUST support opening a folder and displaying a file tree of
.mdfiles.File tree behavior:
.mdand.markdownfiles by defaultFR-18: Folder Open Methods
markdown-reader ~/docs/3.5 Live File Watching
FR-19: Auto Reload on External Change
When a currently open file is modified by an external process such as a text
editor,
markdown-readerMUST automatically re-render it without losingscroll position.
Requirements:
FR-20: Watch Indicator
A visible indicator in the status bar MUST show that file watching is active
for the current file.
3.6 Search
FR-21: In-Document Search
The app MUST support full-text search within the currently open document.
FR-22: Folder-Wide Search
When a folder is open, the app MUST support searching across all
.mdfilesin the folder.
3.7 Themes
FR-23: Built-In Themes
The app MUST ship six built-in themes:
FR-24: Theme Switching
FR-25: Custom CSS Injection
Users MUST be able to inject custom CSS via Settings → Custom Style to
override any visual aspect of the rendered content.
3.8 Export
FR-26: Export to HTML
The app MUST export the rendered document as a self-contained HTML file.
Requirements:
FR-27: Export to PDF
The app MUST export the rendered document to PDF using headless browser
rendering via Playwright.
Requirements:
3.9 Reading Aids
FR-28: Reading Position Memory
When re-opening a previously viewed file, the app MUST restore the last
known scroll position automatically.
FR-29: Font Size Control
The user MUST be able to adjust the reading font size.
FR-30: Reading Width Presets
The maximum content width MUST be configurable:
FR-31: Focus Mode
A distraction-free reading mode MUST hide all UI chrome except the content area.
Hidden in focus mode:
Trigger: Cmd/Ctrl+Shift+F or View menu → Focus Mode
3.10 OS Integration
FR-32: Native Menu Bar
The app MUST provide a native OS menu bar with the following structure:
FR-33: Native File Dialogs
All file open and save dialogs MUST use native OS-provided dialogs.
FR-34: macOS Spotlight Indexing
On macOS, opened files MUST be registered with the OS for Spotlight search.
FR-35: Drag and Drop onto Dock or Taskbar
On macOS and Windows, dragging a
.mdfile onto the app icon in the Dockor Taskbar MUST open that file.
3.11 Keyboard Navigation
FR-36: Full Keyboard Control
4. Non-Functional Requirements
4.1 Performance
4.2 Bundle Size
4.3 Platform Compatibility
.mdfiles up to 50MB without crashing4.4 Accessibility
4.5 Privacy
4.6 Reliability
5. System Architecture
5.1 Runtime Architecture
5.2 Tech Stack
5.3 File Structure
5.4 TypedRPC IPC Bridge
The full typed API surface between main process and renderer:
6. UI and UX Specification
6.1 Window Layout
6.2 Typography
6.3 Welcome Screen
When no file is open:
6.4 Status Bar Items (left to right)
7. Release Roadmap
v0.1 — Core Reader (Week 1–2)
.mdfilev0.2 — Reading Experience (Week 3)
v0.3 — Rich Content (Week 4)
v0.4 — OS Integration (Week 5)
.mdhandlermarkdown-reader file.mdv0.5 — Export and Polish (Week 6)
v1.0 — Public Launch (Week 7–8)
.md→ opens in under 800ms8. Success Metrics
9. Appendix
9.A Supported Markdown Features
9.B Installation Methods
9.C Why Electrobun + Electron (Not Just Electron)
9.D The One-Sentence Pitch
"PDF Reader — but for Markdown files."
End of SRS — markdown-reader v1.0.0
Generated: April 2026
License: MIT