ephemera
End to end encrypted secrets that self-destruct.
github.com/iurman/ephemeraSource available / Self-hosted application

- Role
- Design and build
- Status
- Source available
- Stack
- Next.js 16
- tRPC 11
- Drizzle
- PostgreSQL
- Zod 4
- WebCrypto (AES-256-GCM, PBKDF2)
- Vitest against PGlite
- Playwright
Share something with a limited life
ephemera shares text, links and files with an expiry time and a chosen number of views. A sender composes a drop, selects its limits and lets the browser encrypt the content before it is uploaded.
The recipient gets a link to a reveal page. Text can be rendered as Markdown after decryption, while files are retrieved through the same encrypted-drop workflow. The server stores ciphertext.
Where the key lives
In link mode, a random 256-bit key is generated in the browser and carried in the URL fragment. Browsers do not send that fragment over the network, so the server receives a token and ciphertext without the decryption key.
Passphrase mode derives a key with PBKDF2-SHA256 and stores the salt. Decryption happens in the recipient's browser.
A deliberate reveal
Opening a link does not consume a view. Link previews, mail scanners and prefetching bots reach a gate page; the recipient must choose to reveal the secret.
A wrong passphrase can be retried locally against the fetched ciphertext without spending another view. Expiry and retention work remove dead content and prune old view logs.
The boundary of browser encryption
Encryption protects stored content from someone reading the database. A malicious server operator could still deliver JavaScript that captures a secret or its key, so browser-delivered encryption is not protection against every possible server attack.
The source is available to inspect and self-host. The gallery shows the application's compose-and-reveal path.
Have a project in mind?
Tell us what you want to build or what your current site needs.