DEV Community

Mares Popa
Mares Popa

Posted on

I spent 3 years building a local-first, zero-server

I started HermesMarkdown back in 2023 as a personal tool — I just wanted a plain Markdown editor for my own notes, nothing more ambitious than that.

I'm a software engineer by trade, and this was very much a side project: something to write in during evenings, not a product.

It kept changing shape as my own habits changed. I rewrote the editor engine more than once, dropped features I'd added and regretted, and settled — slowly, not in one flash of insight — on a smaller idea than I started with: keep everything a plain file, keep the frontmatter predictable, and don't make the app the smart thing in the loop.

That's the version of HermesMarkdown that exists today, three years and a lot of rewrites later. I wanted to talk about a few of the architectural decisions and trade-offs behind it.

1. It runs in the browser but never touches a server

This was the part I was most stubborn about. The editor uses the native File System Access API (showDirectoryPicker()) to read and write a folder directly from Chromium-based browsers — no upload step, no account, and no third-party sync service in the middle.

You open a folder, you're editing the actual files on your disk, and closing the tab doesn't lose anything because nothing was ever "in" the app to begin with.

The trade-off: Firefox and Safari don't implement the File System Access API, so the vault picker is simply disabled there. I went back and forth on whether that was an acceptable cost for the architecture and decided it was — a tool that's local-first "most of the time" isn't really local-first.

2. Frontmatter as a strict contract, not a feature

The metadata schema is deliberately tiny:

---
title: "Dev.to Draft"
status: draft
tags: [architecture, webdev]
---
Enter fullscreen mode Exit fullscreen mode

That's it. No custom fields, no per-vault configuration. Every extra field is one more thing to fill in before you can start writing, and that's exactly the friction I was trying to remove.

The status key cycles through draft → review → active → archived and stays in sync with a lifecycle tag inline in the document, so you can update it either from the frontmatter panel or by clicking the tag directly in the text.

3. AI, only when you ask for it

There's no default model baked in, and no AI running ambiently in the background. AI is an opt-in chat interface connected strictly to your own API key (Anthropic or Google Gemini) — nothing more, nothing less.

A lot of modern tools default to the AI layer being always-on. For something that holds personal notes, I wanted the opposite: invisible until summoned. Without an API key configured, zero note content ever touches a network request.

4. Built to never need a mouse

The editor opens full-screen by default — no toolbar, no sidebar, and no clutter:

  • Slash commands: typing /table, /code, /math, or /link lets you insert elements quickly without touching a formatting bar
  • Global palette (CTRL+SHIFT+P): a fuzzy-searchable list of every app-level action
  • Keyboard-driven tables: sorting columns, inserting rows, and exporting as CSV all work purely through Tab, Shift+Tab, and arrow keys

5. Dictation with a safety buffer

Pressing CTRL+SHIFT+V triggers speech input. Speech lands in an editable preview first — not directly into the note file — so you can fix misheard words before committing them.

  • Say "insert this" (or hit Enter) to commit text at the cursor
  • Say "new paragraph" for line breaks, or "scratch that" to undo the last phrase
  • It's transcription-only, keeping the focus entirely on plain text without unexpected formatting glitches

6. Minimal on purpose

  • Dual views: switch seamlessly between rendered and source views — both editable, writing directly to the same file
  • Live inline rendering: Mermaid diagrams and LaTeX math render live inline, but round-trip cleanly as plain fenced code and $...$ syntax on disk
  • Vault task management: a centralized view aggregates every Markdown checkbox across your vault by status

None of this is groundbreaking on its own — keyboard-first editors and voice dictation both exist elsewhere. What I was chasing was the combination: a clean writing surface that gets out of the way, stays a plain file on disk, and only adds AI when you explicitly ask for it.

What's in your ideal Markdown setup?

If you spend time in Markdown vaults and care about staying keyboard-first, I'd love to hear your thoughts:

  • What shortcuts do you find missing in web-based editors?
  • How do you handle sync or local file conflicts in your own workflow?

Feel free to check out HermesMarkdown and let me know what you think!

Top comments (0)