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

# Feature Flags

> Remotely toggle features in your overlay using the Overlayed Dashboard.

## Overview

Feature flags let you enable or disable features in your overlay without deploying a new version. Flags are managed
through the [Overlayed Dashboard](https://overlay.dev/feature-flags) and automatically fetched by `@overlayed/app`.

## Registering Flags

Pass a record of flag names and their default values to the `featureFlags` option. The keys provide typed access, and
the values are used as defaults before the API responds or when a flag is missing from the response.

```typescript theme={null}
import { overlayed } from "@overlayed/app";

const overlay = overlayed({
	featureFlags: { "new-scoreboard": false, "beta-hud": false },
	// ...
});
```

<Info>
  If a registered flag name is not found in the API response, a warning is logged to help catch typos or removed
  flags.
</Info>

## Waiting for Flags

The `ready` promise resolves once the initial feature flag fetch completes, whether it succeeds or fails. Use it to
delay app startup until flags are available.

```typescript theme={null}
await overlay.featureFlags.ready;
// Flags are now fetched (or defaults are in use if the request failed)
```

## Checking Flag Status

```typescript theme={null}
const enabled = overlay.featureFlags.get("new-scoreboard");
```

Before the API responds, or if the flag is missing from the response, `get` returns the configured default value. If no
default was registered, it returns `false`.

Get all flags at once:

```typescript theme={null}
const allFlags = overlay.featureFlags.getAll();
// { "new-scoreboard": true, "beta-hud": false }
```

`getAll` merges defaults, API values, and overrides — API values take precedence over defaults, and overrides take
precedence over both.

## Listening for Changes

Feature flags are automatically fetched:

* When the overlay bootstraps
* Every 10 minutes
* When a game launches or closes

Listen for individual flag changes:

```typescript theme={null}
overlay.featureFlags.on("scoreboard-enabled", (enabled) => {
	// Flag value changed
});
```

Listen for any flag update:

```typescript theme={null}
overlay.featureFlags.on("updated", () => {
	// Flags were refreshed from the API
});
```

## Manual Refresh

Force a refresh from the API at any time:

```typescript theme={null}
await overlay.featureFlags.refresh();
```

## Overriding Flags

Override flag values locally. Overrides persist across API refetches and take precedence over API values.

Override a single flag:

```typescript theme={null}
overlay.featureFlags.override("new-scoreboard", true);
```

<Info>
  Calling `override` emits a change event for the flag (and the `updated` event) if the effective value changes. Once
  overridden, subsequent API refreshes will not emit change events for that flag.
</Info>

Check whether a flag is overridden:

```typescript theme={null}
if (overlay.featureFlags.isOverridden("new-scoreboard")) {
	// The flag value is being forced locally
}
```

Get every active override:

```typescript theme={null}
const overrides = overlay.featureFlags.getAllOverrides();
// { "new-scoreboard": true }
```

## Clearing Overrides

Remove an override so the flag resolves from the API value (or default) again:

```typescript theme={null}
overlay.featureFlags.clearOverride("new-scoreboard");
```

Remove every override at once:

```typescript theme={null}
overlay.featureFlags.clearOverrides();
```

<Info>
  Clearing an override emits a change event for the flag (and the `updated` event) only if the effective value
  actually changes. Clearing an override that matched the underlying API value is silent.
</Info>

## Inspecting a Flag

Get a breakdown of the individual layers that contribute to a flag's effective value. Useful for debug panels that need
to show where a value came from.

```typescript theme={null}
const layers = overlay.featureFlags.inspect("new-scoreboard");
// {
//   effective: true,  // resolved value (override ?? actual ?? default ?? false)
//   override: true,   // value set via override(), or undefined
//   actual: false,    // value returned by the API, or undefined
//   default: false,   // registered default, or undefined
// }
```

Each layer is `undefined` when it is not set, so `override: false` can be distinguished from "not overridden".
