react-turnstile
React bindings for Cloudflare Turnstile — a privacy-first CAPTCHA alternative with a declarative component and a full imperative ref API.
Repository Health
Technical Analysis
@marsidev/react-turnstile wraps Cloudflare’s Turnstile CAPTCHA replacement in a single <Turnstile siteKey="..." /> React component, handling script injection, container sizing (to avoid layout shift across widget sizes), and widget lifecycle internally so consumers don’t touch Cloudflare’s raw window.turnstile API directly.
For cases that need more control, an optional ref exposes reset(), execute(), remove(), getResponse(), getResponsePromise(), and isExpired() against the underlying widget instance. It ships full TypeScript types for every public shape, works with React 17 through 19, and is built for SSR frameworks like Next.js and Remix out of the box.
What You Get
- A
<Turnstile />component that handles Cloudflare script injection, widget rendering, and teardown automatically - An imperative ref API (
reset,execute,remove,getResponse,getResponsePromise,isExpired) for manual control - Automatic container sizing per widget size (normal/compact/flexible/invisible) to prevent layout shift while the widget loads
- Full TypeScript types for props, render parameters, and the server-side siteverify request/response shapes
- SSR-safe rendering that works with Next.js, Remix, and other React SSR frameworks
Common Use Cases
- Adding a CAPTCHA-style bot check to a login or signup form
- Gating form submission behind a solved Turnstile challenge before hitting the server
- Running an invisible, non-interactive challenge via
execution: 'execute'triggered by a user action - Rendering multiple independent Turnstile widgets on the same page
Under The Hood
Architecture
The Turnstile component (packages/lib/src/lib.tsx) is a single forwardRef component built around a module-level singleton script-loading state machine (turnstileState, turnstileLoadPromise) so Cloudflare’s api.js is injected exactly once no matter how many widget instances mount. useObserveScript (use-observe-script.ts) backs this with a MutationObserver to detect the script tag even when it’s injected manually. Container (container.tsx) is a thin forwardRef wrapper that lets the rendered tag be customized via an as prop. Everything else is orchestrated through effects: an inject effect calls injectTurnstileScript (utils.ts), a wait effect resolves once window.turnstile exists, and a render effect calls window.turnstile.render with a memoized renderConfig that maps declarative props onto Cloudflare’s raw parameter names, storing the returned widget id in a ref and calling turnstile.remove on cleanup. The imperative handle exposed via useImperativeHandle is a thin, stateful shim directly over window.turnstile, by design, since the underlying widget is a global browser API rather than something the library can reimplement.
Tech Stack
TypeScript throughout, with wide React peer dependencies (^17.0.2 || ^18.0.0 || ^19.0) covering three major versions. Built to ESM-only output with tsdown, typechecked with tsgo (TypeScript’s newer Go-based checker) rather than plain tsc, tested with vitest plus @testing-library/react and jsdom, and linted/formatted with the Rust-based oxlint/oxfmt instead of ESLint/Prettier. The repo is a pnpm workspace with three packages: the library itself, a Next.js demo app under demos/, and a 13-page docs.page documentation site under docs/. Releases are automated with Changesets, and CI includes a dedicated zizmor.yml workflow for GitHub Actions workflow security linting.
Code Quality
The test suite exercises real DOM behavior with @testing-library/react and jsdom across dedicated cases for basic mounting and script injection, manual script injection, invalid render-parameter handling, and offlabel parameter forwarding. Error handling is deliberate rather than incidental: tryRenderWidget wraps window.turnstile.render in a try/catch specifically because Cloudflare’s script throws synchronously for invalid parameters instead of routing them through its own error callback, and this quirk is documented directly in code comments alongside other tracked upstream issues (nonce attribute reflection, invisible-mode container sizing). Every public type is exported and documented with TSDoc comments, and CI lints and tests on every push.
What Makes It Unique
The library’s core value is collapsing Cloudflare’s imperative, global-object Turnstile API into one declarative component while still exposing an escape hatch for the imperative cases (execute() for invisible/execution mode, getResponsePromise() for awaiting a solved token as a promise). rerenderOnCallbackChange is a deliberate, documented API tradeoff: stable callback refs by default to avoid unnecessary widget re-renders, with an opt-in mode for consumers who need live callback updates. Thirteen dedicated documentation pages (dynamic callbacks, form-submission retry logic, multiple widgets, validating a token server-side, and more) go well beyond a typical single-README package.
Used by 10 apps in this directory
AFFiNE
Productivity · Project Management · Note Taking
Write, draw, and plan in one infinite canvas — the open-source alternative to Notion and Miro that keeps your data yours.
Documenso
Digital Signiture
Self-hosted, open-source DocuSign alternative with legally binding PDF signatures, multi-party workflows, and a full REST and tRPC API.
Karakeep
Bookmarks Archiving
Self-hosted bookmark manager that captures links, notes, images, and PDFs with AI tagging, full-text search, and automatic archiving.
LearnHouse
Learning Management · CMS
Open-source LMS with AI tutoring, real-time collaboration boards, live code execution, and built-in course monetization — self-hosted in minutes.
Libra AI
AI Development · No Code Platforms
Open-source AI-powered platform that generates and deploys full-stack web applications from natural language prompts, built natively for Cloudflare Workers.
LibreChat
Developer Tools · AI Assistants
Unite every major AI model in one self-hosted chat platform with agents, code execution, MCP tools, and enterprise authentication.
PostHog
Analytics · Monitoring · Developer Tools
The all-in-one open source product platform combining analytics, session replay, feature flags, error tracking, AI observability, and a built-in data warehouse in a single self-hostable stack.
Rallly
Scheduling
Self-hostable group scheduling polls that eliminate back-and-forth emails and find the best meeting time for everyone.
Rivet
AI Agents · Developer Tools
Stateful actors as a primitive for AI agents, real-time collaboration, and durable execution — with in-memory state, WebSockets, queues, and scheduling built in.