/check route to run the widget and save one receipt after server verification. It uses Node 24+ and persistent SQLite storage. The server client can also be used with your application’s existing database.
Install the example
Download the server examples and put the extractedserver-examples directory beside your app’s app directory. Add app/check/route.js:
/check free of a page.js; the handler owns that route. If your app uses src/app, put server-examples beside src/app instead.
Copy the archive’s .env.example values into your app’s .env.local. Run your app’s usual development command and open http://127.0.0.1:3000/check. Keep the secret in server-only environment variables; do not use a NEXT_PUBLIC_ prefix.
The initial values use test keys and save a local receipt without real measurements. Follow the production key setup to run real checks on your verified domain.
Bind verification to the action
The shared handler sets an HttpOnly SameSite cookie and saves an attempt before renderingdata-cdata. It verifies the token against that attempt’s hostname, site, action and ID. Server policy is uncontradicted; change it together with the widget presentation if your action requires a different policy.
Verification failures return 403. Missing proof returns 400. An unavailable API returns 503 and leaves the action pending. Retries use the same token and idempotency key; a completed attempt returns the existing receipt.
Replace the receipt write in examples/lib/form-flow.mjs with your business write in the same transaction. Bind your authenticated user and the operation’s data to the pending record. The example’s random cookie identifies a browser session, not an account.
Deployment
Keep the Node runtime. SQLite needs a persistent writable disk; a temporary serverless filesystem cannot preserve the single-use guarantee. On serverless or multiple hosts, keep the client and move the attempt/write transaction into your shared database. The handler sendsCache-Control: no-store and a CSP that allows Heretic scripts and frames. Merge the CSP sources into your app’s policy if you move the form into an existing page. The widget script API supports explicit rendering for client-side navigation.