本文へ移動
cccskills
GitHub Copilot 公式無料GitHub で公開

features-variants

Definitive guide to the app-local prototype feature/variant system: configuration, `useFeature()`, URL params, and anti-patterns. USE WHEN: editing `app/features.json`, using `useFeature()` in routes, creating design alternatives, A/B comparisons, layout options, alternate versions, or switching between design proposals. Trigger keywords: feature, variant, version, option, alternate, prototype, design option, A/B, comparison, switch between, try a different, another way, layout option, explore, side by side.

日本語の概要は準備中です。原文の説明を表示しています。

github/replicaスター 49(GitHub 49 + cccskills 0)

実行スコア 未検証

インストール方法を見る

含まれるファイル(1)

  • SKILL.md14.1 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Feature & Variant System Instructions

Paths below are relative to this app's directory.

What Is the Feature System?

CoreAI Sandbox has a built-in feature/variant system for tracking prototyped features and presenting multiple UI alternatives on the same page. It uses a neutral floating selector with small, elevated tab links and a brand-colored Prototype InteractionTag menu trigger to distinguish itself from the designs being prototyped.

A feature represents a prototyped change from main. A feature may:

  • Have variants — multiple design alternatives that can be switched between (e.g., different layouts)
  • Be variant-less — a single prototyped change with no alternatives (just a link to the location of the change)

Multiple features can be active simultaneously on the same page, each with their own independent variant selection.

You MUST use this system whenever a user asks to:

  • Try a different layout, design, or approach for a page or section
  • Create an "option B" or "version 2" of something
  • Compare two or more designs side by side
  • Add an A/B test or design alternative
  • Explore an alternate version of a feature

Do NOT build a custom toggle, tab switcher, or parallel component tree. The feature system already handles all of this.

For a guided walk-through tailored to designer-style requests, invoke the new-variant skill.


How It Works (Summary)

  1. Features are defined in app/features.json. Each feature may have variant options. The registry is currently empty; add definitions to its top-level features array.
  2. Active variants are encoded in the URL as repeated ?variant=feature-id--variant-id params — every combination is a shareable deep link.
  3. When a user navigates to a page with applicable features, the system automatically populates selections from valid URL values, then remembered client-navigation selections, then the first configured variant.
  4. A draggable floating switcher strip appears bottom-center by default showing each feature's variants as small, elevated router-backed tab links, when applicable variants exist and Show feature selector is enabled in the Prototype menu.
  5. Route components use the useFeature(featureId) hook to conditionally render based on the active variant.
  6. Multiple features can be active on the same page simultaneously with independent variant selections.

Architecture — Key Files

FilePurpose
app/features.jsonApp configuration: all features, routes, and variant labels
app/features/featureConfig.tsFeature schema, configuration validation, and route/URL helpers
app/features/FeatureContext.tsFeature context and public context types
app/features/FeatureProvider.tsxURL state, route matching, defaults, and floating selector composition
app/features/FeatureContext.ts (useFeature)Public hook for reading the active variant
app/features/FeatureFloatingUI.tsxFloating variant selector
app/features/FeatureMenu.tsxPrototype feature menu used by the app shell

URL Structure

Variants are encoded as repeated variant query params:

# Single feature with one variant active
?variant=agent-playground-layout--accordion

# Two features active simultaneously
?variant=agent-playground-layout--accordion&variant=code-tab--visible

# Variant-less features have no variant query param (they apply only on matching routes)

Each variant param is a feature-id--variant-id pair using kebab-case string identifiers.


Step-by-Step: Adding a New Variant to an Existing Feature

If a feature already exists in app/features.json and has variants, add a new variant:

1. Update app/features.json

Add a new entry to the variants array of the existing feature:

{
  "id": "your-new-variant",
  "label": "Your New Design Name"
}

Variant id values are kebab-case strings. Choose a descriptive, URL-friendly name.

2. Update the Route Component

In the route component that uses this feature, add a conditional branch for the new variant:

import { useFeature } from '~/features/FeatureContext';

function MyPage() {
  const variant = useFeature('agent-playground-layout');

  if (variant === 'accordion') return <AccordionLayout />;
  if (variant === 'your-new-variant') return <YourNewDesign />; // ← new
  return <DefaultLayout />; // first variant or null
}

That's it. The floating UI automatically shows the new tab link when the selector is visible on an applicable route.


Step-by-Step: Creating a New Feature

Feature WITH Variants

When the feature explores multiple design alternatives:

1. Add the feature to app/features.json

Add this object to the registry's top-level features array:

{
  "id": "agent-playground-layout",
  "label": "Agent Playground Layout",
  "notes": "What design question this feature explores.",
  "defaultRoute": "/build/agents/:agent/playground",
  "defaultParams": { "agent": "agent-001" },
  "routes": ["/build/agents/:agent/playground"],
  "variants": [
    { "id": "side-panel", "label": "Side Panel (Current)" },
    { "id": "accordion", "label": "Accordion Layout" }
  ]
}

2. Add useFeature() to the Route Component

import { useFeature } from '~/features/FeatureContext';

function MyPage() {
  const variant = useFeature('agent-playground-layout');

  if (variant === 'accordion') return <AccordionLayout />;
  return <DefaultLayout />; // 'side-panel' or null
}

Feature WITHOUT Variants

When the feature is a single prototyped change with no alternatives:

1. Add the feature to app/features.json

Add this object to the registry's top-level features array:

{
  "id": "dark-mode-revamp",
  "label": "Dark Mode Revamp",
  "notes": "Updated dark mode colors across settings page.",
  "defaultRoute": "/settings/appearance",
  "routes": ["/settings/appearance"]
}

No variants array needed. The feature appears in the Prototype InteractionTag menu as a navigation link. No useFeature() call is needed in the route component.


Field reference:

FieldRequiredDescription
idYesKebab-case string identifier (used in URL params)
labelYesHuman-readable name shown in the floating UI
notesYesDesign context — what question does this feature explore?
defaultRouteYesThe primary route to navigate to from the Prototype menu; must be in routes
defaultParamsNoFallback values for :param segments (e.g., { "agent": "agent-001" }); required when defaultRoute has required parameters
routesYesRoute patterns this feature applies to. Supports :param wildcards
variantsNoArray of { id: string, label: string }. Omit for variant-less features

Route pattern matching: A pattern like /build/agents/:agent/playground matches any URL of that shape. The :param segments are wildcards matched segment-by-segment.


useFeature() Return Values

const result = useFeature('feature-id');
// Returns:
//   string  — active variant id (e.g., 'accordion') if feature has variants
//   true    — if feature is variant-less and applies to current route
//   null    — if feature doesn't apply to current route

Multi-Feature Pages

A single page can have multiple features active simultaneously. Each component on the page calls useFeature() with its own feature ID independently.

const layout = useFeature('agent-playground-layout');
const codeTab = useFeature('code-tab-visibility');

// Both return their own variant independently
// URL: ?variant=agent-playground-layout--accordion&variant=code-tab-visibility--visible

The floating strip shows variant tab links for all applicable features with variants, separated by dividers.


Variant Scope — What Can Change?

A variant can change anything within its route component:

  • Full page replacement: Return entirely different component trees per variant
  • Section swap: Replace just one panel, card, or section
  • Prop changes: Same component with different props
  • Style changes: Different CSS classes per variant
  • Data presentation: Same data shown in different formats
  • Conditional features: Show/hide features like buttons, tabs, or panels

Example — Small Change (text variant)

const variant = useFeature('hero-text');
return (
  <Text preset="heading2" foreground={1}>
    {variant === 'version-b'
      ? 'Start Building with AI'
      : variant === 'version-c'
        ? 'Your AI Development Platform'
        : 'Welcome to CoreAI Sandbox'}
  </Text>
);

Example — Full Layout Swap

const variant = useFeature('playground-layout');
if (variant === 'accordion') return <AccordionLayout />;
if (variant === 'dialog') return <DialogLayout />;
return <SidePanelLayout />;

Variant-Exclusive Routes

Some variants introduce routes that only exist for that variant (e.g., a "Code" tab route that only exists when go-to-code--tab is active). If a user lands on a variant-exclusive route with the wrong variant selected, the route component should redirect:

const variant = useFeature('go-to-code');

// This route only exists for the "tab" variant — redirect otherwise
if (variant !== 'tab') return <Navigate to="../playground" replace />;

Keep this guard in the route component itself, colocated with the route that knows it's conditional. Do not add redirect logic to FeatureProvider.tsx.


Anti-Patterns — Do NOT Do These

❌ Don't✅ Do Instead
Build a custom toggle/switch for design alternativesUse useFeature() + app/features.json
Store variant state in localStorage or React stateURL query params (?variant=...) handle everything
Create separate routes for each design alternativeOne route, conditional rendering via useFeature()
Import feature implementation internals from app/features/featureConfig.ts or app/features/FeatureProvider.tsx in app componentsUse useFeature() from ~/features/FeatureContext
Hard-code variant IDs as numbersFeature and variant IDs are kebab-case strings
Add a new variant switching UI element into the product designThe floating tab-link UI is the switcher — it's meta-UI
Modify app-local feature-system internals for an app featureOnly modify app/features.json and the consuming component

Troubleshooting

Floating strip doesn't appear on my page:

  • Check that the route pattern in app/features.json matches your page's URL exactly (segment-by-segment)
  • :param segments match any value, but the number of segments must match
  • Ensure the applicable feature has variants and Show feature selector is enabled in the Prototype menu
  • Check browser console for errors

useFeature() returns null:

  • Verify you're passing the feature ID (string), not the variant ID
  • Verify the feature's routes array includes a pattern matching the current page

Variant tab links show but clicking doesn't change anything:

  • Ensure your component reads useFeature() and conditionally renders based on it
  • Make sure you're checking the correct variant IDs (kebab-case strings)

URL params get cleared when navigating:

  • This is expected for off-route variant params: they are removed. When returning during client navigation, valid URL selections take priority, then remembered selections, then the first configured variant. A reload uses the URL or the first variant, not remembered client-navigation state. Unrelated query params are preserved.

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

コメント

ログインなしで書き込めます。使ってみた感想、質問、動かなかった環境などを気軽にどうぞ。

まだコメントはありません。最初のコメントを書いてみませんか。

送信するとすぐに公開されます。メールアドレスや電話番号などの個人情報は書かないでください。URL は 2 つまでです。

0 / 1000 文字

このフォームは reCAPTCHA で保護されており、Google のプライバシーポリシーと利用規約が適用されます。

同じリポジトリのスキル

accessibility-audit

GitHub Copilot 公式無料

Audits actual components and routes against applicable WCAG 2.2 A/AA criteria using consumer-owned design-system evidence and repository tools. Use when asked for an accessibility audit, a11y check, keyboard or focus review, contrast check, or screen-reader verification.

日本語の概要は準備中です。原文の説明を表示しています。

github/replica492026年10月29日 更新

add-seed-data

GitHub Copilot 公式無料

Creates or updates believable deterministic raw fixture scenarios without breaking an existing prototype. Use when asked to add or change fixtures, seed data, sample data, scenarios, or cross-record relationships. Not for UI redesign, live-data infrastructure, or unrelated commands.

日本語の概要は準備中です。原文の説明を表示しています。

github/replica492026年10月29日 更新

agent-browser

GitHub Copilot 公式無料

Use for explicit agent-browser CLI checks or a named browser capability neither the Copilot canvas nor configured Playwright MCP can supply. Ordinary rendered checks and browser selection belong to browser-canvas-validation.

日本語の概要は準備中です。原文の説明を表示しています。

github/replica492026年10月29日 更新

browser-canvas-validation

GitHub Copilot 公式無料

Use the Copilot browser canvas first for rendered route checks, interaction tests, screenshots and visual, responsive or accessibility evidence. Use configured isolated Playwright MCP only when the canvas is unavailable for a required check.

日本語の概要は準備中です。原文の説明を表示しています。

github/replica492026年10月29日 更新

code-review

GitHub Copilot 公式無料

Review Replica pull requests using the same shared conventions and project guides as implementation agents. Use when reviewing changes to code, tests, workflows, or documentation in this repository.

日本語の概要は準備中です。原文の説明を表示しています。

github/replica492026年10月29日 更新

component-design-system-review

GitHub Copilot 公式無料

Reviews existing UI components for design-system consistency, states, responsiveness and accessibility using consumer-owned context. Use when asked to review component quality, check design-system adherence or audit component consistency.

日本語の概要は準備中です。原文の説明を表示しています。

github/replica492026年10月29日 更新

github のスキルをすべて見る

このスキルの問題を報告する