
Vercel Composition Patterns
Refactor or generate React UI using Vercel-style composition—compound components, lifted providers, and explicit variants instead of boolean prop sprawl.
Overview
vercel-composition-patterns is an agent skill most often used in Build frontend (also Ship review) that encodes React composition rules to limit boolean props and scale UI with compound components.
Install
npx skills add https://github.com/vercel-labs/sandcastle --skill vercel-composition-patternsWhat is this skill?
- Three-tier guide: Component Architecture (HIGH), State Management (MEDIUM), Implementation Patterns (MEDIUM)
- Rule 1.1: avoid boolean prop proliferation; prefer composition over isOpen/isLoading flags
- Compound components and provider-lifted state (sections 1.2, 2.3)
- Generic context interfaces for dependency injection (section 2.2)
- Explicit component variants and children-over-render-props guidance (section 3.x)
- Version 1.0.0 (January 2026) with 3 top-level sections and 8 numbered sub-rules in the table of contents
- Component Architecture section marked HIGH priority; State Management and Implementation marked MEDIUM
Adoption & trust: 3 installs on skills.sh; 48 GitHub stars.
What problem does it solve?
Your React components accrue boolean and mode props until agents and humans cannot safely extend or refactor the tree.
Who is it for?
Solo builders on React/Next.js who use AI for large UI refactors and want a single composition rulebook.
Skip if: Non-React stacks, throwaway prototypes with no intention to maintain component APIs, or backend-only work.
When should I use this skill?
Maintaining, generating, or refactoring React components and boolean props or render-prop complexity are spreading.
What do I get? / Deliverables
Refactors and new UI follow compound-component and provider patterns with explicit variants, making generated React easier to extend consistently.
- Refactored component trees using compound patterns
- Provider-based state lifts and explicit variant components
Recommended Skills
Journey fit
Spans multiple journey phases - primary shelf plus alternate fits below.
React structure decisions belong in Build frontend work and recur whenever agents touch UI code. frontend is the primary shelf for component architecture guidance aimed at LLM-maintained React codebases.
Where it fits
Agent scaffolds a modal flow using compound Modal + Modal.Header instead of eight boolean visibility props.
You reject a PR that adds isCompact and isBordered flags and point the agent at explicit variant components.
A hotfix request extends a data table without breaking DI contexts because generic context interfaces were already defined.
How it compares
Architecture rule pack for React composition—not a component library install or a visual design system skill.
Common Questions / FAQ
Who is vercel-composition-patterns for?
Developers and agent workflows maintaining React codebases who need consistent composition rules instead of ad-hoc prop flags.
When should I use vercel-composition-patterns?
Use it in Build frontend when generating or refactoring components; in Ship review when reviewing agent PRs that add boolean props; in Operate iterate when UI debt blocks fast fixes.
Is vercel-composition-patterns safe to install?
It is guidance-only with no runtime hooks; still review the Security Audits panel on this page before trusting any bundled repo tooling.
SKILL.md
READMESKILL.md - Vercel Composition Patterns
# React Composition Patterns **Version 1.0.0** Engineering January 2026 > **Note:** > This document is mainly for agents and LLMs to follow when maintaining, > generating, or refactoring React codebases using composition. Humans > may also find it useful, but guidance here is optimized for automation > and consistency by AI-assisted workflows. --- ## Abstract Composition patterns for building flexible, maintainable React components. Avoid boolean prop proliferation by using compound components, lifting state, and composing internals. These patterns make codebases easier for both humans and AI agents to work with as they scale. --- ## Table of Contents 1. [Component Architecture](#1-component-architecture) — **HIGH** - 1.1 [Avoid Boolean Prop Proliferation](#11-avoid-boolean-prop-proliferation) - 1.2 [Use Compound Components](#12-use-compound-components) 2. [State Management](#2-state-management) — **MEDIUM** - 2.1 [Decouple State Management from UI](#21-decouple-state-management-from-ui) - 2.2 [Define Generic Context Interfaces for Dependency Injection](#22-define-generic-context-interfaces-for-dependency-injection) - 2.3 [Lift State into Provider Components](#23-lift-state-into-provider-components) 3. [Implementation Patterns](#3-implementation-patterns) — **MEDIUM** - 3.1 [Create Explicit Component Variants](#31-create-explicit-component-variants) - 3.2 [Prefer Composing Children Over Render Props](#32-prefer-composing-children-over-render-props) 4. [React 19 APIs](#4-react-19-apis) — **MEDIUM** - 4.1 [React 19 API Changes](#41-react-19-api-changes) --- ## 1. Component Architecture **Impact: HIGH** Fundamental patterns for structuring components to avoid prop proliferation and enable flexible composition. ### 1.1 Avoid Boolean Prop Proliferation **Impact: CRITICAL (prevents unmaintainable component variants)** Don't add boolean props like `isThread`, `isEditing`, `isDMThread` to customize component behavior. Each boolean doubles possible states and creates unmaintainable conditional logic. Use composition instead. **Incorrect: boolean props create exponential complexity** ```tsx function Composer({ onSubmit, isThread, channelId, isDMThread, dmId, isEditing, isForwarding, }: Props) { return ( <form> <Header /> <Input /> {isDMThread ? ( <AlsoSendToDMField id={dmId} /> ) : isThread ? ( <AlsoSendToChannelField id={channelId} /> ) : null} {isEditing ? ( <EditActions /> ) : isForwarding ? ( <ForwardActions /> ) : ( <DefaultActions /> )} <Footer onSubmit={onSubmit} /> </form> ) } ``` **Correct: composition eliminates conditionals** ```tsx // Channel composer function ChannelComposer() { return ( <Composer.Frame> <Composer.Header /> <Composer.Input /> <Composer.Footer> <Composer.Attachments /> <Composer.Formatting /> <Composer.Emojis /> <Composer.Submit /> </Composer.Footer> </Composer.Frame> ) } // Thread composer - adds "also send to channel" field function ThreadComposer({ channelId }: { channelId: string }) { return ( <Composer.Frame> <Composer.Header /> <Composer.Input /> <AlsoSendToChannelField id={channelId} /> <Composer.Footer> <Composer.Formatting /> <Composer.Emojis /> <Composer.Submit /> </Composer.Footer> </Composer.Frame> ) } // Edit composer - different footer actions function EditComposer() { return ( <Composer.Frame> <Composer.Input /> <Composer.Footer> <Composer.Formatting /> <Composer.Emojis /> <Composer.CancelEdit /> <Composer.SaveEdit /> </Composer.Footer> </Composer.Frame> ) } ``` Each variant is explicit about what it renders. We can share internals without sharing a single monolithic parent. ### 1.2 Use Compound Components **Impact: