{"_id":"@delaneydev/laravel-turnstile-vue","_rev":"5-8946761163daa7d9036b73c685cdb4f8","name":"@delaneydev/laravel-turnstile-vue","dist-tags":{"latest":"2.0.0"},"versions":{"1.0.0":{"name":"@delaneydev/laravel-turnstile-vue","version":"1.0.0","keywords":["vue","turnstile","cloudflare","laravel","captcha","component","vue3"],"author":{"name":"Delaney Dev","email":"you@example.com"},"license":"MIT","_id":"@delaneydev/laravel-turnstile-vue@1.0.0","maintainers":[{"name":"delaneydev","email":"delaneywrightbusiness@gmail.com"}],"homepage":"https://github.com/DelaneyDev/laravel-turnstile-vue#readme","bugs":{"url":"https://github.com/DelaneyDev/laravel-turnstile-vue/issues"},"dist":{"shasum":"2b784406358c84e084e25762b4c55222757d7a72","tarball":"https://registry.npmjs.org/@delaneydev/laravel-turnstile-vue/-/laravel-turnstile-vue-1.0.0.tgz","fileCount":6,"integrity":"sha512-AArX6Fj3bAjQn1kVseFTGUUqdoGYAzAyHg5iAP19ptN7pBQ/4lcyKkkulAy2Uu6f4kiEiC5cURpfEaDkitWFzw==","signatures":[{"sig":"MEUCIHwmcQ9JLoqUAie/S/SP9pgi8hy0/Y1GpoCcjOT1WvdeAiEA6dAMiAMjPlzSp2pXLJ/DRFrbo8nC7Wk1U7CHTVjA9Ko=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":17221},"main":"dist/laravel-turnstile-vue.umd.js","types":"index.ts","module":"dist/laravel-turnstile-vue.es.js","gitHead":"d0c8b2b0c87cbf80dcfb9cc3b8576e299543571e","scripts":{"build":"vite build","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"delaneydev","email":"delaneywrightbusiness@gmail.com"},"repository":{"url":"git+https://github.com/DelaneyDev/laravel-turnstile-vue.git","type":"git"},"_npmVersion":"10.9.2","description":"A Vue 3 component wrapper for Cloudflare Turnstile, designed for use with Laravel apps.","directories":{},"_nodeVersion":"23.10.0","dependencies":{"vue":"^3.5.13"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^6.2.6","vue-tsc":"^2.2.8","typescript":"^5.8.3","@vitejs/plugin-vue":"^5.2.3"},"peerDependencies":{"vue":"^3.0.0"},"_npmOperationalInternal":{"tmp":"tmp/laravel-turnstile-vue_1.0.0_1744321277445_0.8959942592798296","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@delaneydev/laravel-turnstile-vue","version":"1.0.2","keywords":["vue","turnstile","cloudflare","laravel","captcha","component","vue3"],"author":{"name":"Delaney Dev","email":"you@example.com"},"license":"MIT","_id":"@delaneydev/laravel-turnstile-vue@1.0.2","maintainers":[{"name":"delaneydev","email":"delaneywrightbusiness@gmail.com"}],"homepage":"https://github.com/DelaneyDev/laravel-turnstile-vue#readme","bugs":{"url":"https://github.com/DelaneyDev/laravel-turnstile-vue/issues"},"dist":{"shasum":"b731bbb4a693196aa7f7b843f36009c2bc57285a","tarball":"https://registry.npmjs.org/@delaneydev/laravel-turnstile-vue/-/laravel-turnstile-vue-1.0.2.tgz","fileCount":6,"integrity":"sha512-Ovrv0u4gYZQnAlyo2vywB+GyTSzpUy99bj49n28R/KkAyOBMIMAdmRVtEKRJ5cdvc9QgRapR4YnT3+ViLsoM2w==","signatures":[{"sig":"MEYCIQCbhWooLZt6Jc+Ktg0WHz4n5xpTsI37iA4lxT4VRh8rZAIhAKxrkm/02ZDMqlSDI7poG/i3OeV7Fnck07heD8mbcF08","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":17226},"main":"dist/laravel-turnstile-vue.umd.js","types":"index.ts","module":"dist/laravel-turnstile-vue.es.js","gitHead":"d4608accf6dfba42cdc53696e1d3b4c2c85b2cc7","scripts":{"build":"vite build","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"delaneydev","email":"delaneywrightbusiness@gmail.com"},"repository":{"url":"git+https://github.com/DelaneyDev/laravel-turnstile-vue.git","type":"git"},"_npmVersion":"10.9.2","description":"A Vue 3 component wrapper for Cloudflare Turnstile, designed for use with Laravel apps.","directories":{},"_nodeVersion":"23.10.0","dependencies":{"vue":"^3.5.13"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^6.2.6","vue-tsc":"^2.2.8","typescript":"^5.8.3","@vitejs/plugin-vue":"^5.2.3"},"peerDependencies":{"vue":"^3.0.0"},"_npmOperationalInternal":{"tmp":"tmp/laravel-turnstile-vue_1.0.2_1744322002224_0.6319126060941906","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"@delaneydev/laravel-turnstile-vue","version":"1.0.3","keywords":["vue","turnstile","cloudflare","laravel","captcha","component","vue3"],"author":{"name":"Delaney Dev","email":"you@example.com"},"license":"MIT","_id":"@delaneydev/laravel-turnstile-vue@1.0.3","maintainers":[{"name":"delaneydev","email":"delaneywrightbusiness@gmail.com"}],"homepage":"https://github.com/DelaneyDev/laravel-turnstile-vue#readme","bugs":{"url":"https://github.com/DelaneyDev/laravel-turnstile-vue/issues"},"dist":{"shasum":"a3840db5b38d4d502cb00b4ad7d777122cd9c38a","tarball":"https://registry.npmjs.org/@delaneydev/laravel-turnstile-vue/-/laravel-turnstile-vue-1.0.3.tgz","fileCount":6,"integrity":"sha512-JspzU97KFuptKm3dJ3Q3WmN4buD43Q8AmCNzDASr4JXxya8ZPYUJgkZUFbXdTtZLiz6t36EZGILls6NJ/AKMYg==","signatures":[{"sig":"MEYCIQCQwND12P2f7gTuTwPP5z7txBjbjjEjVKcRbk2/wdTe/gIhAOQt5R7khzCx3HLXLP1T7C7gtYxjF5Ocg6cRnHkkfBoD","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":17365},"main":"dist/laravel-turnstile-vue.umd.js","types":"index.ts","module":"dist/laravel-turnstile-vue.es.js","gitHead":"51e11e83ed3f95573e1585a9e8f64b001d1e73b7","scripts":{"build":"vite build","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"delaneydev","email":"delaneywrightbusiness@gmail.com"},"repository":{"url":"git+https://github.com/DelaneyDev/laravel-turnstile-vue.git","type":"git"},"_npmVersion":"10.9.2","description":"A Vue 3 component wrapper for Cloudflare Turnstile, designed for use with Laravel apps.","directories":{},"_nodeVersion":"23.10.0","dependencies":{"vue":"^3.5.13"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^6.2.6","vue-tsc":"^2.2.8","typescript":"^5.8.3","@vitejs/plugin-vue":"^5.2.3"},"peerDependencies":{"vue":"^3.0.0"},"_npmOperationalInternal":{"tmp":"tmp/laravel-turnstile-vue_1.0.3_1748559034609_0.6410275903823592","host":"s3://npm-registry-packages-npm-production"}},"1.0.4":{"name":"@delaneydev/laravel-turnstile-vue","version":"1.0.4","keywords":["vue","turnstile","cloudflare","laravel","captcha","component","vue3"],"author":{"name":"Delaney Dev","email":"you@example.com"},"license":"MIT","_id":"@delaneydev/laravel-turnstile-vue@1.0.4","maintainers":[{"name":"delaneydev","email":"delaneywrightbusiness@gmail.com"}],"homepage":"https://github.com/DelaneyDev/laravel-turnstile-vue#readme","bugs":{"url":"https://github.com/DelaneyDev/laravel-turnstile-vue/issues"},"dist":{"shasum":"77564c620eee5b7133ec9e0ad15cb80a36c53096","tarball":"https://registry.npmjs.org/@delaneydev/laravel-turnstile-vue/-/laravel-turnstile-vue-1.0.4.tgz","fileCount":6,"integrity":"sha512-f4+BpnHgFI+9Rxg3WjlJpHf1mvNfN/94OM5QSGUS2jfsYDAFj/+JltyA6Oojaq+NuNHV86U1igp6J9gtOAxQ9A==","signatures":[{"sig":"MEUCIDRS3Q2+wGS+svYJ+4wm6PSZ+KTBFv+/omTTs6h1D4qaAiEA4h+fpJLDgfjd8xc5tHmkMSYJzrmdPCUN60f+zE7HiLI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":17585},"main":"dist/laravel-turnstile-vue.umd.js","types":"index.ts","module":"dist/laravel-turnstile-vue.es.js","gitHead":"18770f77783fc69d01d94bca0d3f15c74f75a51f","scripts":{"build":"vite build","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"delaneydev","email":"delaneywrightbusiness@gmail.com"},"repository":{"url":"git+https://github.com/DelaneyDev/laravel-turnstile-vue.git","type":"git"},"_npmVersion":"10.9.2","description":"A Vue 3 component wrapper for Cloudflare Turnstile, designed for use with Laravel apps.","directories":{},"_nodeVersion":"23.10.0","dependencies":{"vue":"^3.5.13"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^6.2.6","vue-tsc":"^2.2.8","typescript":"^5.8.3","@vitejs/plugin-vue":"^5.2.3"},"peerDependencies":{"vue":"^3.0.0"},"_npmOperationalInternal":{"tmp":"tmp/laravel-turnstile-vue_1.0.4_1748566285394_0.689068798731512","host":"s3://npm-registry-packages-npm-production"}},"2.0.0":{"$schema":"https://json.schemastore.org/package.json","name":"@delaneydev/laravel-turnstile-vue","version":"2.0.0","description":"A production-ready, SSR-safe Cloudflare Turnstile component for Vue 3.","type":"module","author":{"name":"DelaneyDev"},"license":"MIT","main":"./dist/laravel-turnstile-vue.umd.cjs","module":"./dist/laravel-turnstile-vue.js","types":"./dist/index.d.ts","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/laravel-turnstile-vue.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/laravel-turnstile-vue.umd.cjs"}},"./package.json":"./package.json"},"sideEffects":false,"engines":{"node":">=20.19.0"},"keywords":["cloudflare","turnstile","vue","vue3","typescript","ssr","captcha","laravel","inertia","nuxt"],"scripts":{"dev":"vite --config playground/vite.config.ts","build":"vite build","type-check":"vue-tsc -p tsconfig.json --noEmit","lint":"eslint . && markdownlint-cli2","format":"prettier --write .","format:check":"prettier --check .","test":"vitest run","test:coverage":"vitest run --coverage","test:e2e":"playwright test","test:package":"npm run build && node scripts/verify-package.mjs","check:package":"publint && attw --pack .","audit":"npm audit --audit-level=high","check":"npm run lint && npm run format:check && npm run type-check && npm run audit && npm run test:coverage && npm run test:package && npm run check:package","prepack":"npm run build"},"peerDependencies":{"vue":"^3.2.0"},"devDependencies":{"@arethetypeswrong/cli":"^0.18.5","@eslint/js":"^10.0.1","@microsoft/api-extractor":"^7.58.12","@playwright/test":"^1.62.1","@types/node":"^26.1.2","@vitejs/plugin-vue":"^6.0.8","@vitest/coverage-v8":"^4.1.10","@vue/eslint-config-typescript":"^14.9.0","@vue/server-renderer":"^3.5.40","@vue/test-utils":"^2.4.11","eslint":"^10.8.0","eslint-config-prettier":"^10.1.8","eslint-plugin-vue":"^10.10.0","globals":"^17.9.0","happy-dom":"^20.11.1","markdownlint-cli2":"^0.23.2","prettier":"^3.9.6","publint":"^0.3.23","typescript":"~5.9.3","typescript-eslint":"^8.66.0","unplugin-dts":"^1.0.3","vite":"^8.2.0","vitest":"^4.1.10","vue":"^3.5.40","vue-tsc":"^3.3.9"},"repository":{"type":"git","url":"git+https://github.com/DelaneyDev/laravel-turnstile-vue.git"},"bugs":{"url":"https://github.com/DelaneyDev/laravel-turnstile-vue/issues"},"homepage":"https://github.com/DelaneyDev/laravel-turnstile-vue#readme","publishConfig":{"access":"public","provenance":true},"gitHead":"a2ec5d91b2924f8c5c6ad113a23f568e6e1c1350","_id":"@delaneydev/laravel-turnstile-vue@2.0.0","_nodeVersion":"24.18.0","_npmVersion":"11.19.0","dist":{"integrity":"sha512-ZxjFdDjJcoNfNubmuPuUFhEHcH6C10WlozqerLil3Tv76gKaCt1tVmq2T414j2YpGQpgonovZzPcDJa5DtITaQ==","shasum":"754de98c8c9694ad10a2fb28b33352e11d80f5dc","tarball":"https://registry.npmjs.org/@delaneydev/laravel-turnstile-vue/-/laravel-turnstile-vue-2.0.0.tgz","fileCount":18,"unpackedSize":251989,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@delaneydev%2flaravel-turnstile-vue@2.0.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIFI4kssaf5m5mmGrw+9tIhES5q8QGxyGHvLoch3OJ4u1AiEAnV3XIuHWKvvIzIqwRZp6miTxkAnxJuu4VtyFGBRLlfM="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:232c83e5-e7c5-4d43-9b1c-64a4300079ee"}},"directories":{},"maintainers":[{"name":"delaneydev","email":"delaneywrightbusiness@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/laravel-turnstile-vue_2.0.0_1785874417187_0.4482305521936165"},"_hasShrinkwrap":false}},"time":{"created":"2025-04-10T21:41:17.383Z","modified":"2026-08-04T20:13:37.676Z","1.0.0":"2025-04-10T21:41:17.658Z","1.0.2":"2025-04-10T21:53:22.475Z","1.0.3":"2025-05-29T22:50:34.790Z","1.0.4":"2025-05-30T00:51:25.612Z","2.0.0":"2026-08-04T20:13:37.351Z"},"bugs":{"url":"https://github.com/DelaneyDev/laravel-turnstile-vue/issues"},"author":{"name":"DelaneyDev"},"license":"MIT","homepage":"https://github.com/DelaneyDev/laravel-turnstile-vue#readme","keywords":["cloudflare","turnstile","vue","vue3","typescript","ssr","captcha","laravel","inertia","nuxt"],"repository":{"type":"git","url":"git+https://github.com/DelaneyDev/laravel-turnstile-vue.git"},"description":"A production-ready, SSR-safe Cloudflare Turnstile component for Vue 3.","maintainers":[{"name":"delaneydev","email":"delaneywrightbusiness@gmail.com"}],"readme":"# Laravel Turnstile Vue\n\n<p align=\"center\">\n  <a href=\"https://delaneyindustries.co.uk\">\n    <img src=\"https://raw.githubusercontent.com/DelaneyDev/laravel-turnstile-vue/main/.github/assets/delaney-industries-logo.webp\" alt=\"Delaney Industries Ltd\" width=\"180\">\n  </a>\n</p>\n\nFree and open source software from\n[Delaney Industries Ltd](https://delaneyindustries.co.uk).\n\n[![npm version](https://img.shields.io/npm/v/@delaneydev/laravel-turnstile-vue.svg)](https://www.npmjs.com/package/@delaneydev/laravel-turnstile-vue)\n[![npm downloads](https://img.shields.io/npm/dm/@delaneydev/laravel-turnstile-vue.svg)](https://www.npmjs.com/package/@delaneydev/laravel-turnstile-vue)\n[![CI](https://github.com/DelaneyDev/laravel-turnstile-vue/actions/workflows/ci.yml/badge.svg)](https://github.com/DelaneyDev/laravel-turnstile-vue/actions/workflows/ci.yml)\n[![license](https://img.shields.io/npm/l/@delaneydev/laravel-turnstile-vue.svg)](LICENSE)\n\nA typed, production-ready Cloudflare Turnstile component for Vue 3. It is safe to\nimport during SSR, supports visible and invisible widgets, and works with any\nbackend that validates Turnstile tokens.\n\nThe npm name is retained for existing users, but Laravel and Inertia are optional.\n\n## Highlights\n\n- Stable SSR markup with no browser globals accessed during import or server render\n- Shared, race-safe script loader with CSP nonce and consumer-managed script support\n- Every current Cloudflare render option and lifecycle callback\n- Visible, deferred, and invisible challenge flows\n- Typed `v-model`, events, errors, methods, props, and `window.turnstile`\n- Single-flight `challenge()` calls and stale-token protection\n- Optional async preflight before a challenge, useful for refreshing long-lived sessions\n- Automatic cleanup across Vue and Inertia navigation\n- ESM and CommonJS artifacts with bundled declarations\n- Official Cloudflare test keys exported for deterministic integration tests\n\n## Install\n\n```bash\nnpm install @delaneydev/laravel-turnstile-vue\n```\n\nVue is a peer dependency. Vue `3.2` and newer are supported.\n\nCreate a widget in the [Cloudflare Turnstile dashboard](https://dash.cloudflare.com/?to=/:account/turnstile),\nallow your hostnames, and keep the secret key on the server. The sitekey is public.\n\n## Basic Usage\n\n```vue\n<script setup lang=\"ts\">\nimport { ref } from 'vue';\nimport {\n  TurnstileWidget,\n  type TurnstileWidgetInstance,\n} from '@delaneydev/laravel-turnstile-vue';\n\nconst token = ref('');\nconst turnstile = ref<TurnstileWidgetInstance | null>(null);\nconst submitting = ref(false);\n\nasync function submit() {\n  if (!token.value || submitting.value) return;\n  submitting.value = true;\n\n  try {\n    const response = await fetch('/api/contact', {\n      method: 'POST',\n      headers: { 'Content-Type': 'application/json' },\n      body: JSON.stringify({ turnstileToken: token.value }),\n    });\n    if (!response.ok) throw new Error('Submission failed.');\n  } finally {\n    // Tokens are single-use. Reset after every request that may verify one.\n    turnstile.value?.reset();\n    submitting.value = false;\n  }\n}\n</script>\n\n<template>\n  <form @submit.prevent=\"submit\">\n    <!-- Your fields -->\n    <TurnstileWidget\n      ref=\"turnstile\"\n      v-model=\"token\"\n      sitekey=\"your-public-sitekey\"\n      action=\"contact\"\n      size=\"flexible\"\n      :response-field=\"false\"\n    />\n    <button type=\"submit\" :disabled=\"!token || submitting\">Send</button>\n  </form>\n</template>\n```\n\nEvery token must be validated by your backend with Cloudflare Siteverify. Client-side\nsuccess alone is not a security control. See [server-side validation](docs/server-validation.md).\n\n`size=\"flexible\"` fills a container but keeps Cloudflare's 300-pixel minimum. Use\n`size=\"compact\"` when the form's content box can be narrower.\n\n## Invisible And Deferred Challenges\n\nInvisible mode is configured on the Cloudflare widget/sitekey. It is not a widget\n`size`. Pair an invisible sitekey with deferred execution:\n\n```vue\n<script setup lang=\"ts\">\nimport { ref } from 'vue';\nimport {\n  TurnstileWidget,\n  type TurnstileWidgetInstance,\n} from '@delaneydev/laravel-turnstile-vue';\n\nconst turnstile = ref<TurnstileWidgetInstance | null>(null);\nconst submitting = ref(false);\n\nasync function submit() {\n  if (!turnstile.value || submitting.value) return;\n  submitting.value = true;\n\n  try {\n    const token = await turnstile.value.challenge({\n      force: true,\n      timeoutMs: 30_000,\n    });\n\n    const response = await fetch('/api/checkout', {\n      method: 'POST',\n      headers: { 'Content-Type': 'application/json' },\n      body: JSON.stringify({ turnstileToken: token }),\n    });\n    if (!response.ok) throw new Error('Submission failed.');\n  } finally {\n    // The request may have consumed the token even when it failed.\n    turnstile.value?.reset();\n    submitting.value = false;\n  }\n}\n</script>\n\n<template>\n  <TurnstileWidget\n    ref=\"turnstile\"\n    sitekey=\"your-invisible-sitekey\"\n    execution=\"execute\"\n    appearance=\"execute\"\n    action=\"checkout\"\n    :response-field=\"false\"\n  />\n  <button type=\"button\" :disabled=\"submitting\" @click=\"submit\">Pay</button>\n</template>\n```\n\n`challenge()` returns an existing valid token or waits for a fresh one. Concurrent\ncalls share one challenge. `force: true` resets a potentially consumed token first.\n\nCloudflare requires sites using Invisible Turnstile to reference its\n[Turnstile Privacy Addendum](https://www.cloudflare.com/cloudflare-customer-dpa/).\n\n## Session And CSRF Preflight\n\nLong-lived forms can outlive a server session. With deferred execution, use\n`beforeExecute` to refresh the session before asking the user to complete a challenge:\n\n```vue\n<TurnstileWidget\n  ref=\"turnstile\"\n  sitekey=\"your-sitekey\"\n  execution=\"execute\"\n  appearance=\"execute\"\n  :before-execute=\"refreshSession\"\n/>\n```\n\nThe hook runs before `execute()` and `challenge()`. If it rejects, no challenge starts\nand the component emits a typed `preflight` error. This avoids earning a short-lived,\nsingle-use token only to discover that the request will fail with an expired CSRF\nsession. The package does not make framework-specific network requests on its own.\n\nSee the complete [Laravel and Inertia session-refresh pattern](docs/laravel-inertia.md#long-lived-forms-and-csrf-expiry).\n\n## SSR And Vite\n\nThe package can be imported and rendered on the server. It emits a stable empty\ncontainer and loads Cloudflare only after Vue mounts in the browser.\n\nVite SSR should use its normal dependency externalization in version 2:\n\n```ts\n// vite.config.ts\nimport { defineConfig } from 'vite';\n\nexport default defineConfig({\n  // No Turnstile-specific ssr.noExternal entry is required.\n});\n```\n\nBoth default externalization and a bundled `ssr.noExternal` build are tested against\nthe packed npm artifact. The following was a version 1 workaround and can be removed\nafter upgrading:\n\n```ts\nssr: {\n  noExternal: ['@delaneydev/laravel-turnstile-vue'],\n}\n```\n\nSee [Laravel/Inertia SSR](docs/laravel-inertia.md#inertia-ssr) and the\n[version 2 migration guide](docs/migration-v2.md).\n\n## API At A Glance\n\nThe component supports all current Cloudflare options, including:\n\n`theme`, `language`, `tabindex`, `size`, `action`, `cData`, `retry`,\n`retryInterval`, `refreshExpired`, `refreshTimeout`, `appearance`, `execution`,\n`responseField`, `responseFieldName`, `feedbackEnabled`, `offlabelShowPrivacy`, and\n`offlabelShowHelp`.\n\nPackage behavior is controlled with `renderOnMount`, `injectScript`, `scriptOptions`,\n`resetOnModelClear`, and `beforeExecute`.\n\nImperative methods:\n\n```ts\nrender(): Promise<string>\nexecute(): Promise<void>\nchallenge(options?): Promise<string>\nreset(): void\nremove(): void\ngetResponse(): string | undefined\ngetResponsePromise(timeoutMs?): Promise<string>\nisExpired(): boolean\ngetWidgetId(): string | undefined\ngetState(): TurnstileWidgetState\n```\n\nEvents include `success`, `error`, `expired`, `timeout`, `before-interactive`,\n`after-interactive`, `unsupported`, `loaded`, `widget-load`, `reset`, and `removed`.\n\nSee the [complete API reference](docs/api.md).\n\n## Framework Guides\n\n- [Laravel and Inertia, including TypeScript starters, forms, SSR, and CSRF expiry](docs/laravel-inertia.md)\n- [Framework-agnostic server-side validation](docs/server-validation.md)\n- [Testing with Cloudflare's official keys](docs/testing.md)\n- [Troubleshooting production and integration failures](docs/troubleshooting.md)\n- [Migrating from version 1](docs/migration-v2.md)\n- [Version 1.0.4 documentation (archived)](https://github.com/DelaneyDev/laravel-turnstile-vue/blob/4c83df916d25666508b27fc958b34f6da2ab7eff/README.md)\n\n## Browser Support\n\nTurnstile's supported browsers and environments are controlled by Cloudflare. The\ncomponent reports Cloudflare's `unsupported-callback` as an `unsupported` event and\nstate. Do not block form recovery behind a widget that cannot load; provide a support\nor fallback path appropriate to your application.\n\n## Security\n\nReport vulnerabilities through GitHub's private security advisory flow. Do not put a\nTurnstile secret key in Vue props, Vite `VITE_*` variables, browser code, logs, or the\nrepository. See [SECURITY.md](SECURITY.md).\n\n## License\n\nThis is a free and open source product from\n[Delaney Industries Ltd](https://delaneyindustries.co.uk), released under the\n[MIT License](LICENSE). Contributions are welcome through GitHub issues and pull\nrequests.\n\nThis project is independently developed and is not affiliated with, endorsed by,\nor sponsored by Cloudflare.\n","readmeFilename":"README.md"}