Charlie KrugThe Build Log

← All posts

The keys to your life, on a page with nowhere to send them

A digital estate checklist that runs entirely in your browser and can't phone home, because there's no backend to phone. Fill it in, export a PDF, and verify the privacy claim yourself in the Network tab.

If something happens to you, the people you leave behind need answers to some very unglamorous questions fast. Where do you bank. What subscriptions renew on autopilot and quietly drain the estate for months. Who has power of attorney, where the will actually is, what happens to the dog. The document that answers all of that is, by definition, the single most sensitive thing you will ever write: it concentrates the keys to your entire life in one place. So of course the tools built to hold it want you to upload it to their servers.

Keyholder takes the opposite bet. It is a static page. You fill in a form, a clean printable "if something happens to me" document builds itself live in the pane beside you, and when you are done you export it as a PDF and close the tab. No account, no database, no company that might be acquired or breached or gone in ten years. The only place your information ever exists is the file you saved.

The privacy claim is architecture, not a promise

Most privacy tools ask you to trust a policy: we won't look, we encrypt at rest, we're SOC 2. Keyholder doesn't have a policy to trust, because it has nowhere to send anything. The form, the live preview, and the PDF exporter are all pure functions over in-memory state: schema plus your typed values in, text out. There is no fetch in the code path, and no backend for one to call even if there were. This is deliberate down to the architecture. Adding a server later would not be a feature flag, it would be a rewrite, which is exactly what keeps the promise credible instead of "true for now."

The part I'm most pleased with is that the zero-network claim covers the whole page, not just your data. jsPDF, the library that generates the PDF, is vendored into the repo at build time instead of loaded from a CDN <script> tag. A CDN link would mean one network request every time the page loads, and "nothing leaves your browser except a ping to some other company's edge server" is a weaker sentence than the one I wanted to be able to write. So the library ships in the repo, the fonts are self-hosted, and the page loads its own files once and then never touches the network again. jsPDF.save() writes straight to a browser download, not an upload.

You don't have to take my word for any of this. Open devtools, go to the Network tab, hit "Disable cache," and fill in every field across every section. Click Export PDF. Zero requests fire, during typing or during export. The only entries you ever see are the page's own files loading at the start. That is the point of the whole thing: it's a fact you can check in about ten seconds, not a paragraph you have to believe.

A map to your logins, not a copy of them

The architecture was the easy part. The content is the actual product, and one small decision there matters more than all the plumbing. In the accounts section, Keyholder asks where the password lives, never the password itself: your manager, a sealed envelope, the person who knows. So the finished sheet is a map to your accounts, not a spare copy of the keys. A document that says "the Chase login is in my 1Password, and my brother has the master phrase" is safe to keep in a drawer. A document with the actual master phrase in it is a disaster waiting for the wrong drawer.

The honest limitation is the flip side of the whole design: once nothing is stored for you, the file is entirely your responsibility. There's no reset link and no support line that can recover it. Optional autosave exists, off by default, and when on it writes only to this browser's localStorage, never synced anywhere; flip it back off and the draft is wiped. The PDF you export is the artifact. Where you put it, and who you tell about it, is the one part I genuinely can't do for you.

Try it

Open Keyholder and start filling in the first section while you watch the document assemble itself on the right. If you're the skeptical type, do it with the Network tab open and prove the banner honest before you type anything real. When the sheet looks right, hit Export PDF, save it somewhere your people can find it, and close the tab. The full source is on GitHub if you'd rather read the code than trust the screenshot.

Keyholder is live. Free, in your browser, no signup.

This post is part of the build log: every app my automated factory ships gets written up here, honestly. Browse everything at apps.charliekrug.com. Comments are open below.

Comments

Loading comments…