Skip to content
NanoFlags
Start free

Get started

Quickstart

From an empty account to a flag evaluated in your code, then a published change reaching that code. About ten minutes. Every evaluation is local: the SDK holds the configuration in memory and answers synchronously.

1. Create a workspace and a project

Create an account, confirm your e-mail address, and enter a workspace name (usually your company or team) and a first project name. Joining an existing workspace instead? Ask its admin to invite your e-mail address; the invitation is accepted automatically when you sign up.

Every new project starts with three environments:

  • Development and Staging: publish directly.
  • Production: protected (only an owner can relax its publishing policy). On Team and Scale it is created requiring a reviewed change with an independent approval and passing scenario checks; on Explore required approvals and scenario checks are not available, so Production publishes directly, like the others.

2. Pick an environment

A flag has one draft configuration per environment, and each environment publishes its own numbered revisions. Use Development for this guide. Admins can add environments under Settings → Environments.

3. Create a flag

Open Flags → New flag, choose a key (for example checkout-v2) and a type (boolean, string, number or json). The key and the type cannot be changed later. Mark the flag client-exposed if browser code needs to read it: browser keys receive only client-exposed flags.

In the Development draft, turn the flag on and, for example, add a rule that serves true to 10 % of users. Saving changes the draft only; SDKs do not see it until you publish.

4. Create an SDK key

Under Settings → SDK & access keys (admin role), create a key for the Development environment. A key reads exactly one environment. The full key is shown once; NanoFlags stores only a hash. Put it in your secret manager.

  • Server (nf_srv_…): full configuration for trusted backends. A secret.
  • Client (nf_pub_…): browser-safe, receives only client-exposed flags. Anyone with the page can read it.

CI (nf_ci_…) and admin (nf_adm_…) keys are for pipelines and the CLI and are refused by the SDK endpoints. See Keys and scopes.

5. Install the SDK

sh
npm install @nanoflags/sdk

One package covers Node, browsers and edge runtimes (@nanoflags/sdk), React (@nanoflags/sdk/react) and Node test-session propagation (@nanoflags/sdk/node). ESM with TypeScript types. The live socket needs a global WebSocket (Node 22 or newer, browsers, Deno, Bun); otherwise the SDK falls back to server-sent events and polling.

6. Evaluate with an explicit fallback

Every accessor takes a fallback: the value your application uses when NanoFlags cannot answer (no configuration loaded yet, unknown flag, wrong type). Choose the fallback that is safe for your users, usually the current behaviour.

Node

server.ts
import { createClient } from "@nanoflags/sdk";

const flags = createClient({
  sdkKey: process.env.NANOFLAGS_SDK_KEY!, // nf_srv_…
  baseUrl: "https://edge.nanoflags.io",
  service: "checkout-api",               // shown as the service that reports a revision
});

await flags.ready(); // never rejects; check flags.status

const enabled = flags.boolean("checkout-v2", false, { key: user.id, signedIn: true, region: "US" });

Create one client per process and reuse it. Call flags.close() on shutdown: the live connection keeps a Node process alive until then. In short-lived scripts and serverless functions call close() or pass streaming: false.

Browser

flags.ts
import { createClient } from "@nanoflags/sdk";

export const flags = createClient({
  sdkKey: "nf_pub_…", // client key: only client-exposed flags are delivered
  baseUrl: "https://edge.nanoflags.io",
  service: "web",
});

await flags.ready();
const ranking = flags.string("search-ranking", "relevance-v2", { key: user.id });
Never ship an nf_srv_ key to a browser. Rules of client-exposed flags are visible to anyone who has the client key, and evaluation runs on the user's device: do not use browser flags for authorization.

React

app.tsx
import { createClient } from "@nanoflags/sdk";
import { NanoFlagsProvider, useFlag, useFlagsStatus } from "@nanoflags/sdk/react";

const client = createClient({ sdkKey: "nf_pub_…", baseUrl: "https://edge.nanoflags.io", service: "web" });

export function App({ user }: { user: { id: string; plan: string } }) {
  return (
    <NanoFlagsProvider client={client} context={{ key: user.id, plan: user.plan }}>
      <Checkout />
    </NanoFlagsProvider>
  );
}

function Checkout() {
  const v2 = useFlag("checkout-v2", false); // boolean accessor, chosen from the fallback's type
  const { status, revision } = useFlagsStatus();
  return v2 ? <NewCheckout /> : <OldCheckout />;
}

The context attribute key is the stable identity used for percentage rollouts. Pass it for every evaluation that can hit a rollout; without it the context is treated as outside the allocation.

7. Publish

Back in the dashboard, open Publish draft for Development. The review shows the difference between the published revision and the draft. Publishing snapshots the whole draft into an immutable revision (r1, r2, …). If someone else published in the meantime, the publish is refused with Destination changed instead of overwriting their revision.

On Team and Scale, Production requires a change with an independent approval and passing scenarios for the same step: see Changes and approvals.

8. See it arrive

Connected SDKs receive the new revision over the live socket, without polling. Listen for it:

ts
flags.on("update", ({ revision, previousRevision, transport, latencyMs }) => {
  console.log(`now on r${revision} (was r${previousRevision}) via ${transport}`, latencyMs);
});
flags.on("error", (e) => console.warn(e.code, e.message)); // the last bundle keeps serving

transport is "live" when the revision was pushed, "stream" when it was fetched after a server-sent event, and "poll" otherwise. Current propagation measurements are published on the status page.

In the dashboard, the welcome page (/app/welcome) → Check connection shows the revision the service last reported. A report means one process using this key had that revision loaded when it reported; it does not prove that every instance did. See what a reported signal proves.

Next steps

  1. Concepts: drafts, revisions, changes, scenarios, segments and rollout bucketing.
  2. SDK reference: options, statuses, transports, persistence and telemetry.
  3. CI: run scenario checks on every pull request.