Skip to content

feat: add capability-aware feature flag system#3229

Closed
rossnelson wants to merge 5 commits intomainfrom
feature/feature-flag-system
Closed

feat: add capability-aware feature flag system#3229
rossnelson wants to merge 5 commits intomainfrom
feature/feature-flag-system

Conversation

@rossnelson
Copy link
Collaborator

@rossnelson rossnelson commented Mar 18, 2026

Summary

  • Adds featureFlags persistStore holding a Record<string, boolean> under the featureFlags localStorage key — the local override layer
  • Extends the Capabilities type with serverlessWorkers?: boolean | null for forward compatibility with the proto
  • Adds withLocalFallback and isCapabilityEnabled to capability-enablement.ts — server capability is authoritative when present, localStorage is the fallback when absent
  • Adds CapabilityGuard component for declarative feature gating
CleanShot.2026-03-19.at.09.51.55.mp4

How it works

Server capability localStorage Result
true anything ✅ enabled
false true ❌ disabled (server wins)
absent true ✅ enabled
absent absent/false ❌ disabled

Usage

<CapabilityGuard capability="serverlessWorkers">
  <NewUI />
  {#snippet fallback()}
    <OldUI />
  {/snippet}
</CapabilityGuard>

Enable locally until the server reports the capability:

localStorage.setItem('featureFlags.serverlessDeployments', 'true')
// then refresh

Adding a new capability with local override = one line in CAPABILITY_FLAG_MAP.

Test plan

  • pnpm lint passes with no new errors
  • pnpm check passes with no new errors
  • pnpm test -- --run passes all unit tests with no regressions
  • CapabilityGuard renders children when capability/flag enabled, fallback when disabled, nothing when disabled with no fallback
  • Server capability false overrides localStorage true
  • localStorage fallback works when server capability is absent

Add a typed feature flag store using persistStore for localStorage
persistence and cross-tab sync. Exports featureFlags map store,
isFeatureFlagEnabled derived helper, setFeatureFlag setter, and
LocalFeatureFlag guard component for declarative usage.
Includes storage event listener for cross-tab localStorage detection.
@vercel
Copy link

vercel bot commented Mar 18, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
holocene Ready Ready Preview, Comment Mar 19, 2026 2:48pm

Request Review

Replace the localStorage-only LocalFeatureFlag component with a
CapabilityGuard that checks server capabilities first, falling back
to localStorage when the capability is absent. Extends Capabilities
type with serverlessWorkers for forward compatibility. Adds
isCapabilityEnabled factory and withLocalFallback helper to
capability-enablement.ts.
@rossnelson rossnelson requested a review from a team as a code owner March 18, 2026 17:18
@rossnelson rossnelson changed the title feat: add feature flag system with localStorage persistence feat: add capability-aware feature flag system Mar 18, 2026
Replace the JSON map store with per-flag persistStore instances keyed
as featureFlags.<capabilityKey>. Removes isFeatureFlagEnabled and the
FeatureFlag type in favour of using keyof Capabilities directly.
Enable a flag via: localStorage.setItem('featureFlags.serverlessWorkers', 'true')
Comment on lines +21 to +24
const serverValue = $page.data?.systemInfo?.capabilities?.[capabilityKey];
if (serverValue !== undefined && serverValue !== null) {
return Boolean(serverValue);
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious why we need this when below we do the same capability check in isCapabilityEnabled

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not a redundant check. It ensures that the system-info value takes precedence. But i can see how the way its written makes it seem redundant. Ill update it to be more clear.

Replace the separate helper with inlined guard-clause logic and ?? operator
to make the server-first, localStorage-fallback intent self-evident.
): Readable<boolean> {
if (!LOCAL_OVERRIDE_CAPABILITIES.has(key)) {
return derived(page, ($page) =>
Boolean($page.data?.systemInfo?.capabilities?.[key]),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also have page.data.namespace.namespaceInfo?.capabilities which is where workerHeartbeats is currently enabled/disabled. Maybe we want a distinction between isSystemCapabilityEnabled and isNamespaceCapabilityEnabled?

@rossnelson rossnelson closed this Mar 19, 2026
@rossnelson rossnelson deleted the feature/feature-flag-system branch March 19, 2026 15:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants