fresh-turnstile
Cloudflare Turnstile plugin for Deno Fresh.
Installation
First of all, create your fresh app.
Add Turnstile to your import_map.json.
{
"imports": {
"$turnstile/": "https://deno.land/x/fresh_turnstile@1.0.1-0/"
}
}Consume the Turnstile plugin in your app’s main.ts.
import { TurnstilePlugin } from "$turnstile/index.ts";
await start(manifest, {
plugins: [
// ...
TurnstilePlugin(),
// ...
],
});Client-side Rendering
Implicit Rendering
Protecting a form
Add <CfTurnstile sitekey="..." /> inside your form. A hidden input named cf-turnstile-response will be added to your form with the token value once a
response is received from Turnstile. See the instructions in the server-side validation section further below for easy server-side
handling.
Please note that if you use AJAX / fetch to submit the form, you will need to call getTurnstileAsync() to get access to the turnstile object and then
invokes turnstile.reset(widgetId) to get a fresh token. See the section on explicit rendering below for more instructions on how to get
access to the turnstile object. The id attribute you provide to <CfTurnstile /> gets passthrough directly to the widget, so you can use that ID as
widgetId in turnstile.getResponse(widgetId) and turnstile.reset(widgetId).
Protecting a page
You can add the callback, errorCallback, and expiredCallback props on <CfTurnstile /> and dynamically handle these events.
The following code sample displays the response token on the page when it’s received from Turnstile.
import { useSignal } from "@preact/signals";
// ...
const response = useSignal("Waiting for validation...");
// ...
<CfTurnstile sitekey={sitekey} {...props} callback={(token) => response.value = token} />
<pre>{response}</pre>Note: for implicit rendering, the official docs describe
data-callback, data-error-callback, and data-expired-callback as strings (function names) that get invoked later. However, this plugin makes uses of
useId and useEffect hooks to allow you to provide the callable props directly to callback, errorCallback, and expiredCallback.
Disable implicit rendering
Add the disableImplicitRendering option to your plugin declaration. (See the installation section above again for more information.)
await start(manifest, {
plugins: [
// ...
TurnstilePlugin({ disableImplicitRendering: true }),
// ...
],
});Once you have disabled implicit rendering, see the next section to explicitly render your Turnstile widgets.
Explicit Rendering
You can get the turnstile global object from inside a useEffect hook like this:
import { useEffect } from "preact/hooks";
import { getTurnstileAsync } from "$turnstile/plugin.ts";
//...
useEffect(() => {
getTurnstileAsync().then((turnstile) => {
// console.log(turnstile);
});
});Or you can directly use the useTurnstileEffect hook:
import { useTurnstileEffect } from "$turnstile/plugin.ts";
// ...
useTurnstileEffect((turnstile) => {
// console.log(turnstile);
});Once you have got ahold of the turnstile object within an effect hook, you can now call turnstile.render(...) similar to how it is shown in
official docs.
Server-side Validation
fresh-turnstile provides a default POST handler for easy server-side form validations.
You may use it like this in your route:
import { CfTurnstileValidationResult, generatePostHandler } from "$turnstile/handlers/CfTurnstileValidation.ts";
import Page from "$flowbite/components/Page.tsx";
export const handler = { POST: generatePostHandler(cf_turnstile_secret_key) };
export default function CfTurnstileValidation({ data }: PageProps<CfTurnstileValidationResult | null>) {
/* 3 scenarios can occur here:
* 1. data is null => the form was not submitted correctly, or the secret key was not provided.
* 2. data.success is false => the form was submitted correctly, but validation failed. data["error-codes"] should be a list of error codes (as strings).
* 3. data.success is true => the form was submitted correctly and validated successfully. data.challenge_ts and data.hostname should be available for inspection.
*/
}A note about versioning
For now, the versions are a.b.c-x.y.z where a.b.c is the plugin version and x.y.z is the supported Turnstile API version. For example, 0.0.1-0 is the
initial release of plugin, which supports Turnstile API v0.
All tags starting with 0.0. are mutable. Expect breaking changes! Starting from 0.1., tags will be immutable. However, still expect breaking
changes. Starting from 1., semver will kick in and there will be no breaking changes until 2..