Server
Reading flags from Node, Bun, or a Worker, with a private key that also sees sensitive flags.
Creating a client
The server entrypoint imports no React and touches no browser globals. Create one client per process and reuse it; it keeps a snapshot in memory and revalidates in the background.
import { createKlorServerClient } from '@klor/react/server'
export const klor = createKlorServerClient({
apiKey: process.env.KLOR_SECRET_KEY,
ttlMs: 30_000,
})There is no polling timer. The first call in a cold process awaits a fetch; later calls serve from memory and revalidate in the background once past the TTL, so request latency stays flat.
Reading a flag
const newCheckout = await klor.getFlag('checkout_v2', false, {
userId: user.id,
attributes: { platform: 'web', country: user.country },
})The context argument is the same shape the React provider takes, so a rule written for the app behaves identically here.
Everything at once
Useful for handing a fully evaluated set to a client.
const flags = await klor.getAllFlags({ userId: user.id })
// { checkout_v2: true, max_basket_items: 25 }Sensitive flags
A private key sees flags marked sensitive, which are stripped from every public payload. Use it for anything you would not want read out of a decompiled binary: margins, internal thresholds, partner identifiers.
If you pass a snapshot from a private-key client into a browser, you have just published those flags. Fetch with a public key for anything that crosses to the client.
Update gating on the server
Same verdicts as the device, for an API that wants to refuse an ancient client.
const gate = await klor.getVersionGate('ios', request.headers['x-app-version'])
if (gate.status === 'forced') {
return reply.code(426).send({ message: gate.message })
}