Skip to content

Conversation

@sid597
Copy link
Collaborator

@sid597 sid597 commented Dec 22, 2025

Summary by CodeRabbit

  • New Features
    • Feature flag management is now available in the settings panel, providing controls to enable or disable experimental features directly from the interface. Users can adjust feature toggles without requiring code or configuration changes.

✏️ Tip: You can customize this high-level summary in your review settings.

@linear
Copy link

linear bot commented Dec 22, 2025

@supabase
Copy link

supabase bot commented Dec 22, 2025

This pull request has been ignored for the connected project zytfjzqyijgagqxrzbmz because there are no changes detected in packages/database/supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

Copy link
Collaborator Author

sid597 commented Dec 22, 2025

@sid597 sid597 changed the title add new setting component for feature flag ENG-1191: add new setting component for feature flag Dec 22, 2025
@sid597 sid597 marked this pull request as ready for review December 22, 2025 08:32
@sid597
Copy link
Collaborator Author

sid597 commented Dec 22, 2025

@coderabbitai full review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 22, 2025

✅ Actions performed

Full review triggered.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 22, 2025

📝 Walkthrough

Walkthrough

Introduces a feature flag management system consisting of a Zod schema for feature flags, utility functions to read and write flags to block-level settings storage, and a React UI component for toggling feature flags with a Blueprint Checkbox.

Changes

Cohort / File(s) Summary
Feature Flag Schema and Utilities
apps/roam/src/utils/zodSchemaForSettings.ts, apps/roam/src/utils/manageFeatureFlag.ts
Adds Zod schema and TypeScript type for feature flags; implements getFeatureFlag and setFeatureFlag functions to read from and write to block-level settings with schema validation
Feature Flag UI Component
apps/roam/src/components/settings/BlockPropFeatureFlagPanel.tsx
New React component that renders a Blueprint Checkbox synchronized with feature flags; initializes state on mount via getFeatureFlag and persists changes via setFeatureFlag

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

  • Verify that FeatureFlagsSchema is correctly structured and can be extended for future flags
  • Confirm that getFeatureFlag properly validates the retrieved block properties against the schema
  • Check that setFeatureFlag correctly delegates to setBlockPropBasedSettings with the proper key path
  • Ensure the React component correctly initializes state from the persisted flag value and handles state synchronization on toggle

Pre-merge checks

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: adding a new setting component for feature flag functionality, which aligns with the BlockPropFeatureFlagPanel component introduced in the PR.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (1)
apps/roam/src/components/settings/BlockPropFeatureFlagPanel.tsx (1)

17-23: Consider error handling for feature flag operations.

getFeatureFlag may throw if the Zod schema validation fails, and setFeatureFlag performs a void-ed async operation that could fail silently. Consider wrapping these in try-catch blocks or providing user feedback on errors.

Note: This component is currently non-functional due to the empty FeatureFlagsSchema (see zodSchemaForSettings.ts review). Once feature flags are added to the schema, this logic will work as intended.

Example: Basic error handling
const [value, setValue] = useState(() => {
  try {
    return getFeatureFlag(featureKey);
  } catch (error) {
    console.error(`Failed to load feature flag ${String(featureKey)}:`, error);
    return false; // safe default
  }
});

const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
  const { checked } = e.target;
  try {
    setFeatureFlag(featureKey, checked);
    setValue(checked);
  } catch (error) {
    console.error(`Failed to set feature flag ${String(featureKey)}:`, error);
    // Optionally revert UI state or show user notification
  }
};
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8f17d89 and 25706dc.

📒 Files selected for processing (3)
  • apps/roam/src/components/settings/BlockPropFeatureFlagPanel.tsx
  • apps/roam/src/utils/manageFeatureFlag.ts
  • apps/roam/src/utils/zodSchemaForSettings.ts
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/main.mdc)

**/*.{ts,tsx}: Use Tailwind CSS for styling where possible
When refactoring inline styles, use tailwind classes
Prefer type over interface in TypeScript
Use explicit return types for functions
Avoid any types when possible
Prefer arrow functions over regular function declarations
Use named parameters (object destructuring) when a function has more than 2 parameters
Use PascalCase for components and types
Use camelCase for variables and functions
Use UPPERCASE for constants
Function names should describe their purpose clearly
Prefer early returns over nested conditionals for better readability

Files:

  • apps/roam/src/components/settings/BlockPropFeatureFlagPanel.tsx
  • apps/roam/src/utils/zodSchemaForSettings.ts
  • apps/roam/src/utils/manageFeatureFlag.ts
apps/roam/**/*.{js,ts,tsx,jsx,json}

📄 CodeRabbit inference engine (.cursor/rules/roam.mdc)

Prefer existing dependencies from package.json when working on the Roam Research extension

Files:

  • apps/roam/src/components/settings/BlockPropFeatureFlagPanel.tsx
  • apps/roam/src/utils/zodSchemaForSettings.ts
  • apps/roam/src/utils/manageFeatureFlag.ts
apps/roam/**/*.{ts,tsx,jsx,js,css,scss}

📄 CodeRabbit inference engine (.cursor/rules/roam.mdc)

Use BlueprintJS 3 components and Tailwind CSS for platform-native UI in the Roam Research extension

Files:

  • apps/roam/src/components/settings/BlockPropFeatureFlagPanel.tsx
  • apps/roam/src/utils/zodSchemaForSettings.ts
  • apps/roam/src/utils/manageFeatureFlag.ts
apps/roam/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/roam.mdc)

apps/roam/**/*.{ts,tsx,js,jsx}: Use the roamAlphaApi docs from https://roamresearch.com/#/app/developer-documentation/page/tIaOPdXCj when implementing Roam functionality
Use Roam Depot/Extension API docs from https://roamresearch.com/#/app/developer-documentation/page/y31lhjIqU when implementing extension functionality

Files:

  • apps/roam/src/components/settings/BlockPropFeatureFlagPanel.tsx
  • apps/roam/src/utils/zodSchemaForSettings.ts
  • apps/roam/src/utils/manageFeatureFlag.ts
apps/roam/**

📄 CodeRabbit inference engine (.cursor/rules/roam.mdc)

Implement the Discourse Graph protocol in the Roam Research extension

Files:

  • apps/roam/src/components/settings/BlockPropFeatureFlagPanel.tsx
  • apps/roam/src/utils/zodSchemaForSettings.ts
  • apps/roam/src/utils/manageFeatureFlag.ts
🧠 Learnings (3)
📚 Learning: 2025-12-22T05:43:01.282Z
Learnt from: sid597
Repo: DiscourseGraphs/discourse-graph PR: 630
File: apps/roam/src/utils/settingsUsingBlockProps.ts:64-66
Timestamp: 2025-12-22T05:43:01.282Z
Learning: In `apps/roam/src/utils/settingsUsingBlockProps.ts`, the `setBlockPropBasedSettings` function expects callers to ensure that the `value` parameter matches the expected type for the given `keys` path. Type validation is handled at the caller side rather than within the utility function.

Applied to files:

  • apps/roam/src/components/settings/BlockPropFeatureFlagPanel.tsx
  • apps/roam/src/utils/manageFeatureFlag.ts
📚 Learning: 2025-11-25T00:52:41.934Z
Learnt from: CR
Repo: DiscourseGraphs/discourse-graph PR: 0
File: .cursor/rules/roam.mdc:0-0
Timestamp: 2025-11-25T00:52:41.934Z
Learning: Applies to apps/roam/**/*.{ts,tsx,jsx,js,css,scss} : Use BlueprintJS 3 components and Tailwind CSS for platform-native UI in the Roam Research extension

Applied to files:

  • apps/roam/src/components/settings/BlockPropFeatureFlagPanel.tsx
📚 Learning: 2025-11-25T00:52:41.934Z
Learnt from: CR
Repo: DiscourseGraphs/discourse-graph PR: 0
File: .cursor/rules/roam.mdc:0-0
Timestamp: 2025-11-25T00:52:41.934Z
Learning: Applies to apps/roam/**/*.{ts,tsx,js,jsx} : Use the roamAlphaApi docs from https://roamresearch.com/#/app/developer-documentation/page/tIaOPdXCj when implementing Roam functionality

Applied to files:

  • apps/roam/src/utils/manageFeatureFlag.ts
🧬 Code graph analysis (2)
apps/roam/src/components/settings/BlockPropFeatureFlagPanel.tsx (2)
apps/roam/src/utils/zodSchemaForSettings.ts (1)
  • FeatureFlags (8-8)
apps/roam/src/utils/manageFeatureFlag.ts (2)
  • getFeatureFlag (8-18)
  • setFeatureFlag (20-27)
apps/roam/src/utils/manageFeatureFlag.ts (3)
apps/roam/src/utils/zodSchemaForSettings.ts (2)
  • FeatureFlags (8-8)
  • FeatureFlagsSchema (4-5)
apps/roam/src/data/blockPropsSettingsConfig.ts (1)
  • TOP_LEVEL_BLOCK_PROP_KEYS (2-2)
apps/roam/src/utils/settingsUsingBlockProps.ts (2)
  • getBlockPropBasedSettings (6-48)
  • setBlockPropBasedSettings (50-102)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
🔇 Additional comments (2)
apps/roam/src/components/settings/BlockPropFeatureFlagPanel.tsx (1)

25-36: Well-structured component using Blueprint and roamjs-components.

The component correctly uses BlueprintJS 3 Checkbox and roamjs-components utilities (Description, idToTitle) for consistent UI, aligning with the coding guidelines for the Roam extension.

As per coding guidelines and learnings, "Use BlueprintJS 3 components and Tailwind CSS for platform-native UI in the Roam Research extension."

apps/roam/src/utils/manageFeatureFlag.ts (1)

20-27: Proper use of void for async operation.

The void keyword correctly indicates that the promise returned by setBlockPropBasedSettings is intentionally not awaited, which is appropriate for a fire-and-forget write operation.

Based on learnings, setBlockPropBasedSettings relies on caller-side type validation. Since value is typed as boolean and feature flag keys will be defined in the schema, this usage is correct.

Based on learnings, "In apps/roam/src/utils/settingsUsingBlockProps.ts, the setBlockPropBasedSettings function expects callers to ensure that the value parameter matches the expected type for the given keys path."

Comment on lines +8 to +16
export const BlockPropFeatureFlagPanel = ({
title,
description,
featureKey,
}: {
title: string;
description: string;
featureKey: keyof FeatureFlags;
}) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Add explicit return type annotation.

Per coding guidelines, functions should have explicit return types. Add : React.JSX.Element or : JSX.Element to the component signature.

🔎 Proposed fix
 export const BlockPropFeatureFlagPanel = ({
   title,
   description,
   featureKey,
 }: {
   title: string;
   description: string;
   featureKey: keyof FeatureFlags;
-}) => {
+}): React.JSX.Element => {

As per coding guidelines, "Use explicit return types for functions."

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const BlockPropFeatureFlagPanel = ({
title,
description,
featureKey,
}: {
title: string;
description: string;
featureKey: keyof FeatureFlags;
}) => {
export const BlockPropFeatureFlagPanel = ({
title,
description,
featureKey,
}: {
title: string;
description: string;
featureKey: keyof FeatureFlags;
}): React.JSX.Element => {
🤖 Prompt for AI Agents
In apps/roam/src/components/settings/BlockPropFeatureFlagPanel.tsx around lines
8-16, the functional component is missing an explicit return type; update the
component signature to include a React return type (e.g., add `:
React.JSX.Element` or `: JSX.Element` after the parameter list) so the function
has an explicit return type per coding guidelines; ensure necessary React types
are available from imports (add `import React from "react"` or import JSX types
if your TSX setup requires it) and then re-run typechecks.

Comment on lines +8 to +18
export const getFeatureFlag = (key: keyof FeatureFlags): boolean => {
const featureFlagKey = TOP_LEVEL_BLOCK_PROP_KEYS.featureFlags;

const { blockProps } = getBlockPropBasedSettings({
keys: [featureFlagKey],
});

const flags = FeatureFlagsSchema.parse(blockProps || {});

return flags[key];
};
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

getFeatureFlag will fail with the current empty schema.

Since FeatureFlagsSchema is an empty object, flags[key] at Line 17 attempts to access a property that doesn't exist on the validated object type. TypeScript treats keyof FeatureFlags as never, and runtime access will return undefined (not boolean).

Once feature flags are added to the schema, consider adding a fallback default value to handle cases where a flag isn't yet defined:

🔎 Suggested improvement for robustness
 export const getFeatureFlag = (key: keyof FeatureFlags): boolean => {
   const featureFlagKey = TOP_LEVEL_BLOCK_PROP_KEYS.featureFlags;

   const { blockProps } = getBlockPropBasedSettings({
     keys: [featureFlagKey],
   });

   const flags = FeatureFlagsSchema.parse(blockProps || {});

-  return flags[key];
+  return flags[key] ?? false; // Default to false if key is missing
 };

This ensures the function always returns a boolean even if a flag isn't explicitly set in storage.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const getFeatureFlag = (key: keyof FeatureFlags): boolean => {
const featureFlagKey = TOP_LEVEL_BLOCK_PROP_KEYS.featureFlags;
const { blockProps } = getBlockPropBasedSettings({
keys: [featureFlagKey],
});
const flags = FeatureFlagsSchema.parse(blockProps || {});
return flags[key];
};
export const getFeatureFlag = (key: keyof FeatureFlags): boolean => {
const featureFlagKey = TOP_LEVEL_BLOCK_PROP_KEYS.featureFlags;
const { blockProps } = getBlockPropBasedSettings({
keys: [featureFlagKey],
});
const flags = FeatureFlagsSchema.parse(blockProps || {});
return flags[key] ?? false; // Default to false if key is missing
};
🤖 Prompt for AI Agents
In apps/roam/src/utils/manageFeatureFlag.ts around lines 8–18, getFeatureFlag
currently reads flags[key] from an empty/partial schema which can be undefined
and TypeScript treats keyof FeatureFlags as never; change the function to always
return a boolean by providing a safe fallback and correct typing: ensure
FeatureFlagsSchema.parse returns a partial/optional shape or cast the parsed
result to Partial<FeatureFlags>, then return a boolean using a fallback (e.g.,
flags[key] ?? false or Boolean(flags[key])) so the function never returns
undefined.

Comment on lines +3 to +6
/* eslint-disable @typescript-eslint/naming-convention */
export const FeatureFlagsSchema = z.object({
});
/* eslint-disable @typescript-eslint/naming-convention */
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix the ESLint comment pairing.

Line 6 duplicates the eslint-disable comment instead of re-enabling the rule. This leaves the naming-convention rule disabled for the remainder of the file.

🔎 Proposed fix
 /* eslint-disable @typescript-eslint/naming-convention */
 export const FeatureFlagsSchema = z.object({
 });
-/* eslint-disable @typescript-eslint/naming-convention */
+/* eslint-enable @typescript-eslint/naming-convention */
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/* eslint-disable @typescript-eslint/naming-convention */
export const FeatureFlagsSchema = z.object({
});
/* eslint-disable @typescript-eslint/naming-convention */
/* eslint-disable @typescript-eslint/naming-convention */
export const FeatureFlagsSchema = z.object({
});
/* eslint-enable @typescript-eslint/naming-convention */
🤖 Prompt for AI Agents
In apps/roam/src/utils/zodSchemaForSettings.ts around lines 3 to 6, the ESLint
comment at line 6 mistakenly duplicates `/* eslint-disable
@typescript-eslint/naming-convention */` instead of re-enabling the rule; change
the second comment to `/* eslint-enable @typescript-eslint/naming-convention */`
(or remove the disable and scope the disable/enable pair properly around the
specific code) so the naming-convention rule is only disabled for the intended
block.

Comment on lines +4 to +5
export const FeatureFlagsSchema = z.object({
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

find apps/roam -type f -name "*zodSchemaForSettings*" 2>/dev/null

Repository: DiscourseGraphs/discourse-graph

Length of output: 118


🏁 Script executed:

cat -n apps/roam/src/utils/zodSchemaForSettings.ts

Repository: DiscourseGraphs/discourse-graph

Length of output: 385


🏁 Script executed:

rg -n "FeatureFlagsSchema|getFeatureFlag|setFeatureFlag|BlockPropFeatureFlagPanel" apps/roam/src --type ts --type tsx

Repository: DiscourseGraphs/discourse-graph

Length of output: 102


🏁 Script executed:

rg -n "FeatureFlag" apps/roam/src -A 3 -B 1 --type ts --type tsx

Repository: DiscourseGraphs/discourse-graph

Length of output: 102


🏁 Script executed:

rg -n "zodSchemaForSettings" apps/roam/src --type ts --type tsx

Repository: DiscourseGraphs/discourse-graph

Length of output: 102


🏁 Script executed:

rg -n "import.*FeatureFlagsSchema|from.*zodSchemaForSettings" apps/roam/src --type ts --type tsx

Repository: DiscourseGraphs/discourse-graph

Length of output: 102


🏁 Script executed:

find apps/roam/src -type f \( -name "*.ts" -o -name "*.tsx" \) -exec grep -l "feature\|flag" {} \; 2>/dev/null

Repository: DiscourseGraphs/discourse-graph

Length of output: 568


🏁 Script executed:

cd apps/roam/src/utils && git log --oneline -n 20 zodSchemaForSettings.ts 2>/dev/null || echo "No git history available"

Repository: DiscourseGraphs/discourse-graph

Length of output: 125


🏁 Script executed:

head -20 apps/roam/src/utils/zodSchemaForSettings.ts

Repository: DiscourseGraphs/discourse-graph

Length of output: 329


🏁 Script executed:

rg -n "TODO|FIXME|feature.flag|TODO.*feature" apps/roam/src --type ts --type tsx -i | head -20

Repository: DiscourseGraphs/discourse-graph

Length of output: 102


🏁 Script executed:

cat -n apps/roam/src/components/settings/BlockPropFeatureFlagPanel.tsx

Repository: DiscourseGraphs/discourse-graph

Length of output: 1329


🏁 Script executed:

cat -n apps/roam/src/utils/isFlagEnabled.ts

Repository: DiscourseGraphs/discourse-graph

Length of output: 874


🏁 Script executed:

cat -n apps/roam/src/utils/manageFeatureFlag.ts

Repository: DiscourseGraphs/discourse-graph

Length of output: 1073


🏁 Script executed:

cat -n apps/roam/src/utils/pullWatchBlockPropsBasedSettings.ts | head -50

Repository: DiscourseGraphs/discourse-graph

Length of output: 720


🏁 Script executed:

cat -n apps/roam/src/data/blockPropsSettingsConfig.ts

Repository: DiscourseGraphs/discourse-graph

Length of output: 259


Add at least one feature flag definition to make the type system functional.

FeatureFlagsSchema is empty, making keyof FeatureFlags resolve to never. The component BlockPropFeatureFlagPanel and functions getFeatureFlag/setFeatureFlag cannot accept any flag name, preventing the feature flag system from being used.

Add at least one flag definition:

 export const FeatureFlagsSchema = z.object({
+  exampleFeature: z.boolean().default(false),
 });

Alternatively, document in a comment that this PR establishes foundational infrastructure with flag definitions to be added in follow-up PRs.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const FeatureFlagsSchema = z.object({
});
export const FeatureFlagsSchema = z.object({
exampleFeature: z.boolean().default(false),
});
🤖 Prompt for AI Agents
In apps/roam/src/utils/zodSchemaForSettings.ts around lines 4-5,
FeatureFlagsSchema is currently empty which causes keyof FeatureFlags to be
never and breaks consumers; either add at least one concrete flag definition
(e.g., a boolean flag name with z.boolean()) so the type system yields usable
keys, or add a clear file comment stating this PR only adds infrastructure and
that actual flag entries will be added in a follow-up PR — update exports/types
accordingly so BlockPropFeatureFlagPanel, getFeatureFlag and setFeatureFlag
accept real flag names.

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.

2 participants