Knock, knock.
Private previews, secured.
A password screen you paste into your project. No backend, no npm install, no platform upgrade. Set an env var and ship.
For freelancers, agencies, and teams shipping previews to clients
Three steps, no infrastructure.
Copy a file, generate a hash, wrap your app. Ship it.
One template, zero runtime dependencies.
Paste a single file into your project, or install it with the shadcn CLI. Nothing to configure at the platform layer.
Turn your code into a SHA-256 hash.
Type an access code into the generator below and copy the hash it produces — computed locally, never sent anywhere.
Wrap your app, set one env var.
Wrap the page in the gate, set the hash as an environment variable, and deploy. That's the whole install.
Generate a hash
Type or generate a code to get its hash. Only the hash gets pasted into your project, never the plaintext.
Runs entirely in your browser. Nothing is sent anywhere.
Multiple looks, one contract.
Pick the screen, wire a hash, ship it. Every template speaks the same props.
Branded Access
A copy-paste React password screen for client previews and private betas. One file, zero dependencies, local or server verification.
Knock Codes
A copy-paste React access screen for client previews and staging apps — segmented code entry, dark card, footer help text. One file, zero dependencies.
Minimal Access
A copy-paste React access screen for internal tools and quick gates — a single masked field, no frills. One file, zero dependencies.
Modal Access
A copy-paste React access screen for gating one section of a live page — a blur-overlay dialog, content stays mounted behind it. One file, zero dependencies.
Hides the hash, not the children.
Server mode keeps the hash off the client. Anything you already bundled is still in the JavaScript.
| Local mode | Server mode | |
|---|---|---|
| Setup | Paste a template, drop in a hash | One prop swap + a small endpoint |
| Hash visibility | Ships in the client bundle | Stays on your server |
| Bundled children | Still in the JavaScript | Still in the JavaScript unless you fetch after unlock |
| Stored session | Client-writable unless validateSession | Same — validateSession to reject a forged token |
| Rate limiting | Not possible | Yes, per identifier |
| Stops | Casual visitors, crawlers, forwarded links | Reading the hash — not bundled children on their own |
Common questions
Is this real authentication?
No. There's no user identity, no accounts, no permissions — everyone who has the code gets the same access. It's a shared secret, not authentication. See the security model for exactly what it does and doesn't protect against.
Why not use my host's built-in password protection?
If your host already offers one and it fits, use that instead. It's one less thing to maintain. Knock Codes is for when that option doesn't exist: a host with no built-in gate, a framework you don't want to configure at the platform layer, or a screen where the gate needs to live in your own app code instead.
Does it work with Next.js App Router and RSC?
Yes. Every template is a small client component that a Server Component can render as a child — that's exactly how this homepage's own live demo works. Streaming, RSC payloads, and the App Router's caching are unaffected; the gate only touches what's rendered inside it.
Can search engines bypass it?
Search engines that only read server-rendered HTML won't see what's behind the gate — local mode never renders the protected content until a matching code is entered, so there's nothing indexable in the initial markup. That's not a guarantee of invisibility, though — see the next question. Put noindex on any staging or preview deploy regardless; don't rely on the gate alone to keep it out of search results.
In local mode, does the protected content still ship in the bundle?
Usually, yes. Whatever you pass as children is still part of your React tree and your JavaScript bundle — the template just doesn't render it to the DOM until the state flips to unlocked. If what's behind the gate is genuinely sensitive, don't rely on this alone: fetch it only after unlock, or move it behind server mode.
How do I rotate a code?
Generate a hash for the new code and replace the old one — the env var in local mode, or your server's secret in server mode — then redeploy. Existing unlocked sessions keep working until they expire or are cleared, but nobody can unlock with the old code again.
Can I use multiple codes?
Not out of the box in local mode — expectedHash compares against exactly one hash. For more than one valid code, use server mode: your verify function can check the submitted code's hash against a list or lookup table on your server, where the comparison logic is entirely up to you.
Ready to lock something down?
Pick a template, copy the file, wire a hash. Ship it in minutes.