smithery.ai

designing-frontend-patterns

Claude designs scalable React component architectures using compound components, custom hooks, and state machines. Use when building reusable UI systems or complex component APIs.

First seen Mar 20, 2026

Installation

$ npx skills add https://smithery.ai

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery.ai · top by installs.

npx skills add https://smithery.ai

Browse all from smithery.ai

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 4,490 B
  • docs SUMMARY.md 214 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 1 installs

SKILL.md

Designing Frontend Patterns

Quick Start

// Compound component pattern with context
const SelectContext = createContext<SelectContextValue | null>(null);

export function Select({ children, value, onValueChange }: SelectProps) {
  const [isOpen, setIsOpen] = useState(false);
  return (
    <SelectContext.Provider value={{ isOpen, setIsOpen, value, onValueChange }}>
      <div className="relative">{children}</div>
    </SelectContext.Provider>
  );
}

Select.Trigger = SelectTrigger;
Select.Content = SelectContent;
Select.Item = SelectItem;

Features

Feature Description Guide
Compound Components Shared state via context for flexible component APIs ref/compound-components.md
Custom Hooks Encapsulate reusable logic (useDebounce, useLocalStorage) ref/custom-hooks.md
Render Props Maximum flexibility for data fetching and rendering ref/render-props.md
State Machines Predictable state transitions for complex flows ref/state-machines.md
HOCs Cross-cutting concerns (auth, error boundaries) ref/higher-order-components.md
Optimistic UI Instant feedback with rollback on failure ref/optimistic-updates.md

Common Patterns

Custom Hook with Cleanup

export function useDebounce<T>(value: T, delay: number): T {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const timer = setTimeout(() => setDebouncedValue(value), delay);
    return () => clearTimeout(timer);
  }, [value, delay]);

  return debouncedValue;
}

export function useLocalStorage<T>(key: string, initialValue: T) {
  const [stored, setStored] = useState<T>(() => {
    try {
      const item = window.localStorage.getItem(key);
      return item ? JSON.parse(item) : initialValue;
    } catch { return initialValue; }
  });

  useEffect(() => {
    window.localStorage.setItem(key, JSON.stringify(stored));
  }, [key, stored]);

  return [stored, setStored] as const;
}

State Machine Pattern

type FormState = 'idle' | 'validating' | 'submitting' | 'success' | 'error';
type FormEvent =
  | { type: 'SUBMIT'; data: FormData }
  | { type: 'SUCCESS'; response: any }
  | { type: 'ERROR'; error: string };

function useFormMachine() {
  const [state, setState] = useState<FormState>('idle');
  const [context, setContext] = useState({ data: null, error: null });

  const send = useCallback((event: FormEvent) => {
    switch (state) {
      case 'idle':
        if (event.type === 'SUBMIT') { setState('validating'); }
        break;
      case 'submitting':
        if (event.type === 'SUCCESS') { setState('success'); }
        if (event.type === 'ERROR') { setState('error'); setContext(c => ({ ...c, error: event.error })); }
        break;
    }
  }, [state]);

  return { state, context, send };
}

Optimistic Update Hook

export function useOptimistic<T>(initialData: T, reducer: (state: T, action: any) => T) {
  const [state, setState] = useState({ data: initialData, pending: false, error: null });
  const previousRef = useRef(initialData);

  const optimisticUpdate = useCallback(async (action: any, asyncOp: () => Promise<T>) => {
    previousRef.current = state.data;
    setState({ data: reducer(state.data, action), pending: true, error: null });

    try {
      const result = await asyncOp();
      setState({ data: result, pending: false, error: null });
    } catch (error) {
      setState({ data: previousRef.current, pending: false, error: error as Error });
    }
  }, [state.data, reducer]);

  return { ...state, optimisticUpdate };
}

Best Practices

Do Avoid
Use compound components for complex UI with shared state Overusing HOCs (prefer hooks)
Create custom hooks to encapsulate reusable logic Mutating state directly
Implement state machines for complex state transitions Deeply nested component hierarchies
Use TypeScript for type-safe component APIs Passing too many props (use context/composition)
Use forwardRef for component library primitives Creating components with side effects in render
Keep components focused with single responsibility Prop drilling for deeply nested data