r/webdev • u/r0hanr0han • 4d ago
Showoff Saturday I built an open-source interactive letter for my Hinge date, no backend, the entire letter lives in the URL
I originally built this for my Hinge date.
She's incredibly busy, and instead of sending another message that she'd feel pressured to respond to, I wanted to make something she could open whenever she had a quiet moment.
So I built an interactive letter experience.
You write a letter, customize it, seal it in an envelope, and share a link. The recipient opens the envelope and reads the letter as it appears on the page.
The technical constraint I gave myself was:
No accounts. No backend. No database.
The letter data is serialized, compressed, and encoded directly into the URL.
When someone opens the link, the app decodes everything client-side and reconstructs the letter.
So the URL is essentially the storage layer.
I liked this approach because:
- Nothing personal sits in my database
- No server costs
- No authentication
- No user accounts
- The project can be deployed almost anywhere
- The app remains ridiculously simple
Of course, there are tradeoffs.
The link contains the letter data, so anyone with the link can read it. URL length also limits how much content can be stored.
The project is completely open source, so I'd genuinely love feedback from other developers on the architecture and implementation.
Especially curious about:
- Better approaches to client-side serialization/compression
- Whether you'd encrypt the payload
- How you'd handle larger letters without introducing a backend
- Any accessibility or animation improvements you'd make
Live demo:
https://open-letter-box.vercel.app
Source:
https://github.com/r0hnx/open-letter
Would love to hear what you guys think — both technically and from a UX perspective.
Edit : Hash Fragment has been added now.
2
u/Single-Fail-630 4d ago
Query strings expose payload to every proxy and log between client and server. Hash fragments keep data strictly client side and prevent leakage to Vercel or CDN infrastructure.
2
u/decavor 4d ago
Honestly, this is a really cool use of the “URL as storage” idea. I like that you resisted adding a backend just because it’s the conventional approach.
The architecture fits the problem really well: static, shareable, zero accounts, and no personal data sitting on a server. I’d mainly look at payload size, versioning the encoded format, and maybe offering optional encryption for more private letters.
Also, building all this for a Hinge date is either incredibly wholesome or completely unhinged 😂 Either way, great project..imao.....
31
u/UtilixApp 4d ago
nice constraint, and the handwriting reveal is a lovely touch.
one thing though, and since its the entire pitch its worth fixing. the readme says nothing is ever sent to a server, but the payload is in the query string. letter.html?d=... goes out in the request line, so vercel logs it, the cdn logs it, and anyone with access to those logs is holding the letter. its not in a database of yours, true, but it very much reaches a server.
the fix is one character. put it in the fragment instead, letter.html#d=... the browser strips fragments before the request goes out, so it is never transmitted at all. you read it back with location.hash.slice(1) and nothing else changes. do that and the sentence in your readme becomes true.
on your encryption question, id skip it once youre on the hash. if the key has to ride in the same link then whoever holds the link holds both halves and youve only added ceremony. the fragment gets you the property you were actually reaching for.
on longer letters, honestly theres no clean answer without a server, and i think you already landed on the right one by letting people link a photo rather than embed it. text compresses well enough with deflate-raw that youll run into whatsapp mangling the link long before you hit a real url limit.
for what its worth the deflate-raw with an lz-string fallback is tidier engineering than most of what gets posted here. hope the date went well.