How Do I Keep My App Private With an Invite Code or Password?
6 min read
You want a private beta, so you need a gate: a way to let in the people you invited and keep everyone else out. The short answer is that you have three real options, from simplest to sturdiest: a single shared password on the whole site, an invite code checked at signup, or an allowlist of specific emails. For most vibe-coded betas an email allowlist is the right amount of gate. The one thing that will not protect you is a check that runs only in the browser.
Why this is fiddly
When you asked your agent to "build a signup page," it built exactly that: a form anyone can fill in. You never asked it to keep strangers out, so it didn't. The demo worked because the only person testing was you. A gate is a separate feature you have to ask for on purpose, and the agent will happily add a code box that looks like a gate but checks the code in front-end JavaScript, where anyone can read the correct answer or skip the check entirely.
There are two different things people mean by "private," and they need different gates:
- The whole site should be hidden (nobody should even see the landing page).
- Anyone can see it, but only invited people can make an account.
Pick which one you actually want before you build, because the fix differs.
How to check what you have now
- Open your app in a private/incognito window, signed out. If you can reach the real app without any code or login, you have no gate.
- If there is an invite-code box, open the browser's Network tab, submit a wrong code, and watch. If no request leaves the browser, the code is being checked in front-end code and is not a real gate.
- Try to hit a signed-in page directly by pasting its URL. If it loads, your gate is only on the buttons, not on the data.
The fix
Choose one of these and put the check on the server, not the browser.
- Whole-site password wall (fastest). If you host on Vercel, turn on Deployment Protection (Password Protection) for the project. Netlify and Cloudflare Pages have the equivalent. This puts one shared password in front of everything before your app even loads. Good for a truly closed alpha; weak if you need to know who is who.
- Email allowlist (best fit for most betas). Keep a table of invited emails. On signup, reject any address that is not on the list, and do the check in a server route or a database rule, never in the browser. On Supabase you can enforce this in the signup flow and back it with a Row Level Security policy; on Firebase, in a Cloud Function or Security Rules. Now every user is a real, named account you invited.
- Single-use invite codes (if you want to hand out links). Generate a code per invite, store it server-side with a "used" flag, and mark it used on redemption so one code lets in one person. Verify and burn the code in a server route.
Whichever you pick, re-run the incognito check from above afterwards and confirm a stranger is stopped.
The trap to avoid
The common wrong fix is a code checked in the browser: if (code === "BETA2026")
somewhere in your front-end JavaScript. Anyone can open the network tab, read the
correct code, and walk in, or just skip your signup page and call your API and
database directly. A gate that lives only in the browser is a sign on an open
door. The gate has to be enforced where the browser cannot edit it: on the server
or in your database rules.
Where this fits
An invite gate is one of the first things a curious visitor tests, and a fake one gives you false confidence right when you are inviting real people. It sits next to the other "is anyone I didn't invite getting in" questions, like stopping bots from creating fake accounts and knowing what beta-ready actually means. The free Readiness Report runs against your real project and tells you whether your gate is enforced on the server or only painted on the front end. If you would rather have the gate built and the surrounding fixes handed to you in order, that is what the Finishing Pass is for.