Quickstart
Identify your first user and pass them to Gates in under a minute.
1. Get a key
Identity syncs every change to People, so createIdentity requires an apiKey. Any key granted people:identify works:
- In the browser — the publishable client key (
ck_client_…) from Settings → API keys. It's safe to ship: it is write-only and can never read profile data back. - On a server — your People server key or a scoped key.
2. Install
pnpm add @lucerna-dev/identitynpm install @lucerna-dev/identitybun add @lucerna-dev/identity3. Create one identity
In the browser there's one user, so create one shared instance in a module of its own:
// identity.ts
import { createIdentity } from "@lucerna-dev/identity";
export const identity = createIdentity({
apiKey: import.meta.env.VITE_LUCERNA_CLIENT_KEY,
});A new identity starts anonymous with a stable anon_… id — Gates rollouts and experiment variants are already sticky for logged-out visitors, before any wiring.
4. Identify on login
When the user signs in, tell identity who they are:
identity.identify({
userId: "u_42", // your app's id — never an email
email: "ada@example.com", // PII: routed to encrypted People fields
name: "Ada Lovelace",
traits: { plan: "pro" }, // targeting data: no PII here
});
identity.trait("beta", true); // update one trait laterThat's the whole write path: every change upserts the person to People in the background — fire-and-forget, batched, never blocking your code. The userId/traits split matters for GDPR — read the two rules before shipping.
5. Pass it everywhere
Every Lucerna SDK accepts the same object:
// Browser — Gates subscribes and refetches decisions on every change:
const gates = createGates({ clientKey, identity });
// Server — pass a snapshot per check:
gates.flag("new_billing", identity.current());6. Reset on logout
identity.reset();Traits are cleared and a fresh anonymous id is minted, so two people on one device are never linked.
Persisting across page loads
By default nothing touches the device — the anonymous id lives for the session. To keep it across reloads, wire storage after the user consents (a persisted id counts like a cookie under GDPR):
const identity = createIdentity({ apiKey, storage: localStorage });One identity per request on servers
In the browser, one shared identity is right — there's one user. On a server, create the identity inside the request handler: a module-level identity would target every request as the same user.
Next
- Reference — every option and method.
- Privacy & GDPR — the PII rules and the erasure endpoint.
- Gates browser quickstart — put the identity to work.