One snippet, one floating button. Let users sign up, store, search, edit, copy and delete their API keys — all from a secure, isolated widget that lives in the corner of any page.
Built around real workflows — not just a CRUD form. Auth, verification, recovery, search, copy, edit, delete, all wired and styled.
Sign up & login with strong password validation, email verification, resend with countdown timer, and full forgot/reset-password flow.
Debounced search, sort by platform/created/updated, asc or desc, with a clean "Load more" paginated list.
Inline forms with field-level validation. Delete is guarded by a confirm dialog so nobody nukes a key by accident.
The full key is never shown in the list. Click Copy and it's on the clipboard, with a fallback for older browsers and a friendly "Copied" flash.
Eye toggle on the API key input so users can verify what they pasted without exposing it on screen by default.
All widget styles live inside a Shadow Root — your app's CSS can never bleed in or get overwritten. Drop it in with zero conflicts.
API keys are the keys to your kingdom. Here's exactly how the widget protects them — in transit, at rest, and in the UI.
All requests run over TLS, served from a Let's Encrypt cert with HTTP → HTTPS auto-redirect. API keys never travel in plaintext.
Enforced 8–16 chars with uppercase, lowercase, number and special character. Weak passwords are rejected before they reach the API.
New accounts must confirm their email via a signed link before any keys can be added. Resend is rate-limited with a 60-second cooldown.
Tokens default to sessionStorage and die
with the tab. Persistent localStorage
only kicks in when the user explicitly ticks "Keep me logged in".
The dashboard never lists raw keys — only platform names. Each secret is fetched on-demand for a single Copy or Edit, and inputs stay masked until you click the eye.
Forgot-password issues a single-use token bound to the email request. Reused or expired links are rejected — no stale recovery surface.
Pick your stack. The API is identical everywhere.
import { useEffect } from "react"; import { initKeyVault } from "mm-key-vault"; export function KeyVaultBoot() { useEffect(() => { initKeyVault(); }, []); return null; }
"use client"; import { useEffect } from "react"; import { initKeyVault } from "mm-key-vault"; export function KeyVaultProvider() { useEffect(() => { initKeyVault(); }, []); return null; } // then drop <KeyVaultProvider /> inside app/layout.tsx
<script type="module"> import { initKeyVault } from "https://kv.masterymade.com/dist/mm-key-vault.esm.js"; initKeyVault(); </script>
All options are optional — sensible defaults are applied automatically.
initKeyVault({ position: "bottom-right", offsetX: "24px", offsetY: "24px", zIndex: 9999, });
positionbottom-rightoffsetX20pxoffsetY20pxzIndex9999The widget ships with a hardcoded backend. Same routes power auth and key management.