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

# Feature Flags

> Read the flags your server holds from a NUI interface

A feature flag is a [named, typed value](/cloud/offers/feature-flags) you flip in the [dashboard](https://dash.nonefivem.com). The server fetches them and publishes the shared ones to its clients, so reading one from your NUI reaches the client script's copy and **never the API**.

```typescript theme={null}
import { NoCloud } from "@nocloud/cfx-nui";

if (await NoCloud.flags.isFlagEnabled("new-hud")) {
  renderNewHud();
}
```

<Warning>
  Only `shared` flags reach a client. A `server` flag is never published, so
  reads here behave exactly like a flag that does not exist. This is enforced on
  your server, not in the browser — a secret cannot reach a NUI by accident.
</Warning>

## Methods

<Accordion title="NoCloud.flags.isFlagEnabled">
  Checks whether a boolean flag is on.

  ```typescript theme={null}
  if (await NoCloud.flags.isFlagEnabled("new-hud")) {
    renderNewHud();
  }

  // With an explicit fallback
  const maintenance = await NoCloud.flags.isFlagEnabled("maintenance-mode", true);
  ```

  **Parameters**

  * key: `string` — The flag's key
  * fallback: `boolean` — Returned when the flag is not a readable boolean flag (optional, `false` by default)

  **Returns**

  * `Promise<boolean>` — Whether the flag is on

  A missing flag, or one holding another type, reads as the fallback.
</Accordion>

<Accordion title="NoCloud.flags.getFlagValue">
  Reads one flag's value, whatever its type.

  ```typescript theme={null}
  const motd = await NoCloud.flags.getFlagValue("motd", "Welcome");
  const economy = await NoCloud.flags.getFlagValue("economy");
  ```

  **Parameters**

  * key: `string` — The flag's key
  * fallback: `FlagValue` — Returned when the flag is missing or unreadable (optional, `null` by default)

  **Returns**

  * `Promise<FlagValue>` — The flag's value, or the fallback
</Accordion>

<Accordion title="NoCloud.flags.getFlags">
  Reads every flag this client holds.

  ```typescript theme={null}
  const all = await NoCloud.flags.getFlags();
  // { "new-hud": true, "motd": "Welcome", ... }
  ```

  **Returns**

  * `Promise<FlagValues>` — Every readable flag keyed by flag key, or an empty object when there are none to read
</Accordion>

<Accordion title="NoCloud.flags.areFlagsReady">
  Checks whether the server has published any flags yet.

  ```typescript theme={null}
  if (await NoCloud.flags.areFlagsReady()) {
    // the server has published its flags
  }
  ```

  **Returns**

  * `Promise<boolean>` — Whether there are flags to read

  Reads before this is true fall back, so this is what to wait on when a UI would rather show nothing than show a fallback.
</Accordion>

## Reads never throw

A missing flag, a server that does not have `nocloud` installed, or a callback that could not be reached all answer with the fallback — so a flag archived in the dashboard can never break a UI.

```typescript theme={null}
// Safe even if nocloud is not on this server
const theme = await NoCloud.flags.getFlagValue("ui-theme", "dark");
```

Use `areFlagsReady()` when you need to tell those cases apart from a flag that is genuinely `false`.

## What a read costs

A read reaches the `nocloud` client script's copy of replicated state, so it is a local round trip rather than a request to anything — cheap, but not free.

<Tip>
  Read what you need once rather than per frame, and read again when you need it
  current. There is no change event on this side: a UI that wants current values
  reads again.
</Tip>

```typescript theme={null}
// Good — read once into component state
const [flags, setFlags] = useState<FlagValues>({});

useEffect(() => {
  NoCloud.flags.getFlags().then(setFlags);
}, []);

// Avoid — a call per render
// if (await NoCloud.flags.isFlagEnabled("new-hud")) ...
```

If you need a UI to follow changes, re-read on an interval or when the interface is reopened. The underlying values are refreshed by the server for as long as a client script is reading them.

## Types

```typescript theme={null}
type JsonValue =
  | string
  | number
  | boolean
  | null
  | JsonValue[]
  | { [key: string]: JsonValue };

/** A feature flag's value. Flags hold booleans, strings, numbers or JSON. */
type FlagValue = JsonValue;

/** Feature flags keyed by flag key — every flag this client holds. */
type FlagValues = Record<string, FlagValue>;
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Feature Flags" icon="flag" href="/cloud/offers/feature-flags">
    Types, runtimes, limits and the audit log
  </Card>

  <Card title="CFX Feature Flags" icon="gamepad" href="/cloud/sdks/cfx/flags">
    How flags reach your clients in the first place
  </Card>
</CardGroup>
