because i don't trust pastebins either

I use pastebins all the time.

API keys. Logs. Config files. Recovery codes. Terminal output. Things that need to be shared, but probably shouldn't live forever.

The problem is that using one usually means trusting someone else's server with your data.

Maybe the service encrypts your notes. Maybe it doesn't. Maybe the implementation is solid. Maybe it isn't.

Either way, you have to trust that someone, somewhere, can read your data if something goes wrong.

I wanted something simpler.

Something where the server literally can't read what you upload.

So I built binthere.

How it works

Every note is encrypted in your browser before it's uploaded.

The server only ever stores encrypted data. It never sees the original note, and it never receives the encryption key.

Even if someone had access to the server or database, all they'd find is ciphertext.

The interesting bit

My favorite part is where the encryption key lives.

Instead of uploading it, the key stays in the URL fragment:

https://binthere.gaury.dev/p/abc123#key_here

Browsers never send anything after the # to the server.

That means the server only receives:

https://binthere.gaury.dev/p/abc123

When someone opens the link, their browser reads the key from the URL, downloads the encrypted note, and decrypts everything locally.

The server never has enough information to read the contents.

I always thought that was a neat trick.

Open once. Then it's gone.

Most of the things I share only need to be seen once.

So every note is one-time by default.

The first successful reader gets the contents, after which the note is permanently deleted. If nobody opens it, it expires after 24 hours.

You can also add an optional password, so both the URL key and the password are needed to decrypt the note.

The surprisingly hard part

Making "open-once" actually mean once turned out to be trickier than I expected.

What happens if two people click the same link at the exact same time?

Without some coordination, they could both end up reading the note before it's deleted.

To avoid that, binthere uses Cloudflare Durable Objects to perform the read-and-delete operation atomically.

The first request gets the note.

By the time every other request arrives, it's already gone.

Why Cloudflare Workers?

The whole project runs on Cloudflare Workers with Durable Objects and KV.

I also intentionally skipped frameworks and build steps.

It's just plain JavaScript and the Web Crypto API.

Fewer dependencies, smaller codebase, easier to audit, and easier to deploy.

Open source

Binthere is completely open source under the MIT License.

If you'd rather not trust my deployment, you can run your own instance in a few minutes.

Live: binthere.gaury.dev

GitHub: github.com/nxfu/binthere

I like building tools that solve problems by removing trust instead of asking for more of it.

This was one of those projects.

Let's see what I build next.

For the curious

This post is the "why."

The README is the "okay, but how exactly?"

If you're the kind of person who gets excited about URL fragments, AES-GCM, and Durable Objects, you'll probably enjoy it.

GitHub: github.com/nxfu/binthere/blob/main/README.md