This document explains how to configure Cloudflare Turnstile for both local development and production deployment.
Turnstile is integrated to protect Pokemon pages from bot traffic by requiring users to complete a one-time security challenge. The verification is valid for 24 hours via a secure session cookie.
The .dev.vars file contains your Turnstile keys for local development. This file is already created but needs your actual keys.
Edit .dev.vars and replace the placeholder values:
# Public site key (visible in client-side code)
NEXT_PUBLIC_TURNSTILE_SITE_KEY=0x4AAAAAAA...
# Secret key (NEVER expose to client - used for server-side validation only)
TURNSTILE_SECRET_KEY=0x4AAAAAAA...Where to find your keys:
- Go to Cloudflare Dashboard
- Navigate to Turnstile
- Select your widget
- Copy the Site Key and Secret Key
npm run previewWrangler will automatically load the .dev.vars file.
- Visit
http://localhost:8788/pokemon/pikachu/red-blue/kanto - You should be redirected to
/verify?redirect=/pokemon/pikachu/red-blue/kanto - Complete the Turnstile challenge
- You'll be redirected back to the Pokemon page
- For the next 24 hours, you won't see the challenge again
IMPORTANT: Never deploy .dev.vars to production. Cloudflare uses encrypted secrets instead.
After deploying your code, set the secrets via Wrangler:
# Deploy your code first
npm run deploy
# Then set the secrets (you'll be prompted to enter each value securely)
wrangler secret put TURNSTILE_SECRET_KEY
wrangler secret put NEXT_PUBLIC_TURNSTILE_SITE_KEYWhen prompted, paste your production Turnstile keys.
- Go to Cloudflare Dashboard
- Navigate to Workers & Pages
- Select your
pokemechanicsworker - Click Settings → Variables
- Under Environment Variables, click Add variable
- Add two variables:
- Name:
TURNSTILE_SECRET_KEY- Value: (paste your secret key)
- Type: Encrypted
- Name:
NEXT_PUBLIC_TURNSTILE_SITE_KEY- Value: (paste your site key)
- Type: Plain text (this is public anyway)
- Name:
- Click Save
- Redeploy if necessary
After deployment:
- Visit https://pokemechanics.app/pokemon/pikachu/red-blue/kanto
- You should be redirected to the verification page
- Complete the Turnstile challenge
- Verify you're redirected back to the Pokemon page
- Check that subsequent Pokemon page visits work without re-challenge (for 24 hours)
-
First Visit:
- User → Pokemon page → Middleware detects no session cookie
- Redirect to
/verify?redirect=/pokemon/pikachu/red-blue/kanto - Turnstile widget loads (invisible unless suspicious traffic detected)
- User passes challenge → Token sent to
/api/verify-turnstile - Server validates with Cloudflare → Sets 24hr session cookie
- Redirect back to Pokemon page
-
Return Visits (within 24 hours):
- User → Pokemon page → Middleware finds valid cookie
- Request proceeds directly to page (no challenge)
-
Bot Traffic:
- Bot → Pokemon page → Middleware detects no cookie
- Redirect to
/verify - Bot fails Turnstile challenge → No cookie set
- Bot remains blocked from all Pokemon pages
✅ Session-based verification: One challenge per 24 hours ✅ Managed challenge mode: Invisible to most users, only shows CAPTCHA to suspicious traffic ✅ Middleware enforcement: Bots blocked before reaching CPU-intensive Pokemon pages ✅ Secure cookies: HttpOnly, Secure, SameSite=Lax ✅ Secret key protection: Never exposed in client code, stored encrypted in Cloudflare
- Cause:
NEXT_PUBLIC_TURNSTILE_SITE_KEYnot set - Fix: Add the environment variable and redeploy
- Cause:
TURNSTILE_SECRET_KEYnot set - Fix: Run
wrangler secret put TURNSTILE_SECRET_KEYor add via Dashboard
- Cause: Browser blocking Cloudflare challenges domain
- Fix: Check browser extensions/ad blockers, ensure
challenges.cloudflare.comis not blocked
- Cause: Cookie not being set after successful verification
- Fix: Check browser allows cookies, verify API route is setting cookie correctly
New Files:
.dev.vars- Local development secretssrc/components/TurnstileChallenge.tsx- Challenge widget componentapp/verify/page.tsx- Verification pageapp/api/verify-turnstile/route.ts- Validation API endpointsrc/utils/validateTurnstile.ts- Validation utilityTURNSTILE_SETUP.md- This documentation
Modified Files:
app/layout.tsx- Added Turnstile scriptmiddleware.ts- Added session verification and.dev.varsblocking.gitignore- Added.dev.vars
After deployment, monitor:
- Cloudflare Analytics → Check reduction in CPU timeout errors
- Turnstile Dashboard → View challenge success/failure rates
- Worker Logs → Watch for validation failures
Expected results:
- Bot traffic blocked at middleware (no CPU usage)
- Legitimate users challenged once per 24 hours
- CPU timeout errors significantly reduced