Skip to main content
This /check route serves the widget form and saves one receipt after server verification. The complete example uses Node 24+ with adapter-node and persistent SQLite storage.

Install the example

Download the server examples. Put the extracted directory at src/lib/server/server-examples, then add src/routes/check/+server.js:
The SvelteKit server route returns a plain HTML form on GET and checks its POST. The code and secret stay in server-only modules. Copy the archive’s .env.example into your app’s private environment. Set APP_ORIGIN=http://localhost:5173 for Vite’s default development port. Run your app and open /check. The supplied test keys save a receipt without running measurements or a phone ceremony. For production, use your verified site’s keys, set HERETIC_ALLOW_TEST=false, and set APP_ORIGIN to the exact HTTPS origin. With adapter-node, configure SvelteKit’s ORIGIN to the same value when serving behind your reverse proxy.

Keep the backend check

The shared handler checks Origin and the HttpOnly browser-session cookie, then verifies the token against the saved attempt ID, action, site and hostname. It chooses policy: "uncontradicted" on the server. The widget attributes control presentation; the backend chooses what proof authorizes the write. Failures return an error page. A network timeout leaves the action pending, and the same submission can be retried. A completed attempt returns its existing receipt. Test proofs are rejected outside explicit local test mode. Replace the receipt write in examples/lib/form-flow.mjs with your business write in the same transaction. Save the authenticated account and operation data with the attempt when your action needs them.

Use your deployment’s database

The bundled store needs persistent local storage. A Cloudflare or other serverless adapter needs your shared database’s transaction and unique constraint in place of SQLite. The Node API client uses fetch and can run separately from the Node-specific example store. The example returns Cache-Control: no-store and a CSP that permits Heretic scripts and frames. Merge those sources into your existing page policy when moving the form into a Svelte component. For explicit widget rendering during client navigation, remove the widget when the component unmounts using heretic.remove().