{"_id":"@codesurvia/next-turnstile","_rev":"2-623ed7c31b3366df4f78cc247508e14c","name":"@codesurvia/next-turnstile","dist-tags":{"latest":"1.0.4"},"versions":{"1.0.4":{"name":"@codesurvia/next-turnstile","version":"1.0.4","keywords":["nextjs","cloudflare","turnstile","captcha","react"],"license":"MIT","_id":"@codesurvia/next-turnstile@1.0.4","maintainers":[{"name":"codesurvia","email":"project@codesurvia.online"}],"dist":{"shasum":"f6cf34138ebd3cc3749456ee9ec3a4a2abf68183","tarball":"https://registry.npmjs.org/@codesurvia/next-turnstile/-/next-turnstile-1.0.4.tgz","fileCount":20,"integrity":"sha512-V4FLPmvlVkB/rqD7olzKZifz9DHdpN7CrwrkkV6WGNjYSGv02kcyYZvzn2/T/kCyz9QiCNj0x52YR5HAIWQrig==","signatures":[{"sig":"MEUCIQC/2Tz3jNFTYM6RAqZAK+HZuOvQ2z2Hel7vZbFweT2z8gIgda1oKnVCtI/fGbh/KVcQv9n2VW6vs5dQC+VlyD26Urs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":28489},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"b19ab9c8bf1c7d43b0679f92eabfb751dde08d09","scripts":{"lint":"eslint src/**/*.ts*","test":"jest","build":"tsc"},"_npmUser":{"name":"codesurvia","email":"project@codesurvia.online"},"_npmVersion":"11.4.1","description":"Cloudflare Turnstile integration for Next.js applications","directories":{},"_nodeVersion":"23.11.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.0.0","eslint":"^8.0.0","typescript":"^4.9.0","@types/react":"^18.0.0","@typescript-eslint/parser":"^5.0.0","@typescript-eslint/eslint-plugin":"^5.0.0"},"peerDependencies":{"next":">=12","react":">=16","react-dom":">=16"},"_npmOperationalInternal":{"tmp":"tmp/next-turnstile_1.0.4_1749671941087_0.8381745110456684","host":"s3://npm-registry-packages-npm-production"}}},"time":{"created":"2025-06-11T19:59:00.978Z","modified":"2025-07-18T06:01:16.144Z","1.0.4":"2025-06-11T19:59:01.274Z"},"license":"MIT","keywords":["nextjs","cloudflare","turnstile","captcha","react"],"description":"Cloudflare Turnstile integration for Next.js applications","maintainers":[{"email":"project@codesurvia.online","name":"paulus-otto-harman"}],"readme":"# Next-Turnstile\n\nA 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.\n\n[![npm version](https://badge.fury.io/js/next-turnstile.svg)](https://www.npmjs.com/package/next-turnstile)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n## Features\n\n- 🔒 **Type-safe**: Full TypeScript support\n- 🎨 **Customizable**: Extensive styling and behavior options\n- 🧪 **Sandbox Mode**: Built-in support for development testing\n- ⚡ **Server Validation**: Easy token verification\n- 📱 **Responsive**: Works across all device sizes\n- 🔄 **Auto-reload**: Configurable token refresh\n- 🌙 **Theme Support**: Light, dark, and auto themes\n- 🌐 **i18n Ready**: Multiple language support\n\n## Installation\n\n```bash\n# npm\nnpm install next-turnstile\n\n# yarn\nyarn add next-turnstile\n\n# pnpm\npnpm add next-turnstile\n\n# bun\nbun add next-turnstile\n```\n\n## Quick Start\n\n### Client-Side Usage\n\n```tsx\nimport { Turnstile } from \"next-turnstile\";\n\nfunction MyForm() {\n  const handleVerify = (token: string) => {\n    // Handle the verification token\n    console.log(\"Verification successful:\", token);\n  };\n\n  return (\n    <Turnstile siteKey=\"your-site-key\" onVerify={handleVerify} theme=\"light\" />\n  );\n}\n```\n\n### Server-Side Validation\n\n```tsx\nimport { validateTurnstileToken } from \"next-turnstile\";\n\nasync function validateToken(token: string) {\n  try {\n    const result = await validateTurnstileToken({\n      token,\n      secretKey: process.env.TURNSTILE_SECRET_KEY,\n    });\n\n    if (result.success) {\n      // Token is valid\n      return true;\n    }\n  } catch (error) {\n    console.error(\"Validation failed:\", error);\n  }\n  return false;\n}\n```\n\n## API Reference\n\n### Turnstile Component Props\n\n| Prop             | Type                                                                    | Default              | Description                         |\n|------------------|-------------------------------------------------------------------------|----------------------|-------------------------------------|\n| `siteKey`        | `string`                                                                | Required             | Your Cloudflare Turnstile site key  |\n| `onVerify`       | `(token: string) => void`                                               | -                    | Callback when verification succeeds |\n| `onError`        | `(error: unknown) => void`                                              | -                    | Callback when an error occurs       |\n| `onExpire`       | `() => void`                                                            | -                    | Callback when the token expires     |\n| `onLoad`         | `() => void`                                                            | -                    | Callback when the widget loads      |\n| `theme`          | `'light' \\| 'dark' \\| 'auto'`                                           | `'auto'`             | Widget theme                        |\n| `size`           | `'normal' \\| 'compact'`                                                 | `'normal'`           | Widget size                         |\n| `appearance`     | `'always' \\| 'execute' \\| 'interaction-only'`                           | `'always'`           | When to show the widget             |\n| `retry`          | `'auto' \\| 'never'`                                                     | `'auto'`             | Retry behavior on failure           |\n| `retryInterval`  | `number`                                                                | `8000`               | Milliseconds between retries        |\n| `refreshExpired` | `'auto' \\| 'manual' \\| 'never'`                                         | `'auto'`             | Token refresh behavior              |\n| `language`       | `string`                                                                | -                    | Widget language code                |\n| `id`             | `string`                                                                | `'turnstile-widget'` | Container element ID                |\n| `className`      | `string`                                                                | -                    | Additional CSS classes              |\n| `sandbox`        | `boolean` \\| `pass` \\| `block` \\| `pass-invisible` \\| `block-invisible` | `false`              | Enable sandbox mode                 |\n\n### Server Validation Options\n\n| Option           | Type                                    | Required | Description               |\n|------------------|-----------------------------------------|----------|---------------------------|\n| `token`          | `string`                                | Yes      | The token from the client |\n| `secretKey`      | `string`                                | Yes      | Your Turnstile secret key |\n| `remoteip`       | `string`                                | No       | User's IP address         |\n| `idempotencyKey` | `string`                                | No       | Unique request identifier |\n| `sandbox`        | `boolean`\\| `pass` \\| `fail` \\| `error` | No       | Enable sandbox mode       |\n\n## Advanced Usage\n\n### With Form Submission\n\n```tsx\nimport { Turnstile } from \"next-turnstile\";\n\nexport default function Form() {\n  const [token, setToken] = useState<string>();\n\n  const handleSubmit = async (e: React.FormEvent) => {\n    e.preventDefault();\n    if (!token) return;\n\n    const response = await fetch(\"/api/submit\", {\n      method: \"POST\",\n      body: JSON.stringify({ token }),\n      headers: { \"Content-Type\": \"application/json\" },\n    });\n\n    // Handle response...\n  };\n\n  return (\n    <form onSubmit={handleSubmit}>\n      <input type=\"email\" required />\n      <Turnstile\n        siteKey={process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY!}\n        onVerify={setToken}\n      />\n      <button type=\"submit\" disabled={!token}>\n        Submit\n      </button>\n    </form>\n  );\n}\n```\n\n### Server Action Validation\n\n```tsx\nimport { validateTurnstileToken } from \"next-turnstile\";\n\nasync function submitForm(formData: FormData) {\n  \"use server\";\n\n  const token = formData.get(\"cf-turnstile-response\");\n  if (!token || typeof token !== \"string\") {\n    return { error: \"No token provided\" };\n  }\n\n  const result = await validateTurnstileToken({\n    token,\n    secretKey: process.env.TURNSTILE_SECRET_KEY!,\n  });\n\n  if (!result.success) {\n    return { error: \"Invalid token\" };\n  }\n\n  // Process form submission...\n}\n```\n\n### Development Mode\n\nDuring development, you can use sandbox mode to test without real credentials:\n\n```tsx\n<Turnstile\n  siteKey=\"1x00000000000000000000AA\"\n  sandbox={process.env.NODE_ENV === \"development\"}\n  onVerify={handleVerify}\n/>\n```\n\n### Dark Mode Support\n\n```tsx\n<Turnstile\n  siteKey={process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY!}\n  theme=\"dark\"\n  onVerify={handleVerify}\n/>\n```\n\n### With Custom Styling\n\n```tsx\n<Turnstile\n  siteKey={process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY!}\n  className=\"my-turnstile-widget\"\n  onVerify={handleVerify}\n/>\n\n<style>\n  .my-turnstile-widget {\n    margin: 1rem 0;\n    /* Note: Internal widget styling is limited by Turnstile */\n  }\n</style>\n```\n\n## Development and Contributing\n\n1. Clone the repository\n2. Install dependencies:\n   ```bash\n   pnpm install\n   ```\n3. Start development:\n   ```bash\n   pnpm dev\n   ```\n\n## License\n\nMIT © Jed Patterson\n\n## Credits\n\nBuilt with ❤️ using:\n\n- [Next.js](https://nextjs.org)\n- [Cloudflare Turnstile](https://developers.cloudflare.com/turnstile)\n- [TypeScript](https://www.typescriptlang.org)\n","readmeFilename":"README.md"}