Skip to content

Configuration, not conditionals

Host-specific behavior passes in as props — shared libs do not sniff where they run.

react-platform-config-not-conditionals

Why it matters

Failure modes if this rule is ignored
StakeIf ignored
Agent gets lost
  • A UI lib containing if (context === 'embedded') is no longer a lib — it's part of that host app.
Hard to change
  • New host needs a lib edit — the "shared" component is now owned by whoever embedded it last.
Unsafe to delete
  • Without this, in a year you have 40 ifs in one component and nobody knows what's safe to delete.

How to fix

Same library, different behaviors per host — through props and configuration, not ifs that sniff where the code is running.

Examples

Bad
tsx
// libs/shared/ui-chat/src/lib/chat-sidebar.tsx
function ChatSidebar({ context }: { context: 'embedded' | 'account' }) {
  return (
    <Sidebar>
      <NewChatButton />
      {context === 'embedded' && <DevModeToggle />}
      {context === 'embedded' && <AdminModeToggle />}
      {context === 'account' && <BillingShortcut />}
    </Sidebar>
  );
}
Good
tsx
// libs/shared/ui-chat/src/lib/chat-sidebar.tsx
type SidebarAction = { id: string; render: () => ReactNode };

export function ChatSidebar({ actions }: { actions: SidebarAction[] }) {
  return (
    <Sidebar>
      <NewChatButton />
      {actions.map(a => <Fragment key={a.id}>{a.render()}</Fragment>)}
    </Sidebar>
  );
}

// apps/embedded-host/src/main.tsx
<ChatSidebar actions={[
  { id: 'dev-mode', render: () => <DevModeToggle /> },
  { id: 'admin-mode', render: () => <AdminModeToggle /> },
]} />

// apps/account/src/main.tsx
<ChatSidebar actions={[
  { id: 'billing', render: () => <BillingShortcut /> },
]} />

Contribute

Released under the MIT License.

esc