Skip to content

JedPattersonn/next-turnstile

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

3 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Next-Turnstile

A type-safe, feature-rich integration of Cloudflare Turnstile for Next.js applications. This package provides both client and server-side components for seamless CAPTCHA integration.

npm version License: MIT

Features

  • πŸ”’ Type-safe: Full TypeScript support
  • 🎨 Customizable: Extensive styling and behavior options
  • πŸ§ͺ Sandbox Mode: Built-in support for development testing
  • ⚑ Server Validation: Easy token verification
  • πŸ“± Responsive: Works across all device sizes
  • πŸ”„ Auto-reload: Configurable token refresh
  • πŸŒ™ Theme Support: Light, dark, and auto themes
  • 🌐 i18n Ready: Multiple language support

Installation

# npm
npm install next-turnstile

# yarn
yarn add next-turnstile

# pnpm
pnpm add next-turnstile

# bun
bun add next-turnstile

Quick Start

Client-Side Usage

import { Turnstile } from "next-turnstile";

function MyForm() {
  const handleVerify = (token: string) => {
    // Handle the verification token
    console.log("Verification successful:", token);
  };

  return (
    <Turnstile siteKey="your-site-key" onVerify={handleVerify} theme="light" />
  );
}

Server-Side Validation

import { validateTurnstileToken } from "next-turnstile";

async function validateToken(token: string) {
  try {
    const result = await validateTurnstileToken({
      token,
      secretKey: process.env.TURNSTILE_SECRET_KEY,
    });

    if (result.success) {
      // Token is valid
      return true;
    }
  } catch (error) {
    console.error("Validation failed:", error);
  }
  return false;
}

API Reference

Turnstile Component Props

Prop Type Default Description
siteKey string Required Your Cloudflare Turnstile site key
onVerify (token: string) => void - Callback when verification succeeds
onError (error: unknown) => void - Callback when an error occurs
onExpire () => void - Callback when the token expires
onLoad () => void - Callback when the widget loads
theme 'light' | 'dark' | 'auto' 'auto' Widget theme
size 'normal' | 'compact' 'normal' Widget size
appearance 'always' | 'execute' | 'interaction-only' 'always' When to show the widget
retry 'auto' | 'never' 'auto' Retry behavior on failure
retryInterval number 8000 Milliseconds between retries
refreshExpired 'auto' | 'manual' | 'never' 'auto' Token refresh behavior
language string - Widget language code
id string 'turnstile-widget' Container element ID
className string - Additional CSS classes
sandbox boolean false Enable sandbox mode

Server Validation Options

Option Type Required Description
token string Yes The token from the client
secretKey string Yes Your Turnstile secret key
remoteip string No User's IP address
idempotencyKey string No Unique request identifier
sandbox boolean No Enable sandbox mode

Advanced Usage

With Form Submission

import { Turnstile } from "next-turnstile";

export default function Form() {
  const [token, setToken] = useState<string>();

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!token) return;

    const response = await fetch("/api/submit", {
      method: "POST",
      body: JSON.stringify({ token }),
      headers: { "Content-Type": "application/json" },
    });

    // Handle response...
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="email" required />
      <Turnstile
        siteKey={process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY!}
        onVerify={setToken}
      />
      <button type="submit" disabled={!token}>
        Submit
      </button>
    </form>
  );
}

Server Action Validation

import { validateTurnstileToken } from "next-turnstile";

async function submitForm(formData: FormData) {
  "use server";

  const token = formData.get("cf-turnstile-response");
  if (!token || typeof token !== "string") {
    return { error: "No token provided" };
  }

  const result = await validateTurnstileToken({
    token,
    secretKey: process.env.TURNSTILE_SECRET_KEY!,
  });

  if (!result.success) {
    return { error: "Invalid token" };
  }

  // Process form submission...
}

Development Mode

During development, you can use sandbox mode to test without real credentials:

<Turnstile
  siteKey="1x00000000000000000000AA"
  sandbox={process.env.NODE_ENV === "development"}
  onVerify={handleVerify}
/>

Dark Mode Support

<Turnstile
  siteKey={process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY!}
  theme="dark"
  onVerify={handleVerify}
/>

With Custom Styling

<Turnstile
  siteKey={process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY!}
  className="my-turnstile-widget"
  onVerify={handleVerify}
/>

<style>
  .my-turnstile-widget {
    margin: 1rem 0;
    /* Note: Internal widget styling is limited by Turnstile */
  }
</style>

Development and Contributing

  1. Clone the repository
  2. Install dependencies:
    pnpm install
  3. Start development:
    pnpm dev

License

MIT Β© Jed Patterson

Credits

Built with ❀️ using:

About

React package for Cloudflare Turnstile

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published