Skip to content

Instantly share code, notes, and snippets.

@LaurMo
Created March 25, 2026 19:57
Show Gist options
  • Select an option

  • Save LaurMo/8b1d3fefa686d113ff90dc8760ba6331 to your computer and use it in GitHub Desktop.

Select an option

Save LaurMo/8b1d3fefa686d113ff90dc8760ba6331 to your computer and use it in GitHub Desktop.
Copilot skill: Setup a feature flag in github-ui
name setup-feature-flag
description Sets up a new client-side feature flag in github-ui. Registers the flag, adds usage in code, updates tests, and validates. Use when adding a new feature that needs to be gated behind a feature flag.

Setup Feature Flag

Use this skill when adding a new feature flag to gate UI changes in github-ui.

Prerequisites

  • You are working in the github-ui repository.
  • You know the purpose of the feature being flagged.

Rules

  1. ALWAYS use snake_case for flag names.
  2. ALWAYS insert flags in alphabetical order in the registry array — the list is @eslint-sort-array enforced.
  3. ALWAYS use isFeatureEnabled from @github-ui/feature-flagsnever the deprecated useFeatureFlag hook from @github-ui/react-core/use-feature-flag.
  4. Flag names are visible to users in the <script id="client-env"> attribute. Avoid revealing secret project names.
  5. Feature flags only gate UI — they do not enforce access control. Always enforce access checks at the data/API layer separately.

Steps

1. Choose a Flag Name

Pick a descriptive snake_case name. Follow existing conventions:

  • Prefix with the feature area (e.g., copilot_, issues_, prs_, dashboard_)
  • Be specific enough to distinguish from other flags
  • Keep it non-obvious if the feature is confidential

Confirm the flag name with the user before proceeding.

2. Register the Flag

Add the flag name to the jsFeatureFlags array in:

packages/feature-flags/client-feature-flags.ts

Insert it in alphabetical order within the array. The array uses as const and is enforced by @eslint-sort-array.

If the flag is CSS-only (toggling styles without JS logic), add it to the cssFeatureFlags array instead.

If the flag should be evaluated server-side but not sent to the client, add it to serverOnlyFeatureFlags.

3. Use the Flag in Code

In the component or module that needs the gate, import and check the flag:

import {isFeatureEnabled} from '@github-ui/feature-flags'

// Check the flag
if (isFeatureEnabled('your_flag_name')) {
  // New feature code
}

For React components, call it at the top of the component body:

import {isFeatureEnabled} from '@github-ui/feature-flags'

export function MyComponent() {
  const myFeatureEnabled = isFeatureEnabled('your_flag_name')

  if (!myFeatureEnabled) {
    return <OldBehavior />
  }

  return <NewBehavior />
}

For CSS-only flags, use the data attribute selector:

[data-css-features~="your_flag_name" i] {
  /* styles behind flag */
}

4. Update Tests

Mock the feature flag in tests. Two approaches:

Option A — Mock the module (preferred for unit tests):

import {isFeatureEnabled} from '@github-ui/feature-flags'

vi.mock('@github-ui/feature-flags', () => ({
  isFeatureEnabled: vi.fn(),
}))

// In a test:
vi.mocked(isFeatureEnabled).mockReturnValue(true)

Option B — Mock the client env (for integration-style tests):

import {mockClientEnv} from '@github-ui/client-env'

mockClientEnv({featureFlags: ['your_flag_name']})

Write tests for both states (flag on and flag off) to ensure the old behavior is preserved when the flag is disabled.

5. Validate

Run the following checks for each modified package:

# Lint the feature-flags package (checks alphabetical order)
npm run lint -w @github-ui/feature-flags -- --fix client-feature-flags.ts

# Lint, typecheck, and test the package you changed
npm run lint -w @github-ui/<your-package> -- --fix
npm run tsc -w @github-ui/<your-package>
npm test -w @github-ui/<your-package>

6. Local Testing

To toggle the flag locally against a running dev server, use:

script/toggle-feature-flag enable your_flag_name

Or override via URL query parameter (staff only):

?_features=your_flag_name        # enable
?_features=!your_flag_name       # disable

Or via cookie:

document.cookie = "_features=your_flag_name; path=/"

Output

After completing these steps, the PR should include:

  • The flag registered in packages/feature-flags/client-feature-flags.ts
  • Feature-gated code using isFeatureEnabled('flag_name')
  • Tests covering both flag-on and flag-off states
  • All lint, typecheck, and test checks passing

Reminders

  • Feature flags should be short-lived. Plan to clean up the flag once the feature is fully rolled out.
  • The server-side flag (in the Rails monolith) must also be created separately via DevPortal or Vexi for the flag to evaluate as enabled in production.
  • Check the flag with a safe default: FeatureFlag.vexi.enabled?("your_flag", actor, default: false) on the server side.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment