1.0.4 โ€ข Published 11 months ago

@codesurvia/next-turnstile v1.0.4

Weekly downloads
-
License
MIT
Repository
-
Last release
11 months ago

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

PropTypeDefaultDescription
siteKeystringRequiredYour 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
retryIntervalnumber8000Milliseconds between retries
refreshExpired'auto' \| 'manual' \| 'never''auto'Token refresh behavior
languagestring-Widget language code
idstring'turnstile-widget'Container element ID
classNamestring-Additional CSS classes
sandboxboolean | pass | block | pass-invisible | block-invisiblefalseEnable sandbox mode

Server Validation Options

OptionTypeRequiredDescription
tokenstringYesThe token from the client
secretKeystringYesYour Turnstile secret key
remoteipstringNoUser's IP address
idempotencyKeystringNoUnique request identifier
sandboxboolean| pass | fail | errorNoEnable 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:

1.0.4

11 months ago