A Markdown editor for macOS that works like Typora and looks like its Newsprint theme: you write and read in one view, and Markdown syntax disappears once you finish typing it.
- One writing surface. Headings, emphasis, links, lists, quotes, and code render in place. The Markdown markers reappear only while the cursor is inside them. ⌘/ switches to plain source.
- Your file stays your file. The text on disk is the document. Opening and saving without edits leaves every byte the same, including CRLF line endings and a UTF-8 BOM, and saves are atomic.
- Four interface languages. OpenViewer’s menus, editor controls, and Settings are available in English, 繁體中文, 简体中文, and 日本語. Choose a language in Settings → General, or follow the macOS preferred language order with System.
- Tables you can edit in place. Click a cell and type, Tab to move, and use the toolbar to add or remove rows and columns. Each edit changes only the lines it touches; Tidy lines up the columns.
- Images. Paste or drag an image in and it is copied into
./assetsnext to the document and linked with a relative path (Settings → Images offers a folder per document instead). Images from the internet stay off until you turn them on. - Any text encoding. UTF-8, UTF-16, and legacy encodings such as Big5, GBK, or Shift_JIS open and save in their own encoding; the status bar names any encoding that isn't UTF-8.
- Export to PDF (⇧⌘E) or a single self-contained HTML file, in the same Newsprint look, with local images and fonts embedded.
- Code blocks in a dark card with syntax highlighting and a language picker.
- Math.
$…$inline and$$blocks render with KaTeX as you leave them, and show their TeX again when the cursor goes back in. Prices like$5 and $10stay text. Export keeps the formulas, with KaTeX's fonts embedded. - Mermaid diagrams. A
```mermaidblock is drawn as a picture (flowcharts, sequence, class, state, ER, Gantt, and pie charts) and shows its code when you click it. Diagrams are drawn in a sealed-off frame with no network access and shown as images; Settings → Images can turn them off. - Outline sidebar (⇧⌘L), focus mode (F8), typewriter mode (F9), and a word count that counts Chinese, Japanese, and Korean characters as words.
- Custom shortcuts. Settings (⌘,) lets you record a new shortcut for any menu or formatting
command. They are saved to
keybindings.json, which you can also edit by hand. - Small and native: about 14 MB, one document per window, native menus and dialogs, and "Open With" from Finder.
You need macOS, Node.js 24 (see .node-version), and a stable
Rust toolchain.
npm install
npm run app:dev # run the app with live reload
npm run app:build # build src-tauri/target/release/bundle/macos/OpenViewer.appThe build is not signed with a Developer ID or notarized yet, so macOS blocks the first launch of a
downloaded copy. Open it once, then go to System Settings → Privacy & Security and click Open Anyway
next to the message about OpenViewer. (Or, in Terminal: xattr -dr com.apple.quarantine /path/to/OpenViewer.app.)
npx playwright install webkit # once
npm test # typecheck, Rust tests, browser suites, CSP check
npm run test:all # the same, plus WebKit (the engine the app uses)The browser suites run the editor in a plain browser against npm run dev.
OpenViewer updates itself with Tauri's updater: it checks a signed feed on GitHub, and installs only updates signed with the project's key.
- Once: create the updater key pair and keep the private key out of the repository:
npx tauri signer generate -w ~/.tauri/openviewer.key. Paste the contents of~/.tauri/openviewer.key.pub(one base64 line) intosrc-tauri/tauri.release.conf.json. The public GitHub repositorysayre4ux/openviewermust exist before the first release is published. - Set the version:
npm run release -- --version 0.1.0-beta.1updatespackage.json,Cargo.toml, andtauri.conf.json. Write the notes inrelease-notes/<version>.md, then review and commit both (the release refuses to build from a tree with changes). Push before publishing: the release tag is made at the commit that was built. - Build: with
TAURI_SIGNING_PRIVATE_KEY(andTAURI_SIGNING_PRIVATE_KEY_PASSWORDif the key has one) set,npm run releasebuilds the app, the signed update archive, the download zip (made withditto, so the signature survives), andlatest.jsonintorelease/<version>/, and checks the update's signature against the public key the app ships with. It only prints the publishing commands.--universalbuilds for Apple silicon and Intel. - Sign and notarize (when available): set
APPLE_SIGNING_IDENTITYfor Developer ID signing, andAPPLE_ID,APPLE_PASSWORD(an app-specific password), andAPPLE_TEAM_IDto notarize. Without them the build is signed ad hoc, and testers use Open Anyway on first launch. - Publish:
npm run release -- --universal --publishcreates the GitHub release (a pre-release for versions like0.1.0-beta.1) and replaceslatest.jsonon the release taggedupdates, which is where the app looks. A fixed tag is used because GitHub's "latest release" link skips pre-releases, so testers on a beta would never see the next one. Don't delete theupdatesrelease. Publishing needs--universal: the onelatest.jsonserves both kinds of Mac.
OpenViewer treats every Markdown file as untrusted. The app can read and write only files you chose (Open, Save As, drag and drop, or Open With), local images load only from the document's folder or git repository (other folders only after you allow them), images from your local network are blocked, and a strict Content-Security-Policy applies. Images from the internet don't load unless you turn them on in Settings → Images, because loading one tells its server that you opened the document. Formulas can't make links or load images, and Mermaid diagrams are drawn in a sandboxed frame with no network access and shown only as images. A diagram that freezes the app is shown as code the next time, with a button to try again.
OpenViewer is a Tauri 2 app. The editor is CodeMirror 6 with a live-preview layer that only adds decorations over the Markdown text, so nothing is re-serialized when you save. Notes for contributors and coding agents are in AGENTS.md.
Before the first release:
- Signing with a Developer ID and notarization
- Continuous integration
After the first release:
- Dark mode
- A file tree sidebar
- A choice of spellcheck language
- Windows support
MIT.
- The look follows Typora's Newsprint theme. The CSS here is written from scratch.
- PT Serif by ParaType, bundled under the SIL Open Font License.
- Built with Tauri, CodeMirror, Lezer, KaTeX (whose fonts are bundled), and Mermaid.
