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

# Evaluate flags in your app

> Create a shipdit client, wait for ready(), and read flags in memory.

## Overview

Jordan wires Fieldkit's API to shipd. Flag checks are in-memory. The network is only for downloading the **snapshot** (evaluation payload) and optional realtime invalidation.

This guide uses the flags from [Define flags in code](/guides/define-flags).

## Install

```bash theme={null}
pnpm add shipdit
```

Create a **server** SDK key in the dashboard. It looks like `shipd_sdk_server_…` and is shown once.

## Server (Node, workers)

```ts src/lib/shipd.ts theme={null}
import { createClient } from "shipdit";
import type { FlagDefinitions } from "./generated/flags";

export const shipd = createClient<FlagDefinitions>({
  sdkKey: process.env.SHIPD_SDK_KEY!,
  endpoint: process.env.SHIPD_EDGE_URL ?? "https://edge.useshipd.com",
  streamEndpoint: process.env.SHIPD_WS_URL, // e.g. https://ws.useshipd.com
  defaults: {
    "new-checkout": false,
    "search-variant": "control",
    "max-retries": 3,
    "checkout-payload": { mode: "strict", showPromo: true },
  },
});
```

```ts src/checkout.ts theme={null}
import { shipd } from "./lib/shipd";

await shipd.ready();

export function pickCheckout(userId: string) {
  if (shipd.isEnabled("new-checkout", { userId })) {
    return "new";
  }
  return "legacy";
}

export function searchEngine(userId: string) {
  return shipd.getVariant("search-variant", { userId });
  // ^? "control" | "semantic" | "hybrid"
}

export function retryBudget() {
  return shipd.getNumber("max-retries");
}

export function checkoutUi() {
  return shipd.getJson("checkout-payload");
}
```

`ready()` never rejects for network errors. On timeout it resolves anyway and you serve `defaults` until a snapshot arrives.

## Browser

```ts src/lib/shipd-browser.ts theme={null}
import { createClient } from "shipdit/client";
import type { FlagDefinitions } from "./generated/flags";

export const shipd = createClient<FlagDefinitions>({
  sdkKey: "shipd_sdk_client_…",
  endpoint: "https://edge.useshipd.com",
  streamEndpoint: "https://ws.useshipd.com",
  defaults: { "new-checkout": false, "search-variant": "control" },
});

await shipd.ready();
```

Browser clients persist the last good snapshot (and a stable `anonymousId`) in `localStorage` unless you pass `persist: false`.

<Note>
  Client and server keys currently receive the same targeting rules. Prefer server keys for backends. Client keys are safe to embed; reduced client snapshots come later.
</Note>

## Context on a check

```ts theme={null}
shipd.isEnabled("new-checkout", {
  userId: "usr_8f2k19",
  attributes: { plan: "pro", country: "US" },
});
```

Without `userId`, percentage rollouts cannot bucket — the user falls through. Set a default identity with [`identify`](/guides/target-users).

## Polling and realtime

1. `GET /sdk/v1/snapshot` with `If-None-Match`
2. **200** — replace the in-memory snapshot
3. **304** — keep it
4. Optional WebSocket `streamEndpoint` → `/sdk/v1/stream` → on `snapshot.updated`, refetch
5. Poll every `refreshIntervalMs` (default `30_000`) even if the socket is up

Omit `streamEndpoint` for polling only. `refreshIntervalMs: 0` fetches once.

If the edge is unreachable, the last good snapshot (or `defaults`) stays. Evaluation never throws.

```ts theme={null}
shipd.close(); // stop polling + stream
```

## Failure modes

| Situation                                  | What you get                           |
| ------------------------------------------ | -------------------------------------- |
| Edge down / timeout                        | `defaults` or last good snapshot       |
| Unknown flag key                           | `defaults` + `unregistered_flag` event |
| HTTP 401 (revoked key)                     | last good snapshot; `onError`          |
| Snapshot `schemaVersion` you don't support | last good snapshot; `onError`          |

## Next

* [Target users](/guides/target-users)
* [React](/guides/react)
* [SDK reference](/reference/sdk) · [Edge API](/reference/edge-api)
