Skip to main content

Overview

Feature flags let you enable or disable features in your overlay without deploying a new version. Flags are managed through the Overlayed Dashboard 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.
import { overlayed } from "@overlayed/app";

const overlay = overlayed({
	featureFlags: { "new-scoreboard": false, "beta-hud": false },
	// ...
});
If a registered flag name is not found in the API response, a warning is logged to help catch typos or removed flags.

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.
await overlay.featureFlags.ready;
// Flags are now fetched (or defaults are in use if the request failed)

Checking Flag Status

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:
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:
overlay.featureFlags.on("scoreboard-enabled", (enabled) => {
	// Flag value changed
});
Listen for any flag update:
overlay.featureFlags.on("updated", () => {
	// Flags were refreshed from the API
});

Manual Refresh

Force a refresh from the API at any time:
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:
overlay.featureFlags.override("new-scoreboard", true);
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.
Check whether a flag is overridden:
if (overlay.featureFlags.isOverridden("new-scoreboard")) {
	// The flag value is being forced locally
}
Get every active override:
const overrides = overlay.featureFlags.getAllOverrides();
// { "new-scoreboard": true }

Clearing Overrides

Remove an override so the flag resolves from the API value (or default) again:
overlay.featureFlags.clearOverride("new-scoreboard");
Remove every override at once:
overlay.featureFlags.clearOverrides();
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.

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.
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”.