Add a login wall to your site
Put a sign-in screen in front of a site you've already deployed, so only the people you name can open it — everyone else hits a Google login and gets bounced. Route A wraps the site from outside and needs no code changes. Route B builds accounts into the site itself.
Time: ~25–40 min, once. The un-delegable parts are the same on both routes: create an account, register a Google sign-in app in Google's console, and paste a few keys. After that, adding or removing people is one sentence to your agent (Route B) or a few clicks (Route A). You'll need: Claude Code, a site that's already live (see Deploy a website), and a Google account. Last verified: 2026-06-07 · steps checked against Cloudflare One and Clerk's own docs.
[confirmed]New to all this? Do Set up Claude Code first, and skim how to ask your agent. Just want a finished thing anyone can open, no gate? You don't need this page — share the plain link.
Pick a route first
- Route A — Cloudflare Access (recommended). A login screen sits in front of your site; your code never changes. You list who's allowed by email; Cloudflare checks them with Google and turns everyone else away. Free for up to 50 people.
[confirmed]Best when you just want a wall and don't want to touch the app. - Route B — Clerk (accounts inside the app). Real user accounts live in your site — sign-in buttons, a profile menu, "show this only to logged-in users." Free to 50,000 monthly users.
[confirmed]Reach for it when the login is part of the product (per-user data, a members area), not just a gate.
Both lean on the same un-delegable trio: make the account, register a Google sign-in app, paste the keys. Your agent does the wiring around them.
Route A — Cloudflare Access (no app code)
One catch up front: Cloudflare Access can only guard a site on a domain that runs through Cloudflare. [confirmed] If your site is a *.vercel.app / *.netlify.app URL, you first point a custom domain at it through Cloudflare (a ~10-min DNS step), or expose it with a Cloudflare tunnel. Your agent can set either up — but the gate attaches to the domain, not the random host URL.
The ask
With Claude Code running, say:
I deployed a site and want to put a Google login wall in front of it with
Cloudflare Access (Zero Trust), free tier. Walk me through: connecting my
domain to Cloudflare, creating a Zero Trust team, adding Google as a login
method, and adding a self-hosted Access application with an Allow policy
that only lets these emails in: alice@example.org, bob@example.org.
Stop and hand me each step that needs me to click in a browser or in
Google Cloud Console.
The steps that are yours
Three things your agent can't click for you:
- Make the Cloudflare account + Zero Trust team (~5 min, once). Sign up at dash.cloudflare.com, open Zero Trust, pick a team name — that becomes your login domain
your-team.cloudflareaccess.com. Free plan, no card needed under 50 users.[confirmed] - Register a Google sign-in app (~10 min, once). This is the fiddly part — you create OAuth credentials in Google Cloud Console: a new project, an OAuth consent screen, then an OAuth client (Web application). It hands you a Client ID and Client Secret. Two fields must match Cloudflare exactly:
[confirmed]- Authorized JavaScript origin:
https://your-team.cloudflareaccess.com - Authorized redirect URI:
https://your-team.cloudflareaccess.com/cdn-cgi/access/callback
- Authorized JavaScript origin:
- Paste the keys + name who's in (~5 min). In Zero Trust → Settings → Authentication → Login methods, add Google and paste the Client ID + Secret. Then Zero Trust → Access → Applications → Add an application → Self-hosted, pick your domain, and add a policy: Action = Allow, rule Emails → list the addresses (or Emails ending in
@example.orgfor a whole org).[confirmed]
You're done when
You open your site in a private/incognito window and get the Cloudflare login screen → "Sign in with Google." An allowed email gets in; any other Google account is refused. Access is deny-by-default — if no Allow policy matches, nobody gets through. [confirmed]
Changing who's in, later
Edit the policy's email list in the dashboard — add or remove a line, save. Takes effect on their next sign-in. No redeploy, no code.
Route B — Clerk (accounts inside the app)
Clerk drops real sign-in into the app's own pages. Best when the login is the feature.
The ask
With Claude Code running in your project folder, say:
Add Clerk authentication to this app with Google sign-in. I'll create the
Clerk app and paste the keys. Then wire in the Clerk provider, a sign-in
button, a user menu, and gate the main page so only signed-in users see it.
Tell me exactly which environment variables to set and where the sign-in
page lives.
The steps that are yours
- Create the Clerk app + copy two keys (~5 min, once). Sign up at dashboard.clerk.com, Create application, and turn on Google as a sign-in option. Clerk shows you two keys to paste as environment variables:
[confirmed]NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY— the public one (safe in the browser)CLERK_SECRET_KEY— the private one (server only, never commit it)
- For testing: nothing else. Clerk's development instance uses shared Google credentials out of the box — Google sign-in works immediately with no console trip.
[confirmed] - For a real launch: register your own Google sign-in app (~10 min, once). When you go to production, Clerk requires your own Google OAuth credentials. In the Clerk dashboard turn on "Use custom credentials" for Google, copy the Authorized Redirect URI it shows you, then in Google Cloud Console create an OAuth client (Web application), paste that redirect URI into Authorized redirect URIs, and copy the Client ID + Secret back into Clerk.
[confirmed]
Your agent handles everything else — installing Clerk, wrapping the app in the Clerk provider, adding the sign-in button and user menu, and hiding pages from logged-out visitors.
Note on the gating components. Clerk's old
<SignedIn>/<SignedOut>tags are being replaced by<Show when="signed-in">.[confirmed]You don't need to know this — but tell your agent "use Clerk's current components" so it doesn't scaffold the deprecated ones.
You're done when
Run the app, open it logged out → you see a sign-in button, and "Continue with Google" works. Sign in → the gated content appears and a user menu shows your avatar. The free plan covers this fully up to 50,000 monthly users. [confirmed]
If it doesn't work
- Google says "Access blocked: this app's request is invalid" / redirect_uri_mismatch → the redirect URI in Google Cloud Console doesn't exactly match what Cloudflare or Clerk expects — a trailing slash,
httpvshttps, or the wrong team name. Copy it again, character for character, from the dashboard. For Route A it must end in/cdn-cgi/access/callback.[confirmed] - Google says "Access blocked: App not verified" / a scary warning screen → your OAuth consent screen is still in Testing mode, which only lets listed test users in (and shows a warning). Either add each allowed person under Audience → Test users, or click Publish app to move it to production. Route A only needs basic sign-in scopes, so publishing won't trigger Google's lengthy review.
[confirmed] - Nobody can get in (Route A) → you have no matching Allow policy, or the email list has a typo. Access is deny-by-default — without an Allow rule that matches the person, they're refused. Re-check the policy's Emails rule.
[confirmed] - Everybody can get in (Route A) → your policy's rule is too wide — e.g. Allow / Everyone, or Emails ending in a public domain like
@gmail.com. Narrow it to specific addresses or your own org domain.[confirmed] - The login screen never appears (Route A) → the site isn't actually behind Cloudflare. The domain must be an active zone proxied through Cloudflare, and the Access application must point at that hostname — not the raw
*.vercel.appURL.[confirmed] - Clerk keys "invalid" or build fails (Route B) → you swapped the two keys, or left
CLERK_SECRET_KEYunset on the server. The publishable key startspk_, the secretsk_. Set both, and make sure the secret is in your server env (and your deploy host's env vars), not the client bundle.[confirmed] - Google sign-in works locally but breaks once live (Route B) → you shipped with Clerk's shared development credentials. Production needs your own Google OAuth app wired in (step 3 above).
[confirmed]
The slower path: do it all by hand
You don't need the agent for any of this — both routes are clickable dashboards end to end.
- Route A by hand: Cloudflare's own walkthrough takes you click-by-click: add the domain, add Google under Login methods, then Access → Applications → Add → Self-hosted and an Allow policy. The Google identity-provider guide covers the Google Cloud Console half. ~25 min total.
[confirmed] - Route B by hand: Clerk's quickstart plus the Google social-connection guide walk through creating the app, copying keys, and pasting the components yourself. ~20 min, but you'll still write the gating code.
[confirmed]
Watch / read
YouTube blocked transcript pulls from this machine on 2026-06-07, so these aren't verified line-by-line — but each is on the exact task and short, and the first in each pair is the vendor's own channel, so the steps match the dashboards above.
Route A — Cloudflare Access:
- How to Restrict Access to a Website with Cloudflare Zero Trust — Ryder Cragie, 4:06. Add a self-hosted app + an email Allow policy, start to finish. Why this one: shortest walkthrough that shows the exact Allow-policy screen.
- Cloudflare Access: Product Demo — Cloudflare, 5:22. The vendor's own demo of the login-in-front-of-a-site flow. Why this one: official, shows the end-user Google login experience.
Route B — Clerk:
- Add authentication to your Next.js app in 100 seconds with Clerk — Clerk, 2:37. The provider, the components, the keys, in under three minutes. Why this one: official, and the fastest end-to-end picture.
- Add Google OAuth Sign-In with Clerk Components in Next.js — Imran Codes, 4:30. Focuses on the Google connection specifically. Why this one: walks the Google toggle the brief hinges on. (unofficial — community channel, seen 2026-06-07)
Best written walkthroughs:
- Route A: Cloudflare's Add a self-hosted application — the authoritative source the Route A steps were checked against.
[confirmed] - Route B: Clerk's Set up Clerk + Next.js quickstart — the env-var names and components here come straight from these.
[confirmed]
Sources
- Cloudflare Access — policies (Allow action, Include/Emails rules) — checked 2026-06-07
- Add a self-hosted application to Access (menu path, deny-by-default, domain must be an active Cloudflare zone) — checked 2026-06-07
- Google as an identity provider in Cloudflare One (Client ID/Secret,
/cdn-cgi/access/callbackredirect URI) — checked 2026-06-07 - Cloudflare Zero Trust plans — free for up to 50 users — checked 2026-06-07
- Clerk — Set up Clerk (create app, copy keys) — checked 2026-06-07
- Clerk Next.js quickstart —
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY/CLERK_SECRET_KEY, provider + components,<Show>replacing<SignedIn>/<SignedOut>— checked 2026-06-07 - Clerk — Google social connection (shared dev credentials; custom credentials for production) — checked 2026-06-07
- Clerk pricing — 50,000 MRU free per app — checked 2026-06-07
- Google OAuth unverified-app / testing-mode warning behaviour — checked 2026-06-07