{"id":13810518,"url":"https://github.com/nuxt-modules/turnstile","last_synced_at":"2025-05-15T14:05:18.247Z","repository":{"id":60596679,"uuid":"544189832","full_name":"nuxt-modules/turnstile","owner":"nuxt-modules","description":"🔥 Cloudflare Turnstile integration for Nuxt","archived":false,"fork":false,"pushed_at":"2025-05-06T07:09:31.000Z","size":2960,"stargazers_count":263,"open_issues_count":13,"forks_count":18,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-05-06T08:26:08.390Z","etag":null,"topics":["captcha","cloudflare","hacktoberfest","nuxt","recaptcha","turnstile"],"latest_commit_sha":null,"homepage":"https://cloudflare.com/products/turnstile","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nuxt-modules.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":null,"code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":["danielroe"]}},"created_at":"2022-10-01T22:00:09.000Z","updated_at":"2025-05-06T07:09:33.000Z","dependencies_parsed_at":"2023-09-23T05:58:45.254Z","dependency_job_id":"436e0a33-36c7-4ec0-8848-bacd6e85fb6b","html_url":"https://github.com/nuxt-modules/turnstile","commit_stats":null,"previous_names":["danielroe/nuxt-turnstile"],"tags_count":41,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nuxt-modules%2Fturnstile","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nuxt-modules%2Fturnstile/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nuxt-modules%2Fturnstile/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nuxt-modules%2Fturnstile/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nuxt-modules","download_url":"https://codeload.github.com/nuxt-modules/turnstile/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254355334,"owners_count":22057354,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["captcha","cloudflare","hacktoberfest","nuxt","recaptcha","turnstile"],"created_at":"2024-08-04T02:00:57.536Z","updated_at":"2025-05-15T14:05:13.236Z","avatar_url":"https://github.com/nuxt-modules.png","language":"TypeScript","funding_links":["https://github.com/sponsors/danielroe"],"categories":["TypeScript"],"sub_categories":[],"readme":"# Nuxt Turnstile\n\n[![npm version][npm-version-src]][npm-version-href]\n[![npm downloads][npm-downloads-src]][npm-downloads-href]\n[![Github Actions][github-actions-src]][github-actions-href]\n[![Codecov][codecov-src]][codecov-href]\n\n\u003e [Cloudflare Turnstile](https://developers.cloudflare.com/turnstile/) integration for [Nuxt 3](https://v3.nuxtjs.org)\n\n- [✨ \u0026nbsp;Changelog](https://github.com/nuxt-modules/turnstile/blob/main/CHANGELOG.md)\n- [▶️ \u0026nbsp;Online playground](https://stackblitz.com/github/nuxt-modules/turnstile/tree/main/playground)\n\n## Features\n\n- 💪 smart verification with minimal user interaction\n- 🕵️‍♀️ privacy-focused approach\n- ✨ server validation helper for your nitro endpoints\n- ⚡️ lightweight - script only loaded when required\n\n## Installation\n\n1. First, [follow these steps](https://developers.cloudflare.com/turnstile/get-started/) to obtain a free sitekey and secret key from Cloudflare.\n\n1. Install `@nuxt/scripts` as a dependency - see [docs](https://scripts.nuxt.com/) for more info if you're interested.\n\n1. Install and add `@nuxtjs/turnstile` to your `nuxt.config`.\n\n   ```bash\n   npx nuxi@latest module add turnstile\n   ```\n\n   ```js\n   export default defineNuxtConfig({\n     modules: ['@nuxtjs/turnstile'],\n\n     turnstile: {\n       siteKey: '\u003cyour-site-key\u003e',\n     },\n\n     runtimeConfig: {\n       turnstile: {\n         // This can be overridden at runtime via the NUXT_TURNSTILE_SECRET_KEY\n         // environment variable.\n         secretKey: '',\n       },\n     },\n   })\n   ```\n\n  Alternatively, you may set `turnstile.secretKeyPath` to a path to a file containing the secret key. This will be read at build-time and will override any other explicit `secretKey` you have set.\n\n   **Tip**: At runtime you can override site and secret keys with the `NUXT_TURNSTILE_SECRET_KEY` and `NUXT_PUBLIC_TURNSTILE_SITE_KEY` environment variables.\n\n## Usage\n\nTo use Turnstile, you will likely want to:\n\n- Use the `\u003cNuxtTurnstile\u003e` component in your app (for example to build a contact form)\n- Verify the token on your server, when you are processing an API request or a form submission (for example, before sending the email out)\n\n### Client\n\nTo use Turnstile, add the auto-imported Vue component in whatever component needs it:\n\n```html\n\u003ctemplate\u003e\n  \u003cdiv\u003e\n    \u003cform @submit.prevent=\"onSubmit\"\u003e\n      \u003cNuxtTurnstile v-model=\"token\" /\u003e\n      \u003cinput type=\"submit\" /\u003e\n    \u003c/form\u003e\n  \u003c/div\u003e\n\u003c/template\u003e\n```\n\n`\u003cNuxtTurnstile\u003e` can take a number of options via the `options` argument. [See all options](./src/runtime/types.ts). It renders the Turnstile `\u003ciframe\u003e` within a `\u003cdiv\u003e` wrapper by default, but you can configure this by setting the `element` prop.\n\nWhen in the page, it will automatically load the Turnstile script and validate your user. Each validation lasts for 300s, and `@nuxtjs/turnstile` will automatically revalidate this token after 250s.\n\nYou can access the validation token by setting a `v-model` on the component. Then, send the token along with your form responses, either explicitly or automatically (Cloudflare adds a hidden form element with the name `cf-turnstile-response` to your form). To validate the token on server-side, you can use the auto-imported `verifyTurnstileToken` utility in your Nitro server routes.\n\nThe turnstile token is no longer valid after being processed with CloudFlare via `verifyTurnstileToken`. If you are using @nuxtjs/turnstile with a component that might need to be validated multiple times, such as a submission form, you will need to regenerate the token for each submission. To manually regenerate the token, @nuxtjs/turnstile exposes the `reset` function directly via a [template ref](https://vuejs.org/guide/essentials/template-refs.html).\n\n**Example**:\n\n```html\n\u003ctemplate\u003e\n  \u003cNuxtTurnstile ref=\"turnstile\" /\u003e\n  \u003cbutton @click=\"turnstile.reset()\"\u003eReset token in template\u003c/button\u003e\n  \u003cbutton @click=\"reset()\"\u003eReset token from handler\u003c/button\u003e\n\u003c/template\u003e\n\n\u003cscript setup\u003e\n  // you can call this template ref anything\n  const turnstile = ref()\n\n  function reset() {\n    turnstile.value?.reset()\n  }\n\u003c/script\u003e\n```\n\n### Server\n\nYou can either use the a generated validation endpoint, or use the imported helper method:\n\n**Example with endpoint**:\n\nTurn on the generation of the endpoint first:\n\n```js\nexport default defineNuxtConfig({\n  // ...\n  turnstile: {\n    siteKey: '\u003cyour-site-key\u003e',\n    addValidateEndpoint: true\n  },\n})\n```\n\nYou can now call the endpoint at `/_turnstile/validate` from the client to validate tokens.\n\n**Example with custom endpoint and helper method**:\n\n```js\n// server/api/validateTurnstile.ts\n\nexport default defineEventHandler(async (event) =\u003e {\n  const { token } = await readBody(event)\n\n  if (!token) {\n    throw createError({\n      statusCode: 422,\n      statusMessage: 'Token not provided.',\n    })\n  }\n\n  return await verifyTurnstileToken(token)\n})\n```\n\n## 💻 Development\n\n- Clone this repository\n- Enable [Corepack](https://github.com/nodejs/corepack) using `corepack enable`\n- Install dependencies using `pnpm install`\n- Stub module with `pnpm dev:prepare`\n- Run `pnpm dev` to start [playground](./playground) in development mode\n\n## Credits\n\n- inspired by [laravel-cloudflare-turnstile](https://github.com/ryangjchandler/laravel-cloudflare-turnstile)\n\n## License\n\nMade with ❤️\n\nPublished under the [MIT License](./LICENCE).\n\n\u003c!-- Badges --\u003e\n\n[npm-version-src]: https://img.shields.io/npm/v/@nuxtjs/turnstile?style=flat-square\n[npm-version-href]: https://npmjs.com/package/@nuxtjs/turnstile\n[npm-downloads-src]: https://img.shields.io/npm/dm/@nuxtjs/turnstile?style=flat-square\n[npm-downloads-href]: https://npm.chart.dev/@nuxtjs/turnstile\n[github-actions-src]: https://img.shields.io/github/actions/workflow/status/nuxt-modules/turnstile/ci.yml?style=flat-square\n[github-actions-href]: https://github.com/nuxt-modules/turnstile/actions?query=workflow%3Aci\n[codecov-src]: https://img.shields.io/codecov/c/gh/nuxt-modules/turnstile/main?style=flat-square\n[codecov-href]: https://codecov.io/gh/nuxt-modules/turnstile\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnuxt-modules%2Fturnstile","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnuxt-modules%2Fturnstile","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnuxt-modules%2Fturnstile/lists"}