pi-cloudflare 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (410) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +67 -0
  3. package/bin/setup.mjs +103 -0
  4. package/dist/auth-flow.d.ts +15 -0
  5. package/dist/auth-flow.d.ts.map +1 -0
  6. package/dist/auth-flow.js +90 -0
  7. package/dist/auth-flow.js.map +1 -0
  8. package/dist/client.d.ts +18 -0
  9. package/dist/client.d.ts.map +1 -0
  10. package/dist/client.js +47 -0
  11. package/dist/client.js.map +1 -0
  12. package/dist/config.d.ts +13 -0
  13. package/dist/config.d.ts.map +1 -0
  14. package/dist/config.js +10 -0
  15. package/dist/config.js.map +1 -0
  16. package/dist/index.d.ts +24 -0
  17. package/dist/index.d.ts.map +1 -0
  18. package/dist/index.js +109 -0
  19. package/dist/index.js.map +1 -0
  20. package/dist/oauth.d.ts +44 -0
  21. package/dist/oauth.d.ts.map +1 -0
  22. package/dist/oauth.js +135 -0
  23. package/dist/oauth.js.map +1 -0
  24. package/dist/proxy.d.ts +29 -0
  25. package/dist/proxy.d.ts.map +1 -0
  26. package/dist/proxy.js +39 -0
  27. package/dist/proxy.js.map +1 -0
  28. package/dist/servers.d.ts +19 -0
  29. package/dist/servers.d.ts.map +1 -0
  30. package/dist/servers.js +40 -0
  31. package/dist/servers.js.map +1 -0
  32. package/dist/token-store.d.ts +23 -0
  33. package/dist/token-store.d.ts.map +1 -0
  34. package/dist/token-store.js +47 -0
  35. package/dist/token-store.js.map +1 -0
  36. package/package.json +67 -0
  37. package/skills/agents-sdk/SKILL.md +221 -0
  38. package/skills/agents-sdk/references/browse-the-web.md +63 -0
  39. package/skills/agents-sdk/references/callable.md +92 -0
  40. package/skills/agents-sdk/references/client-sdk.md +110 -0
  41. package/skills/agents-sdk/references/codemode.md +110 -0
  42. package/skills/agents-sdk/references/configuration.md +72 -0
  43. package/skills/agents-sdk/references/durable-execution.md +51 -0
  44. package/skills/agents-sdk/references/email.md +146 -0
  45. package/skills/agents-sdk/references/human-in-the-loop.md +67 -0
  46. package/skills/agents-sdk/references/mcp.md +188 -0
  47. package/skills/agents-sdk/references/observability.md +44 -0
  48. package/skills/agents-sdk/references/queue-retries.md +79 -0
  49. package/skills/agents-sdk/references/routing.md +75 -0
  50. package/skills/agents-sdk/references/server-driven-messages.md +63 -0
  51. package/skills/agents-sdk/references/state-scheduling.md +171 -0
  52. package/skills/agents-sdk/references/streaming-chat.md +198 -0
  53. package/skills/agents-sdk/references/think.md +112 -0
  54. package/skills/agents-sdk/references/voice.md +68 -0
  55. package/skills/agents-sdk/references/webhooks-push.md +86 -0
  56. package/skills/agents-sdk/references/workflows.md +132 -0
  57. package/skills/cloudflare/SKILL.md +248 -0
  58. package/skills/cloudflare/references/agents-sdk/README.md +89 -0
  59. package/skills/cloudflare/references/agents-sdk/api.md +190 -0
  60. package/skills/cloudflare/references/agents-sdk/configuration.md +182 -0
  61. package/skills/cloudflare/references/agents-sdk/gotchas.md +158 -0
  62. package/skills/cloudflare/references/agents-sdk/patterns.md +192 -0
  63. package/skills/cloudflare/references/ai-gateway/README.md +175 -0
  64. package/skills/cloudflare/references/ai-gateway/configuration.md +111 -0
  65. package/skills/cloudflare/references/ai-gateway/dynamic-routing.md +82 -0
  66. package/skills/cloudflare/references/ai-gateway/features.md +96 -0
  67. package/skills/cloudflare/references/ai-gateway/sdk-integration.md +114 -0
  68. package/skills/cloudflare/references/ai-gateway/troubleshooting.md +88 -0
  69. package/skills/cloudflare/references/ai-search/README.md +138 -0
  70. package/skills/cloudflare/references/ai-search/api.md +87 -0
  71. package/skills/cloudflare/references/ai-search/configuration.md +88 -0
  72. package/skills/cloudflare/references/ai-search/gotchas.md +81 -0
  73. package/skills/cloudflare/references/ai-search/patterns.md +85 -0
  74. package/skills/cloudflare/references/analytics-engine/README.md +94 -0
  75. package/skills/cloudflare/references/analytics-engine/api.md +112 -0
  76. package/skills/cloudflare/references/analytics-engine/configuration.md +112 -0
  77. package/skills/cloudflare/references/analytics-engine/gotchas.md +85 -0
  78. package/skills/cloudflare/references/analytics-engine/patterns.md +83 -0
  79. package/skills/cloudflare/references/api/README.md +66 -0
  80. package/skills/cloudflare/references/api/api.md +204 -0
  81. package/skills/cloudflare/references/api/configuration.md +160 -0
  82. package/skills/cloudflare/references/api/gotchas.md +225 -0
  83. package/skills/cloudflare/references/api/patterns.md +204 -0
  84. package/skills/cloudflare/references/api-shield/README.md +44 -0
  85. package/skills/cloudflare/references/api-shield/api.md +141 -0
  86. package/skills/cloudflare/references/api-shield/configuration.md +192 -0
  87. package/skills/cloudflare/references/api-shield/gotchas.md +125 -0
  88. package/skills/cloudflare/references/api-shield/patterns.md +180 -0
  89. package/skills/cloudflare/references/argo-smart-routing/README.md +90 -0
  90. package/skills/cloudflare/references/argo-smart-routing/api.md +240 -0
  91. package/skills/cloudflare/references/argo-smart-routing/configuration.md +197 -0
  92. package/skills/cloudflare/references/argo-smart-routing/gotchas.md +111 -0
  93. package/skills/cloudflare/references/argo-smart-routing/patterns.md +104 -0
  94. package/skills/cloudflare/references/artifacts/README.md +79 -0
  95. package/skills/cloudflare/references/artifacts/api.md +128 -0
  96. package/skills/cloudflare/references/artifacts/configuration.md +92 -0
  97. package/skills/cloudflare/references/bindings/README.md +122 -0
  98. package/skills/cloudflare/references/bindings/api.md +203 -0
  99. package/skills/cloudflare/references/bindings/configuration.md +188 -0
  100. package/skills/cloudflare/references/bindings/gotchas.md +208 -0
  101. package/skills/cloudflare/references/bindings/patterns.md +200 -0
  102. package/skills/cloudflare/references/bot-management/README.md +94 -0
  103. package/skills/cloudflare/references/bot-management/api.md +169 -0
  104. package/skills/cloudflare/references/bot-management/configuration.md +163 -0
  105. package/skills/cloudflare/references/bot-management/gotchas.md +114 -0
  106. package/skills/cloudflare/references/bot-management/patterns.md +182 -0
  107. package/skills/cloudflare/references/browser-rendering/README.md +78 -0
  108. package/skills/cloudflare/references/browser-rendering/api.md +108 -0
  109. package/skills/cloudflare/references/browser-rendering/configuration.md +78 -0
  110. package/skills/cloudflare/references/browser-rendering/gotchas.md +88 -0
  111. package/skills/cloudflare/references/browser-rendering/patterns.md +91 -0
  112. package/skills/cloudflare/references/c3/README.md +111 -0
  113. package/skills/cloudflare/references/c3/api.md +71 -0
  114. package/skills/cloudflare/references/c3/configuration.md +81 -0
  115. package/skills/cloudflare/references/c3/gotchas.md +92 -0
  116. package/skills/cloudflare/references/c3/patterns.md +82 -0
  117. package/skills/cloudflare/references/cache-reserve/README.md +147 -0
  118. package/skills/cloudflare/references/cache-reserve/api.md +194 -0
  119. package/skills/cloudflare/references/cache-reserve/configuration.md +169 -0
  120. package/skills/cloudflare/references/cache-reserve/gotchas.md +132 -0
  121. package/skills/cloudflare/references/cache-reserve/patterns.md +197 -0
  122. package/skills/cloudflare/references/containers/README.md +85 -0
  123. package/skills/cloudflare/references/containers/api.md +187 -0
  124. package/skills/cloudflare/references/containers/configuration.md +188 -0
  125. package/skills/cloudflare/references/containers/gotchas.md +178 -0
  126. package/skills/cloudflare/references/containers/patterns.md +202 -0
  127. package/skills/cloudflare/references/cron-triggers/README.md +99 -0
  128. package/skills/cloudflare/references/cron-triggers/api.md +196 -0
  129. package/skills/cloudflare/references/cron-triggers/configuration.md +180 -0
  130. package/skills/cloudflare/references/cron-triggers/gotchas.md +199 -0
  131. package/skills/cloudflare/references/cron-triggers/patterns.md +190 -0
  132. package/skills/cloudflare/references/d1/README.md +133 -0
  133. package/skills/cloudflare/references/d1/api.md +196 -0
  134. package/skills/cloudflare/references/d1/configuration.md +191 -0
  135. package/skills/cloudflare/references/d1/gotchas.md +98 -0
  136. package/skills/cloudflare/references/d1/patterns.md +189 -0
  137. package/skills/cloudflare/references/ddos/README.md +41 -0
  138. package/skills/cloudflare/references/ddos/api.md +164 -0
  139. package/skills/cloudflare/references/ddos/configuration.md +93 -0
  140. package/skills/cloudflare/references/ddos/gotchas.md +107 -0
  141. package/skills/cloudflare/references/ddos/patterns.md +174 -0
  142. package/skills/cloudflare/references/do-storage/README.md +75 -0
  143. package/skills/cloudflare/references/do-storage/api.md +102 -0
  144. package/skills/cloudflare/references/do-storage/configuration.md +112 -0
  145. package/skills/cloudflare/references/do-storage/gotchas.md +150 -0
  146. package/skills/cloudflare/references/do-storage/patterns.md +194 -0
  147. package/skills/cloudflare/references/do-storage/testing.md +183 -0
  148. package/skills/cloudflare/references/durable-objects/README.md +185 -0
  149. package/skills/cloudflare/references/durable-objects/api.md +187 -0
  150. package/skills/cloudflare/references/durable-objects/configuration.md +160 -0
  151. package/skills/cloudflare/references/durable-objects/gotchas.md +197 -0
  152. package/skills/cloudflare/references/durable-objects/patterns.md +201 -0
  153. package/skills/cloudflare/references/email-routing/README.md +89 -0
  154. package/skills/cloudflare/references/email-routing/api.md +195 -0
  155. package/skills/cloudflare/references/email-routing/configuration.md +186 -0
  156. package/skills/cloudflare/references/email-routing/gotchas.md +196 -0
  157. package/skills/cloudflare/references/email-routing/patterns.md +229 -0
  158. package/skills/cloudflare/references/email-workers/README.md +151 -0
  159. package/skills/cloudflare/references/email-workers/api.md +237 -0
  160. package/skills/cloudflare/references/email-workers/configuration.md +112 -0
  161. package/skills/cloudflare/references/email-workers/gotchas.md +125 -0
  162. package/skills/cloudflare/references/email-workers/patterns.md +102 -0
  163. package/skills/cloudflare/references/flagship/README.md +59 -0
  164. package/skills/cloudflare/references/flagship/api.md +390 -0
  165. package/skills/cloudflare/references/flagship/configuration.md +202 -0
  166. package/skills/cloudflare/references/flagship/gotchas.md +178 -0
  167. package/skills/cloudflare/references/flagship/patterns.md +469 -0
  168. package/skills/cloudflare/references/graphql-api/README.md +147 -0
  169. package/skills/cloudflare/references/graphql-api/api.md +175 -0
  170. package/skills/cloudflare/references/graphql-api/configuration.md +118 -0
  171. package/skills/cloudflare/references/graphql-api/gotchas.md +110 -0
  172. package/skills/cloudflare/references/graphql-api/patterns.md +225 -0
  173. package/skills/cloudflare/references/hyperdrive/README.md +82 -0
  174. package/skills/cloudflare/references/hyperdrive/api.md +143 -0
  175. package/skills/cloudflare/references/hyperdrive/configuration.md +159 -0
  176. package/skills/cloudflare/references/hyperdrive/gotchas.md +77 -0
  177. package/skills/cloudflare/references/hyperdrive/patterns.md +190 -0
  178. package/skills/cloudflare/references/images/README.md +61 -0
  179. package/skills/cloudflare/references/images/api.md +96 -0
  180. package/skills/cloudflare/references/images/configuration.md +211 -0
  181. package/skills/cloudflare/references/images/gotchas.md +99 -0
  182. package/skills/cloudflare/references/images/patterns.md +115 -0
  183. package/skills/cloudflare/references/kv/README.md +89 -0
  184. package/skills/cloudflare/references/kv/api.md +160 -0
  185. package/skills/cloudflare/references/kv/configuration.md +144 -0
  186. package/skills/cloudflare/references/kv/gotchas.md +131 -0
  187. package/skills/cloudflare/references/kv/patterns.md +196 -0
  188. package/skills/cloudflare/references/miniflare/README.md +105 -0
  189. package/skills/cloudflare/references/miniflare/api.md +187 -0
  190. package/skills/cloudflare/references/miniflare/configuration.md +173 -0
  191. package/skills/cloudflare/references/miniflare/gotchas.md +160 -0
  192. package/skills/cloudflare/references/miniflare/patterns.md +181 -0
  193. package/skills/cloudflare/references/network-interconnect/README.md +99 -0
  194. package/skills/cloudflare/references/network-interconnect/api.md +199 -0
  195. package/skills/cloudflare/references/network-interconnect/configuration.md +114 -0
  196. package/skills/cloudflare/references/network-interconnect/gotchas.md +165 -0
  197. package/skills/cloudflare/references/network-interconnect/patterns.md +166 -0
  198. package/skills/cloudflare/references/observability/README.md +88 -0
  199. package/skills/cloudflare/references/observability/api.md +164 -0
  200. package/skills/cloudflare/references/observability/configuration.md +169 -0
  201. package/skills/cloudflare/references/observability/gotchas.md +115 -0
  202. package/skills/cloudflare/references/observability/patterns.md +105 -0
  203. package/skills/cloudflare/references/pages/README.md +88 -0
  204. package/skills/cloudflare/references/pages/api.md +204 -0
  205. package/skills/cloudflare/references/pages/configuration.md +201 -0
  206. package/skills/cloudflare/references/pages/gotchas.md +203 -0
  207. package/skills/cloudflare/references/pages/patterns.md +204 -0
  208. package/skills/cloudflare/references/pages-functions/README.md +98 -0
  209. package/skills/cloudflare/references/pages-functions/api.md +143 -0
  210. package/skills/cloudflare/references/pages-functions/configuration.md +122 -0
  211. package/skills/cloudflare/references/pages-functions/gotchas.md +94 -0
  212. package/skills/cloudflare/references/pages-functions/patterns.md +137 -0
  213. package/skills/cloudflare/references/pipelines/README.md +90 -0
  214. package/skills/cloudflare/references/pipelines/api.md +124 -0
  215. package/skills/cloudflare/references/pipelines/configuration.md +155 -0
  216. package/skills/cloudflare/references/pipelines/gotchas.md +58 -0
  217. package/skills/cloudflare/references/pipelines/patterns.md +130 -0
  218. package/skills/cloudflare/references/pulumi/README.md +100 -0
  219. package/skills/cloudflare/references/pulumi/api.md +200 -0
  220. package/skills/cloudflare/references/pulumi/configuration.md +198 -0
  221. package/skills/cloudflare/references/pulumi/gotchas.md +181 -0
  222. package/skills/cloudflare/references/pulumi/patterns.md +191 -0
  223. package/skills/cloudflare/references/queues/README.md +96 -0
  224. package/skills/cloudflare/references/queues/api.md +206 -0
  225. package/skills/cloudflare/references/queues/configuration.md +144 -0
  226. package/skills/cloudflare/references/queues/gotchas.md +206 -0
  227. package/skills/cloudflare/references/queues/patterns.md +220 -0
  228. package/skills/cloudflare/references/r2/README.md +95 -0
  229. package/skills/cloudflare/references/r2/api.md +200 -0
  230. package/skills/cloudflare/references/r2/configuration.md +165 -0
  231. package/skills/cloudflare/references/r2/gotchas.md +190 -0
  232. package/skills/cloudflare/references/r2/patterns.md +193 -0
  233. package/skills/cloudflare/references/r2-data-catalog/README.md +75 -0
  234. package/skills/cloudflare/references/r2-data-catalog/api.md +122 -0
  235. package/skills/cloudflare/references/r2-data-catalog/configuration.md +98 -0
  236. package/skills/cloudflare/references/r2-data-catalog/gotchas.md +55 -0
  237. package/skills/cloudflare/references/r2-data-catalog/patterns.md +122 -0
  238. package/skills/cloudflare/references/r2-sql/README.md +64 -0
  239. package/skills/cloudflare/references/r2-sql/api.md +121 -0
  240. package/skills/cloudflare/references/r2-sql/configuration.md +50 -0
  241. package/skills/cloudflare/references/r2-sql/gotchas.md +39 -0
  242. package/skills/cloudflare/references/r2-sql/patterns.md +118 -0
  243. package/skills/cloudflare/references/realtime-sfu/README.md +65 -0
  244. package/skills/cloudflare/references/realtime-sfu/api.md +158 -0
  245. package/skills/cloudflare/references/realtime-sfu/configuration.md +137 -0
  246. package/skills/cloudflare/references/realtime-sfu/gotchas.md +133 -0
  247. package/skills/cloudflare/references/realtime-sfu/patterns.md +174 -0
  248. package/skills/cloudflare/references/realtimekit/README.md +113 -0
  249. package/skills/cloudflare/references/realtimekit/api.md +212 -0
  250. package/skills/cloudflare/references/realtimekit/configuration.md +203 -0
  251. package/skills/cloudflare/references/realtimekit/gotchas.md +169 -0
  252. package/skills/cloudflare/references/realtimekit/patterns.md +223 -0
  253. package/skills/cloudflare/references/sandbox/README.md +96 -0
  254. package/skills/cloudflare/references/sandbox/api.md +198 -0
  255. package/skills/cloudflare/references/sandbox/configuration.md +143 -0
  256. package/skills/cloudflare/references/sandbox/gotchas.md +194 -0
  257. package/skills/cloudflare/references/sandbox/patterns.md +201 -0
  258. package/skills/cloudflare/references/secrets-store/README.md +74 -0
  259. package/skills/cloudflare/references/secrets-store/api.md +200 -0
  260. package/skills/cloudflare/references/secrets-store/configuration.md +185 -0
  261. package/skills/cloudflare/references/secrets-store/gotchas.md +97 -0
  262. package/skills/cloudflare/references/secrets-store/patterns.md +207 -0
  263. package/skills/cloudflare/references/smart-placement/README.md +138 -0
  264. package/skills/cloudflare/references/smart-placement/api.md +183 -0
  265. package/skills/cloudflare/references/smart-placement/configuration.md +196 -0
  266. package/skills/cloudflare/references/smart-placement/gotchas.md +174 -0
  267. package/skills/cloudflare/references/smart-placement/patterns.md +183 -0
  268. package/skills/cloudflare/references/snippets/README.md +68 -0
  269. package/skills/cloudflare/references/snippets/api.md +198 -0
  270. package/skills/cloudflare/references/snippets/configuration.md +227 -0
  271. package/skills/cloudflare/references/snippets/gotchas.md +86 -0
  272. package/skills/cloudflare/references/snippets/patterns.md +135 -0
  273. package/skills/cloudflare/references/spectrum/README.md +52 -0
  274. package/skills/cloudflare/references/spectrum/api.md +181 -0
  275. package/skills/cloudflare/references/spectrum/configuration.md +194 -0
  276. package/skills/cloudflare/references/spectrum/gotchas.md +145 -0
  277. package/skills/cloudflare/references/spectrum/patterns.md +196 -0
  278. package/skills/cloudflare/references/static-assets/README.md +65 -0
  279. package/skills/cloudflare/references/static-assets/api.md +199 -0
  280. package/skills/cloudflare/references/static-assets/configuration.md +186 -0
  281. package/skills/cloudflare/references/static-assets/gotchas.md +162 -0
  282. package/skills/cloudflare/references/static-assets/patterns.md +189 -0
  283. package/skills/cloudflare/references/stream/README.md +114 -0
  284. package/skills/cloudflare/references/stream/api-live.md +195 -0
  285. package/skills/cloudflare/references/stream/api.md +199 -0
  286. package/skills/cloudflare/references/stream/configuration.md +141 -0
  287. package/skills/cloudflare/references/stream/gotchas.md +130 -0
  288. package/skills/cloudflare/references/stream/patterns.md +184 -0
  289. package/skills/cloudflare/references/tail-workers/README.md +89 -0
  290. package/skills/cloudflare/references/tail-workers/api.md +200 -0
  291. package/skills/cloudflare/references/tail-workers/configuration.md +176 -0
  292. package/skills/cloudflare/references/tail-workers/gotchas.md +192 -0
  293. package/skills/cloudflare/references/tail-workers/patterns.md +180 -0
  294. package/skills/cloudflare/references/terraform/README.md +102 -0
  295. package/skills/cloudflare/references/terraform/api.md +178 -0
  296. package/skills/cloudflare/references/terraform/configuration.md +197 -0
  297. package/skills/cloudflare/references/terraform/gotchas.md +150 -0
  298. package/skills/cloudflare/references/terraform/patterns.md +174 -0
  299. package/skills/cloudflare/references/tunnel/README.md +129 -0
  300. package/skills/cloudflare/references/tunnel/api.md +193 -0
  301. package/skills/cloudflare/references/tunnel/configuration.md +157 -0
  302. package/skills/cloudflare/references/tunnel/gotchas.md +147 -0
  303. package/skills/cloudflare/references/tunnel/networking.md +168 -0
  304. package/skills/cloudflare/references/tunnel/patterns.md +192 -0
  305. package/skills/cloudflare/references/turn/README.md +82 -0
  306. package/skills/cloudflare/references/turn/api.md +239 -0
  307. package/skills/cloudflare/references/turn/configuration.md +179 -0
  308. package/skills/cloudflare/references/turn/gotchas.md +231 -0
  309. package/skills/cloudflare/references/turn/patterns.md +213 -0
  310. package/skills/cloudflare/references/turnstile/README.md +99 -0
  311. package/skills/cloudflare/references/turnstile/api.md +240 -0
  312. package/skills/cloudflare/references/turnstile/configuration.md +222 -0
  313. package/skills/cloudflare/references/turnstile/gotchas.md +218 -0
  314. package/skills/cloudflare/references/turnstile/patterns.md +193 -0
  315. package/skills/cloudflare/references/vectorize/README.md +133 -0
  316. package/skills/cloudflare/references/vectorize/api.md +88 -0
  317. package/skills/cloudflare/references/vectorize/configuration.md +88 -0
  318. package/skills/cloudflare/references/vectorize/gotchas.md +76 -0
  319. package/skills/cloudflare/references/vectorize/patterns.md +90 -0
  320. package/skills/cloudflare/references/waf/README.md +113 -0
  321. package/skills/cloudflare/references/waf/api.md +202 -0
  322. package/skills/cloudflare/references/waf/configuration.md +203 -0
  323. package/skills/cloudflare/references/waf/gotchas.md +204 -0
  324. package/skills/cloudflare/references/waf/patterns.md +197 -0
  325. package/skills/cloudflare/references/web-analytics/README.md +141 -0
  326. package/skills/cloudflare/references/web-analytics/configuration.md +76 -0
  327. package/skills/cloudflare/references/web-analytics/gotchas.md +82 -0
  328. package/skills/cloudflare/references/web-analytics/integration.md +60 -0
  329. package/skills/cloudflare/references/web-analytics/patterns.md +91 -0
  330. package/skills/cloudflare/references/workerd/README.md +78 -0
  331. package/skills/cloudflare/references/workerd/api.md +185 -0
  332. package/skills/cloudflare/references/workerd/configuration.md +183 -0
  333. package/skills/cloudflare/references/workerd/gotchas.md +139 -0
  334. package/skills/cloudflare/references/workerd/patterns.md +192 -0
  335. package/skills/cloudflare/references/workers/README.md +108 -0
  336. package/skills/cloudflare/references/workers/api.md +195 -0
  337. package/skills/cloudflare/references/workers/configuration.md +185 -0
  338. package/skills/cloudflare/references/workers/frameworks.md +197 -0
  339. package/skills/cloudflare/references/workers/gotchas.md +137 -0
  340. package/skills/cloudflare/references/workers/patterns.md +198 -0
  341. package/skills/cloudflare/references/workers-ai/README.md +197 -0
  342. package/skills/cloudflare/references/workers-ai/api.md +112 -0
  343. package/skills/cloudflare/references/workers-ai/configuration.md +97 -0
  344. package/skills/cloudflare/references/workers-ai/gotchas.md +114 -0
  345. package/skills/cloudflare/references/workers-ai/patterns.md +120 -0
  346. package/skills/cloudflare/references/workers-for-platforms/README.md +89 -0
  347. package/skills/cloudflare/references/workers-for-platforms/api.md +196 -0
  348. package/skills/cloudflare/references/workers-for-platforms/configuration.md +167 -0
  349. package/skills/cloudflare/references/workers-for-platforms/gotchas.md +134 -0
  350. package/skills/cloudflare/references/workers-for-platforms/patterns.md +188 -0
  351. package/skills/cloudflare/references/workers-playground/README.md +127 -0
  352. package/skills/cloudflare/references/workers-playground/api.md +101 -0
  353. package/skills/cloudflare/references/workers-playground/configuration.md +163 -0
  354. package/skills/cloudflare/references/workers-playground/gotchas.md +88 -0
  355. package/skills/cloudflare/references/workers-playground/patterns.md +132 -0
  356. package/skills/cloudflare/references/workers-vpc/README.md +127 -0
  357. package/skills/cloudflare/references/workers-vpc/api.md +202 -0
  358. package/skills/cloudflare/references/workers-vpc/configuration.md +147 -0
  359. package/skills/cloudflare/references/workers-vpc/gotchas.md +167 -0
  360. package/skills/cloudflare/references/workers-vpc/patterns.md +209 -0
  361. package/skills/cloudflare/references/workflows/README.md +77 -0
  362. package/skills/cloudflare/references/workflows/api.md +218 -0
  363. package/skills/cloudflare/references/workflows/configuration.md +152 -0
  364. package/skills/cloudflare/references/workflows/gotchas.md +90 -0
  365. package/skills/cloudflare/references/workflows/patterns.md +175 -0
  366. package/skills/cloudflare/references/wrangler/README.md +135 -0
  367. package/skills/cloudflare/references/wrangler/api.md +188 -0
  368. package/skills/cloudflare/references/wrangler/configuration.md +197 -0
  369. package/skills/cloudflare/references/wrangler/gotchas.md +197 -0
  370. package/skills/cloudflare/references/wrangler/patterns.md +209 -0
  371. package/skills/cloudflare/references/zaraz/IMPLEMENTATION_SUMMARY.md +121 -0
  372. package/skills/cloudflare/references/zaraz/README.md +111 -0
  373. package/skills/cloudflare/references/zaraz/api.md +112 -0
  374. package/skills/cloudflare/references/zaraz/configuration.md +90 -0
  375. package/skills/cloudflare/references/zaraz/gotchas.md +81 -0
  376. package/skills/cloudflare/references/zaraz/patterns.md +74 -0
  377. package/skills/cloudflare-email-service/SKILL.md +103 -0
  378. package/skills/cloudflare-email-service/references/cli-and-mcp.md +125 -0
  379. package/skills/cloudflare-email-service/references/deliverability.md +285 -0
  380. package/skills/cloudflare-email-service/references/rest-api.md +184 -0
  381. package/skills/cloudflare-email-service/references/routing.md +199 -0
  382. package/skills/cloudflare-email-service/references/sending.md +252 -0
  383. package/skills/cloudflare-one/SKILL.md +176 -0
  384. package/skills/cloudflare-one-migrations/SKILL.md +110 -0
  385. package/skills/durable-objects/SKILL.md +186 -0
  386. package/skills/durable-objects/references/rules.md +295 -0
  387. package/skills/durable-objects/references/testing.md +264 -0
  388. package/skills/durable-objects/references/workers.md +346 -0
  389. package/skills/sandbox-migrate-to-next/SKILL.md +185 -0
  390. package/skills/sandbox-next/SKILL.md +91 -0
  391. package/skills/sandbox-next/references/api-quick-ref.md +94 -0
  392. package/skills/sandbox-next/references/examples.md +15 -0
  393. package/skills/sandbox-stable/SKILL.md +110 -0
  394. package/skills/turnstile-spin/README.md +51 -0
  395. package/skills/turnstile-spin/SKILL.md +330 -0
  396. package/skills/turnstile-spin/references/astro.md +199 -0
  397. package/skills/turnstile-spin/references/hugo.md +114 -0
  398. package/skills/turnstile-spin/references/nextjs-app.md +261 -0
  399. package/skills/turnstile-spin/references/nextjs-pages.md +82 -0
  400. package/skills/turnstile-spin/references/sveltekit.md +191 -0
  401. package/skills/turnstile-spin/references/vanilla-html.md +157 -0
  402. package/skills/turnstile-spin/scripts/auth-probe.sh +285 -0
  403. package/skills/turnstile-spin/scripts/persist-skill.sh +114 -0
  404. package/skills/turnstile-spin/scripts/validate.sh +137 -0
  405. package/skills/turnstile-spin/scripts/widget-create.sh +121 -0
  406. package/skills/turnstile-spin/tests/validation.md +62 -0
  407. package/skills/workers-best-practices/SKILL.md +127 -0
  408. package/skills/workers-best-practices/references/review.md +174 -0
  409. package/skills/workers-best-practices/references/rules.md +467 -0
  410. package/skills/wrangler/SKILL.md +922 -0
@@ -0,0 +1,199 @@
1
+ # Astro
2
+
3
+ For Astro projects. The widget renders in a page; siteverify lives in an Astro Action, an API route, or a Pages Function. Astro frontmatter reads the sitekey from env at build time; the secret stays server-only.
4
+
5
+ ```astro title="src/pages/signup.astro"
6
+ ---
7
+ const SITEKEY = import.meta.env.PUBLIC_TURNSTILE_SITEKEY;
8
+ ---
9
+
10
+ <html>
11
+ <head>
12
+ <script
13
+ src="https://challenges.cloudflare.com/turnstile/v0/api.js"
14
+ async
15
+ defer
16
+ ></script>
17
+ </head>
18
+ <body>
19
+ <form action="/api/signup" method="POST">
20
+ <input name="email" type="email" required />
21
+ <div
22
+ class="cf-turnstile"
23
+ data-sitekey={SITEKEY}
24
+ data-action="signup"
25
+ />
26
+ <button type="submit">Sign up</button>
27
+ </form>
28
+ </body>
29
+ </html>
30
+ ```
31
+
32
+ In your `.env`:
33
+
34
+ ```text
35
+ PUBLIC_TURNSTILE_SITEKEY=YOUR_SITEKEY
36
+ TURNSTILE_SECRET=YOUR_SECRET
37
+ ```
38
+
39
+ The `PUBLIC_` prefix is mandatory for client-exposed variables in Astro. The secret has **no** prefix; it stays server-only.
40
+
41
+ ## API route (canonical siteverify)
42
+
43
+ ```ts title="src/pages/api/signup.ts"
44
+ import type { APIRoute } from "astro";
45
+
46
+ const expectedHostnames = new Set(
47
+ (import.meta.env.TURNSTILE_HOSTNAMES ?? "")
48
+ .split(",")
49
+ .map((h) => h.trim())
50
+ .filter(Boolean),
51
+ );
52
+
53
+ export const POST: APIRoute = async ({ request, clientAddress }) => {
54
+ const form = await request.formData();
55
+ const token = form.get("cf-turnstile-response");
56
+ if (typeof token !== "string" || expectedHostnames.size === 0) {
57
+ return new Response("forbidden", { status: 403 });
58
+ }
59
+
60
+ const verify = await fetch("https://challenges.cloudflare.com/turnstile/v0/siteverify", {
61
+ method: "POST",
62
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
63
+ body: new URLSearchParams({
64
+ secret: import.meta.env.TURNSTILE_SECRET,
65
+ response: token,
66
+ remoteip: clientAddress,
67
+ }),
68
+ });
69
+ const result = await verify.json();
70
+ if (
71
+ verify.ok !== true ||
72
+ result.success !== true ||
73
+ result.action !== "signup" ||
74
+ !expectedHostnames.has(result.hostname)
75
+ ) {
76
+ return new Response("forbidden", { status: 403 });
77
+ }
78
+
79
+ // process signup
80
+ return Response.json({ ok: true });
81
+ };
82
+ ```
83
+
84
+ ## Variant: Astro Actions
85
+
86
+ If the project uses Astro Actions, call siteverify from the action:
87
+
88
+ ```ts title="src/actions/index.ts"
89
+ import { defineAction } from "astro:actions";
90
+ import { z } from "astro:schema";
91
+
92
+ const expectedHostnames = new Set(
93
+ (import.meta.env.TURNSTILE_HOSTNAMES ?? "")
94
+ .split(",")
95
+ .map((h) => h.trim())
96
+ .filter(Boolean),
97
+ );
98
+
99
+ export const server = {
100
+ signup: defineAction({
101
+ accept: "form",
102
+ input: z.object({
103
+ email: z.string().email(),
104
+ "cf-turnstile-response": z.string(),
105
+ }),
106
+ handler: async (input, ctx) => {
107
+ if (expectedHostnames.size === 0) throw new Error("Verification failed");
108
+ const verify = await fetch("https://challenges.cloudflare.com/turnstile/v0/siteverify", {
109
+ method: "POST",
110
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
111
+ body: new URLSearchParams({
112
+ secret: import.meta.env.TURNSTILE_SECRET,
113
+ response: input["cf-turnstile-response"],
114
+ remoteip: ctx.clientAddress,
115
+ }),
116
+ });
117
+ const result = await verify.json();
118
+ if (
119
+ verify.ok !== true ||
120
+ result.success !== true ||
121
+ result.action !== "signup" ||
122
+ !expectedHostnames.has(result.hostname)
123
+ ) {
124
+ throw new Error("Verification failed");
125
+ }
126
+ // process signup
127
+ },
128
+ }),
129
+ };
130
+ ```
131
+
132
+ `signup` is the stable action for this surface. Preserve an existing custom migration action and compare the returned action to the same value. Siteverify is mandatory for every widget mode, including pre-clearance. Set `TURNSTILE_HOSTNAMES` to the deployment-specific frontend hostnames; a production value must not include `localhost` or `127.0.0.1`.
133
+
134
+ For a client-side Astro Action, replace the native form and script with an explicit widget. Retain this surface's widget ID and reset it in `finally` after every same-page request completion:
135
+
136
+ ```astro
137
+ <form id="signup-action-form">
138
+ <input name="email" type="email" required />
139
+ <div id="signup-action-turnstile" data-sitekey={SITEKEY}></div>
140
+ <button type="submit">Sign up</button>
141
+ </form>
142
+ <script>
143
+ import { actions } from "astro:actions";
144
+
145
+ type TurnstileApi = {
146
+ render: (
147
+ container: HTMLElement,
148
+ options: { sitekey: string; action: string },
149
+ ) => string;
150
+ reset: (widgetId: string) => void;
151
+ };
152
+
153
+ const turnstileWindow = window as Window & { turnstile?: TurnstileApi };
154
+ const form = document.getElementById("signup-action-form") as HTMLFormElement;
155
+ const container = document.getElementById("signup-action-turnstile") as HTMLElement;
156
+ let signupActionWidgetId: string | undefined;
157
+
158
+ const renderWidget = () => {
159
+ if (!turnstileWindow.turnstile) return;
160
+ signupActionWidgetId = turnstileWindow.turnstile.render(container, {
161
+ sitekey: container.dataset.sitekey!,
162
+ action: "signup",
163
+ });
164
+ };
165
+
166
+ if (turnstileWindow.turnstile) {
167
+ renderWidget();
168
+ } else {
169
+ const script = document.createElement("script");
170
+ script.src =
171
+ "https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit";
172
+ script.async = true;
173
+ script.addEventListener("load", renderWidget, { once: true });
174
+ document.head.appendChild(script);
175
+ }
176
+
177
+ form.addEventListener("submit", async (event) => {
178
+ event.preventDefault();
179
+ try {
180
+ const { error } = await actions.signup(new FormData(form));
181
+ if (error) throw error;
182
+ // proceed
183
+ } catch {
184
+ // surface the error
185
+ } finally {
186
+ if (signupActionWidgetId !== undefined) {
187
+ turnstileWindow.turnstile?.reset(signupActionWidgetId);
188
+ }
189
+ }
190
+ });
191
+ </script>
192
+ ```
193
+
194
+ ## Substitutions
195
+
196
+ | Placeholder | Replace with |
197
+ | ------------------- | -------------------------------------------------------------------- |
198
+ | `YOUR_SITEKEY` | The widget site key from Step 8 |
199
+ | `YOUR_SECRET` | The secret captured in Step 8. Stays in env, never inlined. |
@@ -0,0 +1,114 @@
1
+ # Hugo
2
+
3
+ For Hugo static sites. The widget renders on any page that includes the partial; siteverify happens at whatever backend handles your form submissions (a Cloudflare Pages Function, a Worker, an external API, or a form host with a server-side hook).
4
+
5
+ ```html title="layouts/partials/turnstile.html"
6
+ <script
7
+ src="https://challenges.cloudflare.com/turnstile/v0/api.js"
8
+ async
9
+ defer
10
+ ></script>
11
+
12
+ <form action="{{ .Site.Params.turnstileFormEndpoint }}" method="POST">
13
+ <input name="email" type="email" required />
14
+ <div
15
+ class="cf-turnstile"
16
+ data-sitekey="{{ .Site.Params.turnstileSitekey }}"
17
+ data-action="subscribe"
18
+ ></div>
19
+ <button type="submit">Subscribe</button>
20
+ </form>
21
+ ```
22
+
23
+ Add the params to your site config:
24
+
25
+ ```toml title="hugo.toml"
26
+ [params]
27
+ turnstileSitekey = "YOUR_SITEKEY"
28
+ turnstileFormEndpoint = "/api/subscribe" # path to your existing form handler
29
+ ```
30
+
31
+ Reference the partial from any layout or content file:
32
+
33
+ ```text
34
+ {{ partial "turnstile.html" . }}
35
+ ```
36
+
37
+ ## Backend (where siteverify lives)
38
+
39
+ Hugo doesn't host server-side code, so the form endpoint must live elsewhere. Two common setups:
40
+
41
+ **Cloudflare Pages Function** (`functions/api/subscribe.js`):
42
+
43
+ ```js
44
+ export async function onRequestPost({ request, env }) {
45
+ const form = await request.formData();
46
+ const token = form.get("cf-turnstile-response");
47
+
48
+ const expectedHostnames = new Set(
49
+ (env.TURNSTILE_HOSTNAMES ?? "")
50
+ .split(",")
51
+ .map((h) => h.trim())
52
+ .filter(Boolean),
53
+ );
54
+ if (expectedHostnames.size === 0) {
55
+ return new Response("forbidden", { status: 403 });
56
+ }
57
+
58
+ const r = await fetch("https://challenges.cloudflare.com/turnstile/v0/siteverify", {
59
+ method: "POST",
60
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
61
+ body: new URLSearchParams({
62
+ secret: env.TURNSTILE_SECRET,
63
+ response: token,
64
+ remoteip: request.headers.get("CF-Connecting-IP"),
65
+ }),
66
+ });
67
+ const result = await r.json();
68
+ if (
69
+ r.ok !== true ||
70
+ result.success !== true ||
71
+ result.action !== "subscribe" ||
72
+ !expectedHostnames.has(result.hostname)
73
+ ) {
74
+ return new Response("forbidden", { status: 403 });
75
+ }
76
+
77
+ // process subscribe
78
+ return new Response("ok");
79
+ }
80
+ ```
81
+
82
+ `subscribe` is the stable action for this surface. Preserve an existing custom migration action and compare the returned action to the same value. Siteverify is mandatory for every widget mode, including pre-clearance. Set `TURNSTILE_HOSTNAMES` to the deployment-specific frontend hostnames; a production value must not include `localhost` or `127.0.0.1`.
83
+
84
+ After the user approves a canonical absolute `WRANGLER_BIN` outside the project, set the secret with `(set +x; printf '%s' "$WIDGET_SECRET" | "$WRANGLER_BIN" pages secret put TURNSTILE_SECRET)` (or use the dashboard's Pages → your project → Settings → Environment variables → Add secret).
85
+
86
+ **External backend**: any Node/Ruby/Python/Go handler can do the same call. See the [vanilla-html reference](./vanilla-html.md) for non-Cloudflare-specific snippets.
87
+
88
+ ## Variant: shortcode for content files
89
+
90
+ If you want to drop the widget into Markdown content (not just layouts), create a shortcode:
91
+
92
+ ```html title="layouts/shortcodes/turnstile-form.html"
93
+ {{ partial "turnstile.html" . }}
94
+ ```
95
+
96
+ Use in content:
97
+
98
+ ```markdown title="content/contact.md"
99
+ ---
100
+ title: Contact
101
+ ---
102
+
103
+ Contact us:
104
+
105
+ {{< turnstile-form >}}
106
+ ```
107
+
108
+ ## Substitutions
109
+
110
+ | Placeholder | Replace with |
111
+ | ------------------------ | -------------------------------------------------------------------- |
112
+ | `YOUR_SITEKEY` | The widget site key from Step 8 |
113
+ | `turnstileFormEndpoint` | The path or URL to your form handler (Pages Function, Worker, etc.) |
114
+ | `TURNSTILE_SECRET` | Env-var name in your backend. Value is the secret captured in Step 8.|
@@ -0,0 +1,261 @@
1
+ # Next.js (App Router)
2
+
3
+ For `app/`-directory Next.js projects. The widget needs to run on the client, so the page or component must be `"use client"`. The siteverify call lives server-side, either in a Server Action or an API route.
4
+
5
+ ```tsx title="app/signup/page.tsx"
6
+ "use client";
7
+ import Script from "next/script";
8
+ import { type FormEvent, useRef, useState } from "react";
9
+
10
+ type TurnstileWidgetId = string;
11
+ type TurnstileApi = {
12
+ render: (
13
+ container: HTMLElement,
14
+ options: {
15
+ sitekey: string;
16
+ action: string;
17
+ callback: (token: string) => void;
18
+ },
19
+ ) => TurnstileWidgetId;
20
+ reset: (widgetId: TurnstileWidgetId) => void;
21
+ };
22
+
23
+ declare global {
24
+ interface Window {
25
+ turnstile: TurnstileApi;
26
+ }
27
+ }
28
+
29
+ export default function SignupPage() {
30
+ const turnstileContainer = useRef<HTMLDivElement>(null);
31
+ const signupWidgetId = useRef<TurnstileWidgetId | null>(null);
32
+ const [token, setToken] = useState("");
33
+
34
+ function renderTurnstile() {
35
+ if (!turnstileContainer.current || signupWidgetId.current !== null) return;
36
+ signupWidgetId.current = window.turnstile.render(turnstileContainer.current, {
37
+ sitekey: "YOUR_SITEKEY",
38
+ action: "signup",
39
+ callback: setToken,
40
+ });
41
+ }
42
+
43
+ async function handleSubmit(e: FormEvent<HTMLFormElement>) {
44
+ e.preventDefault();
45
+ try {
46
+ const res = await fetch("/api/signup", {
47
+ method: "POST",
48
+ headers: { "Content-Type": "application/json" },
49
+ body: JSON.stringify({ token }),
50
+ });
51
+ const data = await res.json();
52
+ if (!res.ok || data.ok !== true) throw new Error("Submission failed");
53
+ // proceed
54
+ } catch {
55
+ // surface the error
56
+ } finally {
57
+ if (signupWidgetId.current !== null) {
58
+ window.turnstile.reset(signupWidgetId.current);
59
+ setToken("");
60
+ }
61
+ }
62
+ }
63
+
64
+ return (
65
+ <>
66
+ <Script
67
+ src="https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit"
68
+ strategy="afterInteractive"
69
+ onReady={renderTurnstile}
70
+ />
71
+ <form onSubmit={handleSubmit}>
72
+ <input name="email" type="email" required />
73
+ <div ref={turnstileContainer} />
74
+ <button type="submit" disabled={!token}>
75
+ Sign up
76
+ </button>
77
+ </form>
78
+ </>
79
+ );
80
+ }
81
+ ```
82
+
83
+ Explicit rendering returns the widget ID for this surface. The `finally` block resets that ID after network, JSON, validation, server, or successful same-page completion.
84
+
85
+ API route (canonical siteverify):
86
+
87
+ ```ts title="app/api/signup/route.ts"
88
+ const expectedHostnames = new Set(
89
+ (process.env.TURNSTILE_HOSTNAMES ?? "")
90
+ .split(",")
91
+ .map((h) => h.trim())
92
+ .filter(Boolean),
93
+ );
94
+
95
+ export async function POST(req: Request) {
96
+ const { token } = await req.json();
97
+ const remoteip = req.headers.get("x-forwarded-for") ?? undefined;
98
+
99
+ if (expectedHostnames.size === 0) {
100
+ return new Response("forbidden", { status: 403 });
101
+ }
102
+
103
+ const r = await fetch("https://challenges.cloudflare.com/turnstile/v0/siteverify", {
104
+ method: "POST",
105
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
106
+ body: new URLSearchParams({
107
+ secret: process.env.TURNSTILE_SECRET!,
108
+ response: token,
109
+ ...(remoteip ? { remoteip } : {}),
110
+ }),
111
+ });
112
+ const result = await r.json();
113
+ if (
114
+ r.ok !== true ||
115
+ result.success !== true ||
116
+ result.action !== "signup" ||
117
+ !expectedHostnames.has(result.hostname)
118
+ ) {
119
+ return new Response("forbidden", { status: 403 });
120
+ }
121
+
122
+ // existing signup logic runs here
123
+ return Response.json({ ok: true });
124
+ }
125
+ ```
126
+
127
+ `signup` is the stable action for this surface. Preserve an existing custom migration action and compare the returned action to the same value. Siteverify is mandatory for every widget mode, including pre-clearance. Set `TURNSTILE_HOSTNAMES` to the deployment-specific frontend hostnames; a production value must not include `localhost` or `127.0.0.1`.
128
+
129
+ ## Variant: Server Action
130
+
131
+ If you are using Server Actions, do the siteverify call from the action itself. The widget still goes in a client component, but the verify call moves server-side:
132
+
133
+ ```tsx title="app/signup/actions.ts"
134
+ "use server";
135
+ import { headers } from "next/headers";
136
+
137
+ export type SignupState = { ok?: true; error?: string } | null;
138
+
139
+ const expectedHostnames = new Set(
140
+ (process.env.TURNSTILE_HOSTNAMES ?? "")
141
+ .split(",")
142
+ .map((h) => h.trim())
143
+ .filter(Boolean),
144
+ );
145
+
146
+ export async function submitSignup(
147
+ _previousState: SignupState,
148
+ formData: FormData,
149
+ ): Promise<SignupState> {
150
+ const token = formData.get("cf-turnstile-response");
151
+ if (typeof token !== "string") return { error: "Verification failed" };
152
+ if (expectedHostnames.size === 0) return { error: "Verification failed" };
153
+ const remoteip = (await headers()).get("x-forwarded-for") ?? undefined;
154
+
155
+ const r = await fetch("https://challenges.cloudflare.com/turnstile/v0/siteverify", {
156
+ method: "POST",
157
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
158
+ body: new URLSearchParams({
159
+ secret: process.env.TURNSTILE_SECRET!,
160
+ response: token,
161
+ ...(remoteip ? { remoteip } : {}),
162
+ }),
163
+ });
164
+ const result = await r.json();
165
+ if (
166
+ r.ok !== true ||
167
+ result.success !== true ||
168
+ result.action !== "signup" ||
169
+ !expectedHostnames.has(result.hostname)
170
+ ) {
171
+ return { error: "Verification failed" };
172
+ }
173
+
174
+ // process signup
175
+ return { ok: true };
176
+ }
177
+ ```
178
+
179
+ ```tsx title="app/signup/page.tsx (server-action variant)"
180
+ "use client";
181
+ import Script from "next/script";
182
+ import { useActionState, useRef, useState } from "react";
183
+ import { submitSignup, type SignupState } from "./actions";
184
+
185
+ type TurnstileWidgetId = string;
186
+ type TurnstileApi = {
187
+ render: (
188
+ container: HTMLElement,
189
+ options: {
190
+ sitekey: string;
191
+ action: string;
192
+ callback: (token: string) => void;
193
+ },
194
+ ) => TurnstileWidgetId;
195
+ reset: (widgetId: TurnstileWidgetId) => void;
196
+ };
197
+
198
+ declare global {
199
+ interface Window {
200
+ turnstile: TurnstileApi;
201
+ }
202
+ }
203
+
204
+ export default function SignupPage() {
205
+ const turnstileContainer = useRef<HTMLDivElement>(null);
206
+ const signupActionWidgetId = useRef<TurnstileWidgetId | null>(null);
207
+ const [token, setToken] = useState("");
208
+ const [state, action, pending] = useActionState(
209
+ async (previousState: SignupState, formData: FormData) => {
210
+ try {
211
+ return await submitSignup(previousState, formData);
212
+ } finally {
213
+ if (signupActionWidgetId.current !== null) {
214
+ window.turnstile.reset(signupActionWidgetId.current);
215
+ setToken("");
216
+ }
217
+ }
218
+ },
219
+ null,
220
+ );
221
+
222
+ function renderTurnstile() {
223
+ if (!turnstileContainer.current || signupActionWidgetId.current !== null) return;
224
+ signupActionWidgetId.current = window.turnstile.render(
225
+ turnstileContainer.current,
226
+ {
227
+ sitekey: "YOUR_SITEKEY",
228
+ action: "signup",
229
+ callback: setToken,
230
+ },
231
+ );
232
+ }
233
+
234
+ return (
235
+ <>
236
+ <Script
237
+ src="https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit"
238
+ strategy="afterInteractive"
239
+ onReady={renderTurnstile}
240
+ />
241
+ <form action={action}>
242
+ <input name="email" type="email" required />
243
+ <div ref={turnstileContainer} />
244
+ {state?.error && <p role="alert">{state.error}</p>}
245
+ <button type="submit" disabled={!token || pending}>
246
+ Sign up
247
+ </button>
248
+ </form>
249
+ </>
250
+ );
251
+ }
252
+ ```
253
+
254
+ Server Actions can return state without navigating. This wrapper accepts `previousState` before `FormData` and resets the retained widget ID in `finally`, including validation, server, and network failures.
255
+
256
+ ## Substitutions
257
+
258
+ | Placeholder | Replace with |
259
+ | ------------------- | -------------------------------------------------------------------- |
260
+ | `YOUR_SITEKEY` | The widget site key from Step 8 |
261
+ | `TURNSTILE_SECRET` | Env-var name. Value is the secret captured in Step 8, kept off disk. |
@@ -0,0 +1,82 @@
1
+ # Next.js (Pages Router)
2
+
3
+ For older Next.js projects using `pages/` rather than `app/`. The widget renders client-side; siteverify lives in the API route.
4
+
5
+ ```tsx title="pages/signup.tsx"
6
+ import Script from "next/script";
7
+
8
+ export default function SignupPage() {
9
+ return (
10
+ <>
11
+ <Script src="https://challenges.cloudflare.com/turnstile/v0/api.js" />
12
+ <form action="/api/signup" method="POST">
13
+ <input name="email" type="email" required />
14
+ <div
15
+ className="cf-turnstile"
16
+ data-sitekey="YOUR_SITEKEY"
17
+ data-action="signup"
18
+ />
19
+ <button type="submit">Sign up</button>
20
+ </form>
21
+ </>
22
+ );
23
+ }
24
+ ```
25
+
26
+ This native form navigates to the API response, so it does not need client-side reset code.
27
+
28
+ API route (canonical siteverify):
29
+
30
+ ```ts title="pages/api/signup.ts"
31
+ import type { NextApiRequest, NextApiResponse } from "next";
32
+
33
+ const expectedHostnames = new Set(
34
+ (process.env.TURNSTILE_HOSTNAMES ?? "")
35
+ .split(",")
36
+ .map((h) => h.trim())
37
+ .filter(Boolean),
38
+ );
39
+
40
+ export default async function handler(
41
+ req: NextApiRequest,
42
+ res: NextApiResponse,
43
+ ) {
44
+ const token = req.body["cf-turnstile-response"] ?? req.body.token;
45
+ if (expectedHostnames.size === 0) {
46
+ return res.status(403).json({ error: "Verification failed" });
47
+ }
48
+ const remoteip =
49
+ (req.headers["x-forwarded-for"] as string | undefined)?.split(",")[0] ??
50
+ req.socket.remoteAddress;
51
+
52
+ const verify = await fetch("https://challenges.cloudflare.com/turnstile/v0/siteverify", {
53
+ method: "POST",
54
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
55
+ body: new URLSearchParams({
56
+ secret: process.env.TURNSTILE_SECRET!,
57
+ response: token,
58
+ ...(remoteip ? { remoteip } : {}),
59
+ }),
60
+ });
61
+ const result = await verify.json();
62
+ if (
63
+ verify.ok !== true ||
64
+ result.success !== true ||
65
+ result.action !== "signup" ||
66
+ !expectedHostnames.has(result.hostname)
67
+ ) {
68
+ return res.status(403).json({ error: "Verification failed" });
69
+ }
70
+ // process signup
71
+ return res.json({ ok: true });
72
+ }
73
+ ```
74
+
75
+ `signup` is the stable action for this surface. Preserve an existing custom migration action and compare the returned action to the same value. Siteverify is mandatory for every widget mode, including pre-clearance. Set `TURNSTILE_HOSTNAMES` to the deployment-specific frontend hostnames; a production value must not include `localhost` or `127.0.0.1`.
76
+
77
+ ## Substitutions
78
+
79
+ | Placeholder | Replace with |
80
+ | ------------------- | -------------------------------------------------------------------- |
81
+ | `YOUR_SITEKEY` | The widget site key from Step 8 |
82
+ | `TURNSTILE_SECRET` | Env-var name. Value is the secret captured in Step 8, kept off disk. |