CTCarl Tracy
All work
Live2026

Time-Lock Vault

A password you cannot get back until the date you chose.

The real thing, running here. Hover to scroll it, or click to use it — Escape stops.

The problem with every other version of this

Search for an app that locks something away until a date and you will find dozens. They all work the same way: you give your secret to a server, and the server promises not to hand it back early.

That is a promise, not a lock. It fails if the company is acquired, if the database leaks, if someone talks a support agent into an override, or if the service simply shuts down. And crucially, it fails for exactly the person it is supposed to constrain — because if you can email support, you can get it back.

The actual mechanism

drand is a public randomness beacon run as a distributed network. It publishes a new random value at a fixed interval, forever, and the value for a future round is not computable in advance by anyone.

tlock-js lets you encrypt against a specific future round. The resulting cipher cannot be decrypted until that round is published — not slowly, not with effort, but not at all, because the key does not exist.

The consequences are worth stating plainly:

  • Changing your system clock does nothing.
  • Going offline does nothing. It fails closed — no network, no opening.
  • Reading the page source does nothing.
  • I cannot open it early. Neither can you. There is no emergency exit.

That last one is the feature, and it is irreversible. An escape hatch you control is not a constraint.

Why I built it

To moderate my own Steam access — not quit, moderate. A fixed weekly slot, reached by a ladder that widens the gap a day at a time. My mother holds the Steam recovery email, which closes the obvious back door of just resetting the password.

It works for any secret. The Steam framing is just what made me write it.

The honest limitation

Everything is local. Ciphers live in localStorage, tied to one browser on one device. Lose them and the password is gone permanently, because there is no server holding a copy — that being the entire point.

Export exists for exactly this reason, and the discipline it demands is real: seal something, then immediately email yourself the cipher. The architecture that makes it trustworthy is the same architecture that makes it unforgiving.

The most recent pass softened that without compromising it. Download as an openable file saves a copy of the whole page with your shelf baked into it — not a data export you would have to import somewhere, but a working copy of the app that opens by double-click, offline, with every countdown and Open button intact. Asking someone to keep a JSON file safe is asking them to understand what it is for. Asking them to keep a file that just works is not.

What the last change taught me

The trust-model note — don’t want to type your real password here? Zip it locally and seal the zip’s password instead — was written, correct, and completely invisible. It sat inside a collapsed panel that nobody opens.

Moving it took five minutes and no logic changed. But a safeguard nobody reads is not a safeguard, and “it’s in the documentation” is the weakest defence in software. If it matters, it goes where people are already looking, in the colour you use for everything else that matters.

Refinements

How it changed

Every pass, dated, oldest first — nothing trimmed and nothing tidied out. The version that got rejected is usually more informative than the one that shipped.

20 entries·scroll sideways

5

  1. Started
    Rejected the obvious architecture first

    Every app in this category works the same way — a server holds your secret and declines to give it back until a date. That is not a lock, it is a promise, and it breaks the moment the server is compromised, sold or switched off. Started instead from drand, the League of Entropy beacon that publishes a new random round every three seconds. Encrypt against a future round and the decryption key does not exist anywhere on Earth until that round arrives.

    Functionality
  2. Changed
    One self-contained file, not an app you install

    tlock-js bundled with esbuild into a single HTML file. No accounts, no analytics, no server, and no network call at all except to api.drand.sh at the moment of opening. Sealing works fully offline, because tlock-js hardcodes the chain info — you can lock something away with no connection at all.

    Functionality
  3. Changed
    Dropped the one-month ceiling

    The first build capped seals at a month, on the theory that longer was irresponsible. That was me designing around my own nerves. The cap went to 20 years — still a sanity guard, but no longer a policy about how anyone else should use it.

    Functionality
  4. Changed
    Generate the password in-page, without ambiguous characters

    If the point is that you never see the secret again, typing one you already know is the weaker path. A 24-character generator using crypto.getRandomValues, with lookalike characters stripped out so reading one off a screen at 11pm cannot go wrong.

    Quality of life
  5. Changed
    Named the categories instead of asking "what is this?"

    A free-text box makes you invent a label every time. A dropdown grouped by Gaming, Social & media, Money and Other — with the specific services listed under each — turns it into one click, with free text still available for anything unlisted.

    Ease of use

12

  1. Changed
    Series — one seal, many ciphers

    A single cipher cannot change a habit; it just postpones one evening. Series mints a run of them on a repeating schedule, each opening on its own date and all holding the same password. Open one, log in, burn it, wait for the next.

    Functionality
  2. Changed
    The ladder, and the arithmetic underneath it

    Fixed intervals do not reduce anything. Ladder mode takes free-text day gaps that widen over time. The recommended preset ramps 1+2+3+4+5+6 — which sums to 21, exactly three weeks — so after the ramp every release lands on the same weekday forever. Four presets: Ramp to weekly, Ramp to fortnightly, Gentle ramp, and Full taper for quitting outright.

    Functionality
  3. Note
    Predictability is the mechanism, not a nicety

    An erratic access schedule reproduces the variable-reward pattern that makes gambling compulsive. A schedule you can predict does the opposite. That is why the ladder converges on a fixed weekday rather than simply getting longer, and why "Anchor start" exists to snap the first release to a chosen weekday and time.

    Functionality
  4. Changed
    The Open button enables itself, with no refresh

    The shelf shows live countdowns, and a vault's Open button switches on the moment its round lands. Making someone reload a page to find out whether they are allowed yet adds a small ritual of checking, which is precisely the behaviour the app exists to reduce.

    Quality of life
  5. Changed
    Decrypt in place, then burn

    The password appears in the row it belongs to, with Copy and Burn directly beneath it — not in a modal, not at the top of the page. Burn deletes the cipher and wipes the clipboard, so the intended ritual (open, log in, burn immediately, then play) is the path of least resistance rather than a discipline you have to remember.

    Quality of life
  6. Changed
    Export and email, because there is no sync

    Ciphers live in localStorage, keyed to one browser on one device. Building sync would mean a server, which would undo the entire premise. So: export the whole shelf to JSON, import merges and skips duplicates, and any row can be emailed to yourself — with a one-email-for-the-whole-set option that falls back to the clipboard when the mailto would be too long. A stolen cipher is worthless until its date, so this is safe to do.

    Functionality
  7. Changed
    An opening log that counts the gap, not the streak

    Every opening is recorded with its date, the vault name, and the gap since the previous one, plus a 30-day stat line. Streak counters reward not opening, which turns into a thing to protect and then to break. The gap is the honest measure — and if gaps are widening while sessions get longer, that is bingeing, and the schedule should hold rather than stretch.

    Quality of life
  8. Changed
    Open a cipher that is not on this shelf

    Paste a cipher from a backup email, or load a .txt file. The round is readable from the armor header, so the page can show a real countdown for a cipher it has never seen before, and refuse to open it early. This is what makes the email backup an actual recovery path rather than a comforting-looking string.

    Functionality
  9. Fixed
    The service worker must never cache drand

    The PWA kit caches the app shell so it works offline — but requests to drand.sh are deliberately excluded. A cached beacon response could wrongly unlock a vault, or wrongly refuse to open one that is due. Caching the wrong thing here breaks the only guarantee the app makes.

    Functionality
  10. Note
    The ratchet only turns one way

    Tightening the schedule is one click — delete the remaining ciphers. Loosening it takes five minutes: new password, new ladder, reseal. The asymmetry is deliberate. A system you can relax as easily as you can tighten it is not a constraint, it is a suggestion.

    Functionality
  11. Note
    Known limit, written down rather than hidden

    Sealing 300+ ciphers at once will freeze the tab, because the encryption loop is synchronous. Fine at 50, ugly at 366. The fix is to yield to the event loop between iterations. Recorded in the handoff as a known gap rather than discovered later by whoever hits it.

    Quality of life
  12. Shipped
    Decided against ads, permanently

    An attention-harvesting SDK inside an attention-protection app is a contradiction, and it would break the "nothing leaves your device" claim that is the product's single best argument. Free with a tip jar instead. If it ever monetises properly: a one-time unlock, never a subscription — you do not bill someone monthly for not gaming.

    Quality of life

3

  1. Changed
    A way to use it without trusting the page at all

    Added a note for people unwilling to type a real password into a web page: protect the secret in a local zip first using a tool you already trust, and seal the zip's password here instead. The page then only ever sees an arbitrary string you invented, never the real secret.

    Ease of use
  2. Changed
    Download the whole thing as a file that still works

    The honest weak point was always that losing every copy of a cipher loses the password permanently, and "export a JSON file" asks someone to understand what a JSON file is for. So: one button that saves a complete copy of the page with the current shelf baked in as a localStorage seed. Double-click it later, in any browser, offline, and it behaves exactly like this page — countdowns, Open, per-cipher delete, all of it, because it literally is this page. The source it copies is captured once at load, before any button can have been pressed, so a downloaded file can never carry a decrypted password in it.

    Quality of life
  3. Fixed
    Moved it, because nobody was going to read it there

    That note was correct and completely invisible — written inside a collapsed "How it works" panel that nobody opens. It became its own box, in the app's existing warning red, placed above "How it works" and open by default. Five minutes, no logic changed. A safeguard nobody reads is not a safeguard, and "it's in the documentation" is the weakest defence in software.

    Ease of use

Screens

A look around

Look around — 4 screens

  • Time-Lock Vault: Sealing a vault — enter a secret or generate one, then set the date it becomes openable.
    Sealing a vault — enter a secret or generate one, then set the date it becomes openable.
  • Time-Lock Vault: The trust-model box. Moved out of a collapsed panel and made red, because nobody was reading it where it was.
    The trust-model box. Moved out of a collapsed panel and made red, because nobody was reading it where it was.
  • Time-Lock Vault: Ladder mode — gaps of 1,2,3,4,5,6 days then 7 forever. The sum is exactly three weeks, so every release lands on the same weekday.
    Ladder mode — gaps of 1,2,3,4,5,6 days then 7 forever. The sum is exactly three weeks, so every release lands on the same weekday.
  • Time-Lock Vault: Opening a cipher from a backup email, and the log that tracks the gap between openings rather than a streak.
    Opening a cipher from a backup email, and the log that tracks the gap between openings rather than a streak.