The URL is the database
The TypeScript Playground, Babel REPL, and Excalidraw all do it: encode app state in the URL so anyone with the link sees exactly what you see. No server, no login, no expiring share tokens. The link is the saved state.
When I built Code Explorer, I needed shareable links for code snippets. The whole app is static HTML on GitHub Pages. No backend to store anything. The URL hash was the obvious answer.
The whole thing
lz-string compresses text and outputs a URL-safe string. Read the hash on load, write it on every edit. That's it.
replaceState is important. Without it, every keystroke adds
a history entry, and the back button becomes unusable.
How much fits?
Browsers handle URLs up to around 8KB reliably (Chrome goes higher, but some proxies and CDNs truncate past 8K). lz-string compresses typical code at roughly 60-75%, so you can fit ~5KB of source in a URL. That covers most code snippets, config files, and small modules.
For Code Explorer's default sample (2,400 chars of TypeScript), the compressed hash is ~580 characters. Plenty of room.
Trade-offs
URLs are public. Anyone with the link sees the content. There's no access control, no deletion, no analytics. The "database" is literally just the bytes in the URL. If the link dies (someone stops sharing it), the state is gone.
For tools where sharing means "look at this code," that's exactly right. No accounts, no permissions, no server costs. Copy the link, send it, done.
Try it: code-explorer type map