> ## Documentation Index
> Fetch the complete documentation index at: https://docs.heretic.tech/llms.txt
> Use this file to discover all available pages before exploring further.

# Next.js and PostgreSQL

> Run a complete background-measurement and protected-action integration.

This example uses Next.js App Router, Node 22+ and PostgreSQL 14+. It works on a normal Node host; no additional CDN or Kubernetes service is required.

[Download the complete example](https://heretic.tech/downloads/heretic-next-postgres-0.1.3.zip). It includes the integration package, application source, migration, configuration and local fixtures under the MIT license.

## Choose an example

| Example                                                   | Open locally | What it demonstrates                                                               |
| --------------------------------------------------------- | ------------ | ---------------------------------------------------------------------------------- |
| Allocation redemption                                     | `/`          | One-per-account eligibility, identifier comparisons and limited allocations.       |
| [Account registration](/integration/account-registration) | `/register`  | A pending server-owned identity before sign-in and transactional account creation. |
| [Protected checkout](/integration/protected-checkout)     | `/checkout`  | Server prices, stock allocation and an order with a payment outbox entry.          |

All three use the same SDK, server adapter and prepared browser measurement. The rules in `lib/actions.mjs` are sample customer policies that you can replace.

## Run locally

Start a disposable local PostgreSQL database:

```sh theme={"dark"}
docker run --rm --name heretic-example-postgres \
  -e POSTGRES_HOST_AUTH_METHOD=trust \
  -p 127.0.0.1:55431:5432 postgres:17
```

Extract the archive. From its `heretic-next-postgres` directory, in another terminal:

```sh theme={"dark"}
npm install
cp .env.example .env
npm run setup
npm run dev
```

Open `http://localhost:3300`. Choose a local account and redeem WELCOME. The example records one completed allocation in PostgreSQL. Reloading reuses the measurement; redeeming the same resource on the same account is refused by the example policy. LIMITED has one allocation for concurrency testing.

The fixture's ceremony is clearly labelled and collects no real device data. To exercise it, set `HERETIC_FIXTURE_VERDICT=contradicted` in `.env`, restart, and use a fresh browser session. Background preparation stays quiet; submitting an action opens the fixture. Set `HERETIC_FIXTURE_DELAY_MS=5000` to exercise an early submission while measurement is pending.

`npm run setup` preserves existing allocations. Use a fresh disposable database for a fresh inventory. Stop the example database with `docker stop heretic-example-postgres`.

## Application files

| File                                                             | Purpose                                                                                                |
| ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| `components/integration.jsx`                                     | Initializes the browser client once and supplies it to the app.                                        |
| `app/api/heretic/[...path]/route.js`                             | Mounts the Node server adapter.                                                                        |
| `lib/integration.mjs`                                            | Resolves application context and mounts the adapter.                                                   |
| `lib/actions.mjs`                                                | Defines validation, eligibility and transactional writes for all three actions.                        |
| `app/page.jsx`, `app/register/page.jsx`, `app/checkout/page.jsx` | Forms for redemption, registration and checkout.                                                       |
| `components/use-action.js`                                       | Preserves attempts on retry and displays recoverable errors.                                           |
| `app/api/demo/registration/route.js`                             | Creates or reuses a pending registration in a server session.                                          |
| `sql/example.sql`                                                | Local accounts, sessions, pending registrations, allocations, products, orders and the payment outbox. |

The catch-all route is small because the package handles the continuation protocol:

```js theme={"dark"}
import { handler } from '../../../../lib/integration.mjs';

export const runtime = 'nodejs';
export const dynamic = 'force-dynamic';
export const GET = request => handler().handle(request);
export const POST = request => handler().handle(request);
```

`handler()` and the provider implementation are included in the archive. Use them with the [action contract](/integration/protected-actions) rather than creating your own token parser or polling loop.

## Connect production authentication

The local account chooser, session implementation and fixed test address are fixture-only. The example refuses production context until you replace its `appContext(request)` function.

Return the current authenticated account ID, authenticated session ID and trusted request IP from your actual application. Registration uses a server-owned pending principal until the account exists; other actions must require an authenticated session. See the [registration example](/integration/account-registration). Do not take the account ID from the action body. Confirm which proxy supplies client addresses and which hops are trusted. Call `client.status()` after an authentication change so the SDK updates its opaque context.

Replace the example resource, eligibility and commit SQL with your existing application tables. All writes in `commit` use the supplied transaction client. Choose a shared resource key that covers the accounts competing for the same constrained resource.

The local registration flow creates a record without proving email ownership or signing in. The checkout flow stops at a payment outbox entry. Connect your authentication provider and payment processing, including delivery, reconciliation and cancellation, before using those examples in production.

## Configure production

Set a verified real site key and server secret, an HTTPS `APP_ORIGIN`, your PostgreSQL connection settings, and `HERETIC_FIXTURE_MODE=false`. Use the default Heretic API origin. Keep secrets on the server. Run the package migration and diagnostic command, then verify the browser's [CSP and preparation](/integration/prepare-session#content-security-policy).

Use a pool sized for your deployment. Pending actions, evidence and receipts live in PostgreSQL, so another application instance can continue them after a restart. The in-process pool and key cache are not the source of action authorization.

Before enabling enforcement, test a normal action, duplicate request, account switch, expired measurement, declined/dismissed ceremony and concurrent inventory claim. Keep the example's fixture mode restricted to loopback hosts. It must never authorize production traffic.


## Related topics

- [Protected checkout](/integration/protected-checkout.md)
- [Prepare a session](/integration/prepare-session.md)
- [Account registration](/integration/account-registration.md)
- [Next.js](/integration/nextjs.md)
- [Protect an action](/integration/protected-actions.md)
