### Install nextjs-turnstile Source: https://github.com/davodm/nextjs-turnstile/blob/main/README.md Install the package using npm. This is the first step to integrate Turnstile into your Next.js project. ```bash npm install nextjs-turnstile ``` -------------------------------- ### Client Utility: Load Turnstile Script Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/ANALYSIS_SUMMARY.txt Example of asynchronously loading the Turnstile script. This is often done once at the application level. ```javascript import { loadTurnstileScript, isTurnstileLoaded } from 'nextjs-turnstile'; async function initializeTurnstile() { if (!isTurnstileLoaded()) { try { await loadTurnstileScript(); console.log('Turnstile script loaded successfully.'); } catch (error) { console.error('Failed to load Turnstile script:', error); } } else { console.log('Turnstile script already loaded.'); } } // Call this function when your app initializes // initializeTurnstile(); ``` -------------------------------- ### Turnstile Component Example Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/ANALYSIS_SUMMARY.txt Example of how to integrate the Turnstile component into a Next.js form. Includes handling the token on success. ```jsx import Turnstile from 'nextjs-turnstile'; function MyForm() { const handleSubmit = async (event) => { event.preventDefault(); const formData = new FormData(event.currentTarget); const token = formData.get('cf-turnstile-response'); // Verify token on the server const response = await fetch('/api/verify-turnstile', { method: 'POST', body: JSON.stringify({ token }), }); if (response.ok) { alert('Form submitted successfully!'); } else { alert('CAPTCHA verification failed.'); } }; return (
{/* Other form fields */} { console.log('Turnstile token received:', token); }} /> ); } ``` -------------------------------- ### Client Utility: Execute Turnstile Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/ANALYSIS_SUMMARY.txt Example of programmatically executing the Turnstile challenge using its reference. This can be used to trigger verification on demand. ```javascript import { executeTurnstile, TurnstileRef } from 'nextjs-turnstile'; // Assuming you have a ref to the Turnstile component: // const turnstileRef = React.useRef(null); // To execute the widget: // executeTurnstile(turnstileRef.current); ``` -------------------------------- ### Deferred Turnstile Execution Example Source: https://github.com/davodm/nextjs-turnstile/blob/main/README.md This example demonstrates how to defer the Turnstile challenge execution until a user clicks the submit button. The form submission is then handled asynchronously after a token is received. ```tsx function DeferredForm() { const turnstileRef = useRef(null); const [token, setToken] = useState(null); const handleSubmit = async () => { // Start the challenge turnstileRef.current?.execute(); // Wait for token via onSuccess callback // The form will submit once token is set }; useEffect(() => { if (token) { // Token received, submit the form submitForm(token); } }, [token]); return (
); } ``` -------------------------------- ### Server-Side Verification API Route Example Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/ANALYSIS_SUMMARY.txt Example of a Next.js API route to handle Turnstile token verification. It uses the verifyTurnstile utility function. ```typescript import type { NextApiRequest, NextApiResponse } from 'next'; import { verifyTurnstile } from 'nextjs-turnstile/server'; export default async function handler( req: NextApiRequest, res: NextApiResponse ) { if (req.method === 'POST') { const { token } = req.body; if (!token) { return res.status(400).json({ success: false, message: 'Token is required' }); } try { const isVerified = await verifyTurnstile(token, { secretKey: process.env.CLOUDFLARE_SECRET_KEY, }); if (isVerified) { res.status(200).json({ success: true, message: 'CAPTCHA verified successfully' }); } else { res.status(400).json({ success: false, message: 'CAPTCHA verification failed' }); } } catch (error) { console.error('Turnstile verification error:', error); res.status(500).json({ success: false, message: 'Internal server error' }); } } else { res.setHeader('Allow', ['POST']); res.status(405).end(`Method ${req.method} Not Allowed`); } } ``` -------------------------------- ### VerifyTurnstile Example Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/types.md Demonstrates how to call `verifyTurnstile()` with custom options for secret key, action, hostname, and timeout. Ensure the secret key is securely loaded from environment variables. ```typescript await verifyTurnstile(token, { secretKey: process.env.TURNSTILE_SECRET_KEY, action: "contact_form", hostname: "example.com", timeout: 5000, }); ``` -------------------------------- ### Minimal Turnstile Form Example Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/INDEX.md A basic Next.js client component demonstrating how to integrate the Turnstile component into a form and handle token submission. ```tsx "use client"; import { Turnstile } from "nextjs-turnstile"; import { useState } from "react"; export default function Form() { const [token, setToken] = useState(null); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!token) return; const res = await fetch("/api/verify", { method: "POST", body: JSON.stringify({ token }), }); if (res.ok) { console.log("Success!"); } }; return (
); } ``` -------------------------------- ### WidgetRef Usage Examples Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/types.md Demonstrates how to use WidgetRef with client utility functions like resetTurnstile, accepting string IDs, numeric IDs, or DOM elements. ```typescript resetTurnstile("widget-0"); resetTurnstile(0); resetTurnstile(document.querySelector('#my-widget')); ``` -------------------------------- ### Complete Turnstile Widget Initialization and Usage Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/api-reference/Client-Utilities.md An example showing how to load the Turnstile script, render a widget with a site key and callback, and handle form submission with token validation and retrieval. ```javascript import { loadTurnstileScript, isTurnstileLoaded, renderTurnstile, getTurnstileResponse, resetTurnstile, isTokenExpired, } from "nextjs-turnstile"; async function initWidget() { // Load script await loadTurnstileScript(); // Verify it's loaded if (!isTurnstileLoaded()) { console.error("Turnstile failed to load"); return; } // Render widget const widgetId = await renderTurnstile('#my-widget', { sitekey: 'your-site-key', callback: (token) => console.log('Success:', token), }); if (!widgetId) { console.error("Widget render failed"); return; } // Use the widget const handleSubmit = () => { if (isTokenExpired(widgetId)) { alert("CAPTCHA expired. Resetting..."); resetTurnstile(widgetId); return; } const token = getTurnstileResponse(widgetId); if (token) { console.log("Submitting with token:", token); // Submit form } }; return { widgetId, handleSubmit }; } ``` -------------------------------- ### Client Utility: Get Turnstile Response Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/ANALYSIS_SUMMARY.txt Example of retrieving the Turnstile token from a widget using its reference. Returns the token or null if unavailable. ```javascript import { getTurnstileResponse, TurnstileRef } from 'nextjs-turnstile'; // Assuming you have a ref to the Turnstile component: // const turnstileRef = React.useRef(null); // To get the response token: // const token = getTurnstileResponse(turnstileRef.current); // console.log('Current token:', token); ``` -------------------------------- ### Client Utility: Render Turnstile Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/ANALYSIS_SUMMARY.txt Example of manually rendering a Turnstile widget into a specific DOM element. Returns the widget ID upon success. ```javascript import { renderTurnstile } from 'nextjs-turnstile'; async function setupTurnstileWidget() { const containerElement = document.getElementById('turnstile-container'); if (containerElement) { try { const widgetId = await renderTurnstile(containerElement, { siteKey: 'YOUR_CLOUDFLARE_SITE_KEY', theme: 'dark', }); console.log('Turnstile widget rendered with ID:', widgetId); } catch (error) { console.error('Failed to render Turnstile widget:', error); } } } // Call this function after the DOM is ready // setupTurnstileWidget(); ``` -------------------------------- ### Render Turnstile Widget with Site Key Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/configuration.md Example of rendering the Turnstile component. It automatically uses the NEXT_PUBLIC_TURNSTILE_SITE_KEY environment variable if available, or accepts an explicit siteKey prop. ```tsx ``` ```tsx // Or override with prop ``` -------------------------------- ### Client Utility: Reset Turnstile Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/ANALYSIS_SUMMARY.txt Example of resetting a Turnstile widget programmatically using its reference. This is useful for clearing a previous response. ```javascript import { resetTurnstile, TurnstileRef } from 'nextjs-turnstile'; // Assuming you have a ref to the Turnstile component: // const turnstileRef = React.useRef(null); // To reset the widget: // resetTurnstile(turnstileRef.current); ``` -------------------------------- ### Minimal Turnstile API Route for Verification Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/INDEX.md An example Next.js API route handler for verifying the Turnstile token received from the client. ```typescript import { verifyTurnstile } from "nextjs-turnstile"; export async function POST(req: Request) { const { token } = await req.json(); const ok = await verifyTurnstile(token); return Response.json({ success: ok }, { status: ok ? 200 : 400 }); } ``` -------------------------------- ### Reset Turnstile Widget Examples Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/api-reference/Client-Utilities.md Demonstrates how to reset a Turnstile widget using different reference types: string ID, number ID, or DOM element. ```javascript // By ID resetTurnstile('widget-0'); ``` ```javascript // By number resetTurnstile(0); ``` ```javascript // By DOM element resetTurnstile(document.getElementById('my-widget')); ``` ```javascript // By querySelector (if supported) resetTurnstile(document.querySelector('#my-widget')); ``` -------------------------------- ### Standard Turnstile Form Configuration Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/configuration.md This snippet shows the basic setup for the Turnstile component, utilizing default configurations for most behaviors. It's recommended for most standard form integrations. ```tsx console.error("Turnstile error")} /> ``` -------------------------------- ### Turnstile Component with Callbacks Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/api-reference/Turnstile-Component.md Example demonstrating how to use Turnstile callbacks for handling successful responses, errors, and token expiration. The `onSuccess` callback receives the verification token. ```tsx import Turnstile from 'nextjs-turnstile'; function MyForm() { const handleSuccess = (token: string) => { console.log('Turnstile Success:', token); // Submit the token to your backend for verification }; const handleError = (errorCode?: string) => { console.error('Turnstile Error:', errorCode); // Handle error, e.g., show a message to the user }; const handleExpire = () => { console.log('Turnstile Token Expired'); // Handle token expiration, e.g., prompt user to retry }; return (
{/* ... other form fields */} ); } ``` -------------------------------- ### Turnstile Component with Customization Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/api-reference/Turnstile-Component.md Example showing how to customize the Turnstile widget's appearance and behavior using various props like `theme`, `size`, `appearance`, and `language`. ```tsx import Turnstile from 'nextjs-turnstile'; function MyForm() { return (
{/* ... other form fields */} ); } ``` -------------------------------- ### Verify Turnstile Token on Server (App Router) Source: https://github.com/davodm/nextjs-turnstile/blob/main/README.md Implement server-side verification of the Turnstile token using the `verifyTurnstile` utility. This example demonstrates how to handle a POST request, extract the token, verify it, and respond accordingly. ```ts // app/api/contact/route.ts (App Router) import { verifyTurnstile } from "nextjs-turnstile"; export async function POST(request: Request) { const { token } = await request.json(); const isValid = await verifyTurnstile(token); if (!isValid) { return Response.json( { error: "CAPTCHA verification failed" }, { status: 400 } ); } // Token is valid, continue with your logic... return Response.json({ success: true }); } ``` -------------------------------- ### Execute Turnstile Challenge Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/api-reference/Turnstile-Component.md Starts the Turnstile challenge imperatively. This method only works when the `execution` prop is set to "execute". It is ignored if `execution` is set to "render". ```typescript // Later, trigger the challenge: ref.current?.execute(); ``` -------------------------------- ### executeTurnstile Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/api-reference/Client-Utilities.md Executes the challenge for a widget configured with `execution="execute"` mode. This function starts the Turnstile challenge and is typically called in response to a user action, like a button click. It does nothing if called on a widget configured for `execution="render"`. ```APIDOC ## executeTurnstile ### Description Executes the challenge for a widget with `execution="execute"` mode. Starts the challenge and is typically called in response to a user action. Does nothing if called on a widget with `execution="render"`. ### Method ```ts function executeTurnstile(widgetRef: WidgetRef): void ``` ### Parameters #### Path Parameters - **widgetRef** (`string | number | HTMLElement`) - Required - Widget ID, element, or selector. ### Request Example ```ts import { executeTurnstile } from "nextjs-turnstile"; executeTurnstile('widget-123'); ``` ``` -------------------------------- ### Imperative Control with Turnstile Ref Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/api-reference/Turnstile-Component.md Demonstrates how to control the Turnstile component imperatively using a ref. Allows resetting the CAPTCHA or getting the response token on demand. Requires the 'use client' directive. ```tsx "use client"; import { Turnstile, TurnstileRef } from "nextjs-turnstile"; import { useRef, useState } from "react"; export default function DeferredForm() { const turnstileRef = useRef(null); const [token, setToken] = useState(null); const handleReset = () => { turnstileRef.current?.reset(); setToken(null); }; const handleSubmit = () => { const currentToken = turnstileRef.current?.getResponse(); if (currentToken) { console.log("Token:", currentToken); // Submit to server } }; return (
); } ``` -------------------------------- ### Render Turnstile Widget (Error Handling) Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/api-reference/Client-Utilities.md This example shows how to handle potential errors during the rendering of a Turnstile widget using a try-catch block. It logs success or failure messages to the console based on the outcome of the `renderTurnstile` call. ```typescript try { const widgetId = await renderTurnstile('#widget', { sitekey: 'your-site-key', }); if (!widgetId) { console.error("Widget creation failed"); } else { console.log("Widget created:", widgetId); } } catch (e) { console.error("Render error:", e); } ``` -------------------------------- ### Turnstile Component with Imperative Control Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/api-reference/Turnstile-Component.md Demonstrates using `useRef` to get a reference to the Turnstile component for imperative control, such as executing the challenge manually. The `execution` prop must be set to 'execute'. ```tsx import Turnstile, { TurnstileRef } from 'nextjs-turnstile'; import { useRef } from 'react'; function MyForm() { const turnstileRef = useRef(null); const handleSubmit = async () => { if (turnstileRef.current) { // Manually execute the Turnstile challenge await turnstileRef.current.execute(); // Now you can submit the form, the token will be available } }; return (
{ e.preventDefault(); handleSubmit(); }}> {/* ... other form fields */} ); } ``` -------------------------------- ### Invisible Turnstile Widget with Deferred Execution Source: https://github.com/davodm/nextjs-turnstile/blob/main/README.md This example shows how to defer the Turnstile challenge execution until the user submits the form. It uses a ref to manually trigger the challenge with `turnstileRef.current.execute()`. ```tsx function InvisibleDeferredForm() { const turnstileRef = useRef(null); const [token, setToken] = useState(null); const handleSubmit = async () => { if (!turnstileRef.current?.isReady()) return; turnstileRef.current.execute(); }; useEffect(() => { if (token) { // Token received — submit form fetch("/api/submit", { method: "POST", headers: { "cf-turnstile-response": token }, body: JSON.stringify({ /* form data */ }), }); } }, [token]); return (
{/* Your form fields */} ); } ``` -------------------------------- ### Render Turnstile Widget (Basic) Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/api-reference/Client-Utilities.md This is a low-level function to directly render a Turnstile widget using the Cloudflare API. It's recommended to use the React component for most cases. This example shows basic usage with a container selector and sitekey. ```typescript import { renderTurnstile } from "nextjs-turnstile"; // Basic usage const widgetId = await renderTurnstile('#my-container', { sitekey: 'your-site-key', callback: (token) => console.log('Token:', token), }); if (!widgetId) { console.error("Widget render failed"); } ``` -------------------------------- ### Deferred Execution Pattern with Turnstile Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/api-reference/Client-Utilities.md Demonstrates a deferred execution pattern where the Turnstile challenge is initiated programmatically and the response is handled via an onSuccess callback. This pattern is useful for forms where the challenge should not start until a specific user interaction. ```tsx "use client"; import { executeTurnstile, getTurnstileResponse } from "nextjs-turnstile"; import { useState } from "react"; export default function DeferredForm() { const [token, setToken] = useState(null); const handleSubmit = () => { // Start the challenge executeTurnstile('my-widget'); // Listen for token via onSuccess callback }; const handlePostSolve = () => { const token = getTurnstileResponse('my-widget'); if (token) { setToken(token); // Submit form with token } }; return (
); } ``` -------------------------------- ### Verify Turnstile Token Server-Side Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/configuration.md Example of server-side token verification using the verifyTurnstile function. It automatically uses the TURNSTILE_SECRET_KEY environment variable unless a custom secretKey is provided. ```ts // Automatically used by verifyTurnstile if not overridden const isValid = await verifyTurnstile(token); ``` ```ts // Or override const isValid = await verifyTurnstile(token, { secretKey: process.env.MY_CUSTOM_SECRET_KEY, }); ``` -------------------------------- ### Imperative API Methods Source: https://github.com/davodm/nextjs-turnstile/blob/main/README.md Provides programmatic control over the Turnstile widget using a ref. Methods include resetting the widget, removing it, getting the response token, executing the challenge, checking readiness, and retrieving the widget ID. ```APIDOC ## Imperative API (Ref) Use a ref to control the widget programmatically. ### Ref Methods | Method | Description | |--------|-------------| | `reset()` | Reset the widget for a new challenge | | `remove()` | Remove the widget from the page | | `getResponse()` | Get the current token (or `null`) | | `execute()` | Start the challenge (when `execution="execute"`) | | `isReady()` | Check if the widget is ready | | `getWidgetId()` | Get the internal Cloudflare widget ID | ``` -------------------------------- ### File Structure Overview Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/INDEX.md Illustrates the directory structure of the Next.js Turnstile library, showing the main entry point, components, and utility files. ```tree src/ ├── index.ts # Main entry point (re-exports) ├── components/ │ └── Turnstile.tsx # React component (260+ lines) └── utils/ ├── index.ts # Client utilities └── verifyTurnstile.ts # Server verification ``` -------------------------------- ### Server Verification with All Options Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/configuration.md Configure all available verification options simultaneously for comprehensive control. ```typescript const isValid = await verifyTurnstile(token, { secretKey: process.env.TURNSTILE_SECRET_KEY, ip: getUserIp(request), headers: request.headers, action: "checkout", hostname: "shop.example.com", timeout: 5000, }); ``` -------------------------------- ### Client Utility: Is Token Expired Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/ANALYSIS_SUMMARY.txt Example of checking if the Turnstile token for a widget has expired using its reference. Returns a boolean. ```javascript import { isTokenExpired, TurnstileRef } from 'nextjs-turnstile'; // Assuming you have a ref to the Turnstile component: // const turnstileRef = React.useRef(null); // To check if the token is expired: // const expired = isTokenExpired(turnstileRef.current); // console.log('Is token expired?', expired); ``` -------------------------------- ### Client Utility: Remove Turnstile Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/ANALYSIS_SUMMARY.txt Example of removing a Turnstile widget from the DOM using its reference. This cleans up resources associated with the widget. ```javascript import { removeTurnstile, TurnstileRef } from 'nextjs-turnstile'; // Assuming you have a ref to the Turnstile component: // const turnstileRef = React.useRef(null); // To remove the widget: // removeTurnstile(turnstileRef.current); ``` -------------------------------- ### VerifyOptions Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/types.md Options for the `verifyTurnstile()` function. These allow customization of the verification process, such as overriding the secret key, specifying the visitor's IP address, providing request headers, setting an expected action, validating the hostname, and configuring the fetch timeout. ```APIDOC ## VerifyOptions ### Description Options for the `verifyTurnstile()` function. These allow customization of the verification process, such as overriding the secret key, specifying the visitor's IP address, providing request headers, setting an expected action, validating the hostname, and configuring the fetch timeout. ### Properties - **secretKey** (string) - Optional - Override the secret key. Defaults to `TURNSTILE_SECRET_KEY`. - **ip** (string) - Optional - Visitor IP address. Defaults to auto-detected. - **headers** (`Record | Headers`) - Optional - Headers for IP detection (Pages Router). - **action** (string) - Optional - Expected action value for validation. - **hostname** (string) - Optional - Expected hostname for validation. - **timeout** (number) - Optional - Fetch timeout in milliseconds. Defaults to `10000`. ### Example ```ts await verifyTurnstile(token, { secretKey: process.env.TURNSTILE_SECRET_KEY, action: "contact_form", hostname: "example.com", timeout: 5000, }); ``` ``` -------------------------------- ### Get Turnstile Token After Loading Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/api-reference/Client-Utilities.md Once `isTurnstileLoaded` returns true, you can retrieve the Turnstile token using `window.turnstile.getResponse`. Ensure the widget ID is correct. ```typescript if (isTurnstileLoaded()) { const token = window.turnstile.getResponse(widgetId); console.log("Token:", token); } else { console.warn("Turnstile not available"); } ``` -------------------------------- ### Basic Server Verification (App Router) Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/configuration.md Use this for automatic IP detection with default timeout and secret key settings. ```typescript // Automatic IP detection, default timeout, default secret const isValid = await verifyTurnstile(token); ``` -------------------------------- ### Handling TurnstileError in TypeScript Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/errors.md Example of how to catch and handle TurnstileError exceptions in your server-side code. It demonstrates checking for specific error codes like 'timeout-or-duplicate'. ```typescript try { await verifyTurnstile(token); } catch (e) { if (e instanceof TurnstileError) { console.error("Error codes:", e.errorCodes); console.error("Message:", e.message); if (e.errorCodes.includes("timeout-or-duplicate")) { // Token was already used or expired } } else { // Network error or other exception console.error("Unexpected error:", e); } } ``` -------------------------------- ### Import Client-Side Utilities Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/INDEX.md Import various utility functions for managing the Turnstile script and widget on the client side. ```typescript import { loadTurnstileScript, isTurnstileLoaded, resetTurnstile, getTurnstileResponse, executeTurnstile, isTokenExpired, removeTurnstile, renderTurnstile, type WidgetRef, } from "nextjs-turnstile"; ``` -------------------------------- ### Invisible Turnstile Mode Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/api-reference/Turnstile-Component.md Example of using Turnstile in invisible mode, where the widget is not displayed to the user. The CAPTCHA is completed in the background. Requires the 'use client' directive. ```tsx "use client"; import { Turnstile } from "nextjs-turnstile"; import { useState } from "react"; export default function InvisibleForm() { const [token, setToken] = useState(null); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!token) return; await fetch("/api/submit", { method: "POST", headers: { "cf-turnstile-response": token }, body: JSON.stringify({ /* form data */ }), }); }; return (
{/* The widget is completely invisible */} setToken(null)} feedbackEnabled={false} /> ); } ``` -------------------------------- ### Handling Action and Hostname Mismatch Errors Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/errors.md Verify that the provided token matches the expected action and hostname by passing them as options to `verifyTurnstile`. This snippet demonstrates handling 'action-mismatch' and 'hostname-mismatch' errors. ```typescript import { verifyTurnstile, TurnstileError } from "nextjs-turnstile"; export async function POST(request: Request) { const { token } = await request.json(); try { await verifyTurnstile(token, { action: "contact_form", // Token must have this action hostname: "example.com", // Token must be from this domain }); } catch (e) { if (e instanceof TurnstileError) { if (e.errorCodes.includes("action-mismatch")) { // Token is from a different form/action return Response.json( { error: "Token is from a different action" }, { status: 400 } ); } if (e.errorCodes.includes("hostname-mismatch")) { // Token is from a different domain (CSRF attempt?) console.warn("Hostname mismatch - possible CSRF attempt"); return Response.json( { error: "Token is not valid for this domain" }, { status: 403 } ); } } throw e; } return Response.json({ success: true }); } ``` -------------------------------- ### Get Turnstile Response Token Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/api-reference/Turnstile-Component.md Retrieves the current verification token from the Turnstile widget. Returns null if the widget has not been solved yet. Useful for server-side verification. ```typescript const token = ref.current?.getResponse(); if (token) { await verifyTurnstile(token); } ``` -------------------------------- ### Render Turnstile Widget (Full Options) Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/api-reference/Client-Utilities.md Demonstrates rendering a Turnstile widget with a comprehensive set of options, including theme, size, and various callback functions for success, error, and expiration events. The container is specified as an HTMLElement. ```typescript const widgetId = await renderTurnstile( document.getElementById('captcha'), { sitekey: 'your-site-key', theme: 'dark', size: 'compact', callback: (token) => handleSuccess(token), 'error-callback': (code) => handleError(code), 'expired-callback': () => handleExpire(), } ); ``` -------------------------------- ### Client Utilities for Turnstile Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/types.md Demonstrates the usage of client utility functions like resetTurnstile and getTurnstileResponse with a WidgetRef. ```typescript import { resetTurnstile, getTurnstileResponse, WidgetRef, } from "nextjs-turnstile"; const widgetRef: WidgetRef = "widget-0"; resetTurnstile(widgetRef); const token = getTurnstileResponse(widgetRef); ``` -------------------------------- ### Get Turnstile Response Utility Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/ANALYSIS_SUMMARY.txt Retrieves the current Turnstile token from the widget associated with the provided widget reference. Returns the token string or null if no token is available. ```typescript declare function getTurnstileResponse(widgetRef: WidgetRef): string | null; ``` -------------------------------- ### Get Client IP Address Function Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/ANALYSIS_SUMMARY.txt Asynchronously retrieves the client's IP address from request headers. Useful for server-side logic that requires IP information. ```typescript declare function getClientIp(initHeaders?: HeadersInit): Promise; ``` -------------------------------- ### TurnstileAppearance Type Definition Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/types.md Controls the visibility of the Turnstile widget. 'always' keeps it visible, 'execute' shows it when a challenge starts, and 'interaction-only' displays it only when user interaction is needed. ```typescript type TurnstileAppearance = "always" | "execute" | "interaction-only" ``` -------------------------------- ### Server Verification with Action Validation Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/configuration.md Ensure the token originates from the expected form or action. ```typescript // Ensure token is from the expected form/action const isValid = await verifyTurnstile(token, { action: "contact_form", }); ``` -------------------------------- ### Get Client IP Address Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/api-reference/verifyTurnstile.md Utility function to extract the client IP address from request context. Tries next/headers, falls back to provided headers, or returns undefined. ```typescript async function getClientIp( initHeaders?: Record | Headers ): Promise ``` ```typescript import { getClientIp } from "nextjs-turnstile"; // In App Router (automatic) const ip = await getClientIp(); // In Pages Router (with headers) const ip = await getClientIp(req.headers); ``` -------------------------------- ### Configure Environment Variables Source: https://github.com/davodm/nextjs-turnstile/blob/main/README.md Set up your Cloudflare Turnstile site key and secret key as environment variables in your .env.local file. These keys are essential for both client-side rendering and server-side verification. ```env # .env.local NEXT_PUBLIC_TURNSTILE_SITE_KEY=your_site_key_here TURNSTILE_SECRET_KEY=your_secret_key_here ``` -------------------------------- ### Poll Token Expiration Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/api-reference/Client-Utilities.md This example demonstrates how to periodically check if a Turnstile token has expired using `isTokenExpired` and reset it if necessary. It sets up an interval to check the token status every second. ```typescript const checkTokenStatus = (widgetId: string) => { const interval = setInterval(() => { if (isTokenExpired(widgetId)) { console.log("Token expired, resetting..."); resetTurnstile(widgetId); clearInterval(interval); } }, 1000); // Check every second }; ``` -------------------------------- ### Import Server-Side Verification Functions Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/INDEX.md Import functions for server-side verification of Turnstile tokens. ```typescript import { verifyTurnstile, TurnstileError } from "nextjs-turnstile"; ``` -------------------------------- ### VerifyOptions Interface Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/configuration.md Defines the available options for server-side Turnstile verification. ```typescript interface VerifyOptions { secretKey?: string; ip?: string; headers?: Record | Headers; action?: string; hostname?: string; timeout?: number; } ``` -------------------------------- ### Get Turnstile Widget ID Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/api-reference/Turnstile-Component.md Retrieves the internal widget ID assigned by Cloudflare to the Turnstile instance. This is useful for advanced debugging or integration scenarios. Returns undefined if the widget has not yet been rendered. ```typescript const widgetId = ref.current?.getWidgetId(); console.log("Widget ID:", widgetId); ``` -------------------------------- ### Imperative Turnstile Control with TurnstileRef Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/types.md Provides an imperative handle for controlling the Turnstile widget using `useRef`. Allows for actions like resetting, removing, getting responses, executing challenges, and checking readiness. ```typescript interface TurnstileRef { reset: () => void; remove: () => void; getResponse: () => string | null; execute: () => void; isReady: () => boolean; getWidgetId: () => string | undefined; } ``` ```tsx const ref = useRef(null); // In handlers ref.current?.reset(); const token = ref.current?.getResponse(); const ready = ref.current?.isReady(); ref.current?.execute(); ``` -------------------------------- ### Server-Side Turnstile Verification with Advanced Options Source: https://github.com/davodm/nextjs-turnstile/blob/main/README.md Configure server-side Turnstile verification with advanced options to override the secret key, specify the user's IP address, provide request headers, set an action, match the hostname, or adjust the fetch timeout. ```ts const ok = await verifyTurnstile(token, { secretKey: "custom-secret-key", // Override secret key ip: "1.2.3.4", // User's IP (auto-detected if omitted) headers: request.headers, // For IP detection in Pages Router action: "login", // Reject if action doesn't match hostname: "example.com", // Reject if hostname doesn't match timeout: 5000, // Fetch timeout in ms (default: 10 000) }); ``` -------------------------------- ### Client Utilities Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/00-START-HERE.md Utility functions for interacting with the Turnstile script and widget on the client-side. ```APIDOC ## Client Utilities ### Description These utility functions provide direct access to the Turnstile client-side API for managing the script loading, widget state, and token retrieval. ### Functions - **loadTurnstileScript()**: Loads the Turnstile JavaScript script into the DOM if it's not already loaded. - **isTurnstileLoaded()**: Returns a boolean indicating whether the Turnstile script is currently loaded and ready. - **resetTurnstile(widgetRef)**: Resets the Turnstile widget associated with the provided `widgetRef`. This is useful for re-challenging the user. - **getTurnstileResponse(widgetRef)**: Retrieves the current Turnstile token from the widget associated with `widgetRef`. Returns `null` if no token is available. - **executeTurnstile(widgetRef)**: Programmatically triggers the Turnstile challenge for the widget associated with `widgetRef`. - **isTokenExpired(widgetRef)**: Checks if the Turnstile token for the widget associated with `widgetRef` has expired. Returns `true` if expired, `false` otherwise. ``` -------------------------------- ### isTurnstileLoaded Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/api-reference/Client-Utilities.md Checks if the Turnstile script has been loaded and is ready to use. This is useful to ensure that the `window.turnstile` object is available before attempting to render or interact with widgets. ```APIDOC ## isTurnstileLoaded ### Description Checks if the Turnstile script has been loaded and is ready to use. ### Signature ```ts function isTurnstileLoaded(): boolean ``` ### Returns `true` if `window.turnstile` is available, `false` otherwise. ### Example ```ts import { isTurnstileLoaded } from "nextjs-turnstile"; if (isTurnstileLoaded()) { window.turnstile.render('#widget', { sitekey: 'xxx' }); } else { console.log("Script not loaded yet"); } ``` ``` -------------------------------- ### Get Turnstile Verification Token Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/api-reference/Client-Utilities.md Use `getTurnstileResponse` to retrieve the current verification token from a Turnstile widget. This function returns the token as a string if the widget is solved, or `null` if it's not yet solved or doesn't exist. It's commonly used within form submission handlers. ```typescript import { getTurnstileResponse } from "nextjs-turnstile"; // Get token by widget ID const token = getTurnstileResponse('widget-123'); if (token) { console.log("Token ready for verification:", token); // Send to server for verification } else { console.log("Widget not solved yet or doesn't exist"); } ``` ```typescript const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); const token = getTurnstileResponse('#my-turnstile'); if (!token) { alert("Please complete the CAPTCHA"); return; } const response = await fetch("/api/submit", { method: "POST", body: JSON.stringify({ token, data: /* form data */ }), }); if (response.ok) { resetTurnstile('#my-turnstile'); } }; ``` -------------------------------- ### Client-Side Utilities Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/INDEX.md Low-level functions for controlling the Turnstile widget on the client-side, including script loading, widget rendering, and token retrieval. Useful for advanced scenarios and imperative control. ```APIDOC ## Client-Side Utilities ### Description Provides a set of low-level JavaScript functions for interacting with the Cloudflare Turnstile widget directly. These utilities are useful for advanced use cases, such as managing multiple widgets, controlling widget behavior imperatively, or integrating with custom UI elements. They are implemented to be safe for Server-Side Rendering (SSR) environments. ### Functions #### `loadTurnstileScript(options?: LoadScriptOptions): Promise` Loads the Cloudflare Turnstile JavaScript SDK. It ensures the script is loaded only once. **Parameters:** - `options` (object) - Optional. Configuration for loading the script. - `siteKey` (string) - Required if not already configured via environment variables or previous loads. Your Cloudflare Turnstile site key. - ` 100% ` (string) - Optional. The language for the Turnstile widget. - `appearance` (string) - Optional. The appearance mode of the widget ('always', 'execute', 'none'). - `execution` (string) - Optional. The execution mode ('auto', 'execute'). - `retryInterval` (number) - Optional. The interval in milliseconds to retry loading the script if it fails. - `retryDelay` (number) - Optional. The delay in milliseconds before retrying. **Returns:** - `Promise` - A promise that resolves when the script is successfully loaded. #### `renderTurnstile(elementId: string, options?: RenderOptions): Promise` Renders a Turnstile widget into a specified DOM element. **Parameters:** - `elementId` (string) - Required. The ID of the HTML element where the widget should be rendered. - `options` (object) - Optional. Configuration options for the widget rendering. - `siteKey` (string) - Required if not globally configured. Your Cloudflare Turnstile site key. - `theme` (string) - Optional. The theme of the widget ('light' or 'dark'). - `action` (string) - Optional. A custom action name for the widget. - `cData` (string) - Optional. Client-side data to be passed to the widget. - `callback` (function) - Optional. Callback for successful validation. - `'error-callback'` (function) - Optional. Callback for widget errors. - `'expired-callback'` (function) - Optional. Callback for widget expiration. - `'unsupported-callback'` (function) - Optional. Callback for unsupported widget. - `'before-interactive-callback'` (function) - Optional. Callback before widget interaction. - `'after-interactive-callback'` (function) - Optional. Callback after widget interaction. - `'too-many-requests-callback'` (function) - Optional. Callback for too many requests. - `'client-response-callback'` (function) - Optional. Callback with client response. - `language` (string) - Optional. The language of the widget. - `appearance` (string) - Optional. The appearance of the widget ('always', 'execute', 'none'). - `execution` (string) - Optional. The execution mode of the widget ('auto', 'execute'). - `retryInterval` (number) - Optional. The retry interval in milliseconds. - `retryDelay` (number) - Optional. The delay in milliseconds before retrying. - `size` (string) - Optional. The size of the widget ('normal', 'compact'). **Returns:** - `Promise` - A promise that resolves with the widget ID. #### `getTurnstileToken(elementId: string): Promise` Retrieves the Turnstile token for a widget rendered in a specific element. **Parameters:** - `elementId` (string) - Required. The ID of the HTML element containing the widget. **Returns:** - `Promise` - A promise that resolves with the token string, or `null` if the token cannot be retrieved. #### `resetTurnstile(elementId: string): Promise` Resets a specific Turnstile widget. **Parameters:** - `elementId` (string) - Required. The ID of the HTML element containing the widget to reset. **Returns:** - `Promise` - A promise that resolves when the widget is reset. #### `executeTurnstile(elementId: string): Promise` Executes a specific Turnstile widget, typically to trigger validation. **Parameters:** - `elementId` (string) - Required. The ID of the HTML element containing the widget to execute. **Returns:** - `Promise` - A promise that resolves when the widget execution is triggered. ### Example Usage ```javascript import { loadTurnstileScript, renderTurnstile, getTurnstileToken, resetTurnstile } from 'nextjs-turnstile/client'; async function initializeWidget() { await loadTurnstileScript({ siteKey: 'YOUR_SITE_KEY' }); const widgetId = await renderTurnstile('turnstile-container', { action: 'custom_action', callback: (token) => { console.log('Token received:', token); // Send token to server for verification } }); console.log('Widget rendered with ID:', widgetId); } async function getToken() { const token = await getTurnstileToken('turnstile-container'); console.log('Current token:', token); } async function resetWidget() { await resetTurnstile('turnstile-container'); console.log('Widget reset.'); } // Call initializeWidget() when your component mounts or as needed. ``` ``` -------------------------------- ### Deferred Turnstile Execution Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/configuration.md Sets up the Turnstile component for deferred execution, where the widget is hidden and the challenge only runs after an explicit call to `execute()`. This reduces initial load time and is ideal for scenarios where the widget should not be immediately visible. ```tsx // In submit handler turnstileRef.current?.execute(); ``` -------------------------------- ### Basic Verification with Boolean Check Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/errors.md Use this snippet for simple fail-fast scenarios where only a true/false outcome is needed. It performs verification and returns an error response if the token is invalid. ```typescript import { verifyTurnstile } from "nextjs-turnstile"; export async function POST(request: Request) { const { token } = await request.json(); const isValid = await verifyTurnstile(token); if (!isValid) { return Response.json( { error: "CAPTCHA verification failed" }, { status: 400 } ); } // Process the form... return Response.json({ success: true }); } ``` -------------------------------- ### Invisible Turnstile Widget with Auto-run Source: https://github.com/davodm/nextjs-turnstile/blob/main/README.md Use this pattern for invisible Turnstile widgets that automatically run the challenge when the component mounts. The token is passed to onSuccess as soon as it's available. ```tsx function InvisibleAutoForm() { const [token, setToken] = useState(null); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!token) return; await fetch("/api/submit", { method: "POST", headers: { "cf-turnstile-response": token }, body: JSON.stringify({ /* form data */ }), }); }; return (
{/* Your form fields */} setToken(null)} feedbackEnabled={false} /> ); } ``` -------------------------------- ### Client-Side Turnstile Utility Functions Source: https://github.com/davodm/nextjs-turnstile/blob/main/_autodocs/00-START-HERE.md Manage the Turnstile widget and its state using client-side utility functions. These include loading the script, checking its readiness, resetting the widget, retrieving the response token, executing the challenge, and checking token expiry. ```ts loadTurnstileScript() // Load script isTurnstileLoaded() // Check if ready resetTurnstile(widgetRef) // Reset widget getTurnstileResponse(widgetRef) // Get token executeTurnstile(widgetRef) // Execute challenge isTokenExpired(widgetRef) // Check expiry ```