Skip to content

Rules & Overrides ​

Contextual rules ​

Rules are functions evaluated reactively. Priority: below URL overrides and setFlag, above loader/static.

ts
app.use(FeatureToggles, {
  rules: {
    darkMode: () => window.matchMedia('(prefers-color-scheme: dark)').matches,
    liveChatWidget: () => {
      const h = new Date().getHours()
      return h >= 9 && h < 18
    },
    devFeatures: () => document.cookie.includes('internal=1'),
  },
})

Rules can be overridden by setFlag() or a URL param.

URL overrides ​

When urlOverrides: true, query params override flag values without a page reload.

https://app.example.com/?feature:newDashboard=true&feature:checkoutFlow=v2

Variable overrides:

?feature-var:newCheckout:maxItems=10

Custom prefix (urlPrefix: 'ft'):

?ft:newDashboard=true

Priority order ​

Highest to lowest:

URL override → runtime setFlag() → rules → loader → static flags → defaultValue

If a flag has a schedule configured, an inactive window forces it to false after the chain above resolves a value — but only when neither a URL nor a runtime override is currently set for that flag. An active URL or runtime override always wins over an inactive schedule.

Persistent overrides ​

By default setFlag/setVariant live in memory only. Pass { persist: true } to save to localStorage — this works identically for boolean flags and variant flags:

ts
const { setFlag, setVariant, clearPersistedFlags, isPersisted } = useFeatureProvider()

setFlag('darkMode', true, { persist: true })
// Value survives page reloads

setVariant('checkoutFlow', 'v2', { persist: true })
// Variant overrides persist the same way

isPersisted('darkMode') // → true

clearPersistedFlags() // remove all persisted overrides (both boolean and variant)

Override profiles ​

Named sets of overrides stored in localStorage — useful for QA, demos, and design reviews.

ts
const { saveProfile, loadProfile, listProfiles } = useFeatureProvider()

saveProfile('demo-mode', {
  newDashboard: true,
  betaSearch: true,
  maintenanceMode: false,
})

loadProfile('demo-mode') // applies all flags from the profile as runtime overrides
loadProfile('default') // resets to original values (calls resetAll)

listProfiles() // → ['demo-mode']

The <FeatureDevTools> panel shows a profile dropdown when profiles exist.