This is a submission for the GitHub Finish-Up-A-Thon Challenge
What I Built
FadeKey is a zero-knowledge, self-destructing secret sharing engine. Encrypted entirely in the browser using AES-GCM, the decryption key resides only in the URL hash fragment (#key=...). Since browsers do not send the hash fragment in HTTP requests, the server never sees the key or plaintext.
The project is divided into two distinct components:
Public Open-Source Core: A standalone, stateless Fastify API and SDK package for self-hosting and automation via pipelines/CLI.
Private SaaS Dashboard: A commercial-grade Nuxt 4 web app that adds user accounts, Postgres database sync, persistent audit logs, and Stripe subscription control.
Demo
- Live Site (Private SaaS): https://fadekey.app
- GitHub Repository (Open-Source Core): https://github.com/fadekey-app/fadekey.api
The Comeback Story
We resurrected an unfinished prototype that had major security flaws, incomplete features, and a leaking state. Here is our before-and-after journey:
1. Active Revocation (SDK & API Core)
Before: Secrets could only expire via TTL or view limits. The backend lacked a deletion endpoint, and the @fadekey/sdk had an empty placeholder where revoke() should have been.
After: We built a secure DELETE /api/items/:id route in the Fastify API (with owner verification checks) and implemented the corresponding revoke(id) method in the SDK package.
2. Zero-Knowledge Compliance for QR Codes (UX/Security)
Before: The prototype suggested using external public APIs to generate QR codes. However, sending the full secret URL (containing the #key hash) to a third-party server violates zero-knowledge compliance.
After: We moved 100% of the QR code generation to the browser using local client-side rendering with the qrcode library, ensuring the decryption key never leaves the client.
3. Local-to-Cloud Preference Syncing
Before: Users lost their theme (dark/light) and locale (en/es/pt-BR) settings upon page reload, and there was no way to persist these preferences for registered users.
After: We built a dual-persistence system. Anonymous users store preferences in cookies/localStorage, while authenticated users sync their choices automatically to a PostgreSQL database via a new PATCH /api/auth/preferences endpoint.
4. Critical Nuxt SSR Session Leaks (Major Bugfix)
Before: The authentication state was stored in a global reactive singleton. During Server-Side Rendering (SSR), this leaked the session/token of one user to subsequent requests from completely different visitors, causing security risks and hydration errors.
After: We refactored the auth composable to store sessions in request-isolated Nuxt useState wrappers, guaranteeing sandboxed memory for every client.
5. Transition Polish & Redirection Guarding
Before: Logging out caused dashboard pages to immediately display blank values and zeroes before redirecting. Redirections also dropped the active language prefix (e.g. redirecting /pt-BR/app/dashboard to / instead of /pt-BR).
After: We deferred state destruction in signOut() until after the router navigation completes, backed by a nextTick + delay in router.afterEach to allow the DOM to mount. We wrapped all redirects in localePath() to ensure language consistency.
My Experience with GitHub Copilot
GitHub Copilot acted as a core partner during this sprint, particularly in:
- Refactoring Auth for SSR Safety: Copilot recognized the risks of our initial module-level singleton state in Nuxt and drafted the migration to request-scoped
useStatehooks, pointing out how to avoid server-side data pollution. - Writing Vitest Suites with Testcontainers: It accelerated the creation of our backend integration tests, generating mock Postgres databases and Redis instances using Docker Testcontainers to test rate-limiting and quota rollback scenarios.
- Client-side Encryption Pipelines: Copilot assisted in structuring the Web Crypto API calls in our SDK to correctly derive password hashes using PBKDF2 without introducing synchronous blocking.

Top comments (3)
Parabéns Julian!
devchallenge
githubchallenge
GitHub “Finish-Up-A-Thon” Challenge Submission
A great way to safely share keys with others, pretty cool!
Awesome!