I am an engineer by training, but not a software engineer. I have no coding background. Over the past months I have been building and shipping small commercial tools entirely with AI assistance, and the latest one is an Obsidian plugin. I want to write up the decisions that went into it, because a few of them go against how most paid AI plugins are built.
The problem I was solving for
I kept seeing the same complaint across reading and PKM communities: people sync hundreds of highlights from Readwise, Snipd, or Kindle into their vault, and then never open the folder again. The highlights pile up into a graveyard. The effort of saving them is spent, but nothing comes back out.
I am not a heavy highlighter myself. I found this pain through research, not from my own giant pile of notes. That distinction matters to me, so I am stating it plainly rather than inventing a personal origin story.
The plugin reads the whole folder and writes one synthesis note: a summary, the key claims, and a topic list per source, then the themes that recur across more than one source, with where sources agree and where they pull apart.
Decision 1: no server, at all
Most paid AI Obsidian plugins I looked at validate a subscription against a backend. A typical one runs a Cloudflare Worker, checks your license against the cloud, and bills monthly. That is a reasonable business model, but it means a server I have to run, a database, a recurring cost, and a place where user data could flow.
I went the other way: zero server, zero database, zero recurring cost. The plugin runs entirely on the user's device. There is nothing for me to operate and nothing to leak on my side.
Decision 2: bring your own key (BYOK)
The plugin uses the user's own API key for whichever provider they pick (Anthropic, OpenAI, OpenRouter, or any OpenAI-compatible endpoint). I never see their key and I never proxy their requests.
One honesty point I want to be clear about, because it is easy to oversell: BYOK does not mean the data stays on the device. To synthesize highlights, the plugin sends the highlight text to whatever model provider the user configured. So the accurate privacy claim is "no server, no account, no backend data collection on my side", not "your notes never leave your machine". I refuse to make the second claim because it is not true for any BYOK tool that calls a hosted model.
Decision 3: offline license verification with Ed25519
If there is no server, how do you sell a Pro license? I used offline signature verification. Each plugin has its own Ed25519 keypair. The private key lives only in my password manager. The public key is embedded in the plugin. A license key is a small signed payload: product id, email, issue date, plus a detached signature.
Verification is fully offline using tweetnacl:
import nacl from "tweetnacl";
// publicKey embedded in the plugin, payloadBytes + signature decoded from the license key
const ok = nacl.sign.detached.verify(payloadBytes, signature, publicKey);
If it verifies and the product id matches, Pro is active. No network call, no phone-home, works on a plane. A note for anyone trying this: @noble/ed25519 did not work in Obsidian's Electron environment for me, tweetnacl did.
The free tier is a lifetime cap, not a monthly reset
The free tier allows 3 syncs total, for the lifetime of the install, not 3 per month. A monthly reset lets people wait out the counter and never convert. A lifetime cap creates a real decision point. Generating the report from already-synced highlights stays free forever.
On building this without being a software engineer
The whole thing is TypeScript, and I wrote essentially none of it by hand. Claude wrote the code, I made the product and architecture decisions, tested every step in Obsidian, and pushed back when something was wrong. The parsing is deliberately defensive because highlight exports vary wildly between people's templates: callout blocks, heading-plus-bullet, block ids, or plain text all have to be read, with a whole-body fallback when no markers are found.
It is in the Obsidian community plugin directory now. If you have a highlight backlog like this, I would genuinely like to hear how you currently deal with it, by hand, with a Dataview query, or not at all.
GitHub: https://github.com/ibrh96-prog/obsidian-highlights-synthesizer
Obsidian directory: https://community.obsidian.md/plugins/highlight-inbox-synthesizer
Top comments (0)