Quickstart
Next.js quickstart
Package @camada/next, on npm.
1. Install
npm i @camada/next2. Environment
The key is printed once when you create a project in the app.
CAMADA_KEY=<ingest_token>.<snap_token>
CAMADA_INGEST_URL=http://localhost:8787 # dev only; defaults to production ingest3. Wire it in
// middleware.ts (Next ≤15) or proxy.ts (Next 16) at the project root
import { camada } from '@camada/next';
export default camada();
export const config = { matcher: ['/((?!_next/|favicon.ico).*)'] };
// app/api/camada/[...camada]/route.ts
import { camadaRoute } from '@camada/next';
export const { GET, POST } = camadaRoute();
// app/layout.tsx, inside <head>
import { CamadaBeacon } from '@camada/next';
<CamadaBeacon />- App router. Three files, one env var.
- On Vercel the middleware sees x-vercel-ja4-digest, a real TLS fingerprint, and Vercel's X-Forwarded-For is trusted by default.
- Events ship before the response, so status is unknown at this position. Blocked requests ship with 403.
- Keep the matcher as broad as the example. Every route it excludes is invisible to camada.
4. Send app outcomes
Login failures, signups and checkout declines are the signals no edge position sees. The identifier is HMAC-hashed in your process. How they catch credential stuffing.
import { track } from '@camada/next';
// server action, route handler or server component
await track('login_failed', { user: email });Runtime
What it does per request
- Refreshes the blocklist snapshot off-path in event.waitUntil.
- Enforces it inline: a matching IP or path gets a 403 with x-block-reason and x-block-version. Blocked requests always ship as events.
- Stamps x-camada-rid on the forwarded request and x-rid on the response.
- Ships the wire event before the response, so status is unknown (except 403 on blocks). On Vercel the JA4 digest rides along.
- The route handler serves /api/camada/b.js first-party and relays /api/camada/fp beacon posts to ingest with the trusted-proxy-resolved IP.
Limits
Caveats at this position
- Client IP needs a trusted-proxy setting. Middleware has no socket peer, so without one the IP is null and IP rules do not enforce. On Vercel the default is the Vercel preset.
- Header order is alphabetical at this position; the scorer knows and does not apply order rules here.
- Serverless cold start fails open: the first request on a cold instance passes, then enforcement begins.
- track() works from request scope only and must not be called from middleware.
- Every route your matcher excludes is invisible to camada: no blocking, no events. Keep it as broad as the example.
Kill switch: CAMADA_DISABLED=1, checked per request. All other variables are listed in the docs index.