UNPKG

next-turnstile

Version:

Cloudflare Turnstile integration for Next.js applications

235 lines (181 loc) โ€ข 7.02 kB
# 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](https://badge.fury.io/js/next-turnstile.svg)](https://www.npmjs.com/package/next-turnstile) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/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 ```bash # 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 ```tsx 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 ```tsx 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 ```tsx 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 ```tsx 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: ```tsx <Turnstile siteKey="1x00000000000000000000AA" sandbox={process.env.NODE_ENV === "development"} onVerify={handleVerify} /> ``` ### Dark Mode Support ```tsx <Turnstile siteKey={process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY!} theme="dark" onVerify={handleVerify} /> ``` ### With Custom Styling ```tsx <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: ```bash pnpm install ``` 3. Start development: ```bash pnpm dev ``` ## License MIT ยฉ Jed Patterson ## Credits Built with โค๏ธ using: - [Next.js](https://nextjs.org) - [Cloudflare Turnstile](https://developers.cloudflare.com/turnstile) - [TypeScript](https://www.typescriptlang.org)