Smithery Logo
MCPsSkillsDocsPricing
Login
Smithery Logo

Accelerating the Agent Economy

Resources

DocumentationPrivacy PolicySystem Status

Company

PricingAboutBlog

Connect

© 2026 Smithery. All rights reserved.

    claudeforge

    frontend-patterns

    claudeforge/frontend-patterns
    Coding
    32
    2 installs

    About

    SKILL.md

    Install

    Install via Skills CLI

    or add to your agent
    • Claude Code
      Claude Code
    • Codex
      Codex
    • OpenClaw
      OpenClaw
    • Cursor
      Cursor
    • Amp
      Amp
    • GitHub Copilot
      GitHub Copilot
    • Gemini CLI
      Gemini CLI
    • Kilo Code
      Kilo Code
    • Junie
      Junie
    • Replit
      Replit
    • Windsurf
      Windsurf
    • Cline
      Cline
    • Continue
      Continue
    • OpenCode
      OpenCode
    • OpenHands
      OpenHands
    • Roo Code
      Roo Code
    • Augment
      Augment
    • Goose
      Goose
    • Trae
      Trae
    • Zencoder
      Zencoder
    • Antigravity
      Antigravity
    ├─
    ├─
    └─

    About

    Expert knowledge in React patterns, component design, state management, and frontend best practices. Use for frontend development tasks.

    SKILL.md

    Frontend Patterns Skill

    Modern React patterns and best practices for building scalable applications.

    Component Patterns

    1. Compound Components

    // Parent provides context, children consume it
    const Tabs = ({ children, defaultTab }) => {
      const [activeTab, setActiveTab] = useState(defaultTab);
    
      return (
        <TabsContext.Provider value={{ activeTab, setActiveTab }}>
          <div className="tabs">{children}</div>
        </TabsContext.Provider>
      );
    };
    
    Tabs.List = ({ children }) => <div className="tabs-list">{children}</div>;
    Tabs.Tab = ({ id, children }) => {
      const { activeTab, setActiveTab } = useTabsContext();
      return (
        <button
          className={activeTab === id ? 'active' : ''}
          onClick={() => setActiveTab(id)}
        >
          {children}
        </button>
      );
    };
    Tabs.Panel = ({ id, children }) => {
      const { activeTab } = useTabsContext();
      return activeTab === id ? <div>{children}</div> : null;
    };
    
    // Usage
    <Tabs defaultTab="tab1">
      <Tabs.List>
        <Tabs.Tab id="tab1">Tab 1</Tabs.Tab>
        <Tabs.Tab id="tab2">Tab 2</Tabs.Tab>
      </Tabs.List>
      <Tabs.Panel id="tab1">Content 1</Tabs.Panel>
      <Tabs.Panel id="tab2">Content 2</Tabs.Panel>
    </Tabs>
    

    2. Render Props

    interface MousePosition {
      x: number;
      y: number;
    }
    
    const MouseTracker = ({
      render,
    }: {
      render: (pos: MousePosition) => ReactNode;
    }) => {
      const [position, setPosition] = useState({ x: 0, y: 0 });
    
      useEffect(() => {
        const handleMove = (e: MouseEvent) => {
          setPosition({ x: e.clientX, y: e.clientY });
        };
        window.addEventListener('mousemove', handleMove);
        return () => window.removeEventListener('mousemove', handleMove);
      }, []);
    
      return <>{render(position)}</>;
    };
    
    // Usage
    <MouseTracker
      render={({ x, y }) => (
        <div>Mouse: {x}, {y}</div>
      )}
    />
    

    3. Custom Hooks

    // Reusable logic extraction
    function useLocalStorage<T>(key: string, initialValue: T) {
      const [storedValue, setStoredValue] = useState<T>(() => {
        try {
          const item = window.localStorage.getItem(key);
          return item ? JSON.parse(item) : initialValue;
        } catch {
          return initialValue;
        }
      });
    
      const setValue = (value: T | ((val: T) => T)) => {
        try {
          const valueToStore = value instanceof Function ? value(storedValue) : value;
          setStoredValue(valueToStore);
          window.localStorage.setItem(key, JSON.stringify(valueToStore));
        } catch (error) {
          console.error(error);
        }
      };
    
      return [storedValue, setValue] as const;
    }
    

    4. Higher-Order Components (HOC)

    function withAuth<P extends object>(Component: ComponentType<P>) {
      return function AuthenticatedComponent(props: P) {
        const { user, isLoading } = useAuth();
    
        if (isLoading) return <Spinner />;
        if (!user) return <Navigate to="/login" />;
    
        return <Component {...props} />;
      };
    }
    
    // Usage
    const ProtectedDashboard = withAuth(Dashboard);
    

    State Management Patterns

    Zustand Store Pattern

    interface Store {
      // State
      items: Item[];
      isLoading: boolean;
    
      // Actions
      fetchItems: () => Promise<void>;
      addItem: (item: Item) => void;
      removeItem: (id: string) => void;
    }
    
    const useStore = create<Store>((set, get) => ({
      items: [],
      isLoading: false,
    
      fetchItems: async () => {
        set({ isLoading: true });
        try {
          const items = await api.getItems();
          set({ items, isLoading: false });
        } catch {
          set({ isLoading: false });
        }
      },
    
      addItem: (item) => set((state) => ({
        items: [...state.items, item],
      })),
    
      removeItem: (id) => set((state) => ({
        items: state.items.filter((i) => i.id !== id),
      })),
    }));
    
    // Selectors for performance
    const useItems = () => useStore((s) => s.items);
    const useIsLoading = () => useStore((s) => s.isLoading);
    

    React Query Pattern

    // Query keys factory
    const todoKeys = {
      all: ['todos'] as const,
      lists: () => [...todoKeys.all, 'list'] as const,
      list: (filters: string) => [...todoKeys.lists(), { filters }] as const,
      details: () => [...todoKeys.all, 'detail'] as const,
      detail: (id: string) => [...todoKeys.details(), id] as const,
    };
    
    // Queries
    export const useTodos = (filters?: string) =>
      useQuery({
        queryKey: todoKeys.list(filters ?? ''),
        queryFn: () => fetchTodos(filters),
      });
    
    // Mutations with optimistic updates
    export const useUpdateTodo = () => {
      const queryClient = useQueryClient();
    
      return useMutation({
        mutationFn: updateTodo,
        onMutate: async (newTodo) => {
          await queryClient.cancelQueries({ queryKey: todoKeys.lists() });
          const previous = queryClient.getQueryData(todoKeys.lists());
          queryClient.setQueryData(todoKeys.lists(), (old) =>
            old?.map((t) => (t.id === newTodo.id ? newTodo : t))
          );
          return { previous };
        },
        onError: (err, newTodo, context) => {
          queryClient.setQueryData(todoKeys.lists(), context?.previous);
        },
        onSettled: () => {
          queryClient.invalidateQueries({ queryKey: todoKeys.lists() });
        },
      });
    };
    

    Performance Patterns

    Memoization

    // Memoize expensive calculations
    const expensiveValue = useMemo(() => {
      return items.filter(x => x.active).reduce((acc, x) => acc + x.value, 0);
    }, [items]);
    
    // Memoize callbacks
    const handleClick = useCallback((id: string) => {
      setSelected(id);
    }, []);
    
    // Memoize components
    const MemoizedList = memo(({ items }: { items: Item[] }) => (
      <ul>
        {items.map(item => <li key={item.id}>{item.name}</li>)}
      </ul>
    ));
    

    Code Splitting

    // Lazy load routes
    const Dashboard = lazy(() => import('./pages/Dashboard'));
    const Settings = lazy(() => import('./pages/Settings'));
    
    // With loading fallback
    <Suspense fallback={<PageSkeleton />}>
      <Routes>
        <Route path="/dashboard" element={<Dashboard />} />
        <Route path="/settings" element={<Settings />} />
      </Routes>
    </Suspense>
    

    Virtual Lists

    import { useVirtualizer } from '@tanstack/react-virtual';
    
    function VirtualList({ items }: { items: Item[] }) {
      const parentRef = useRef<HTMLDivElement>(null);
    
      const virtualizer = useVirtualizer({
        count: items.length,
        getScrollElement: () => parentRef.current,
        estimateSize: () => 50,
      });
    
      return (
        <div ref={parentRef} style={{ height: 400, overflow: 'auto' }}>
          <div style={{ height: virtualizer.getTotalSize() }}>
            {virtualizer.getVirtualItems().map((virtualItem) => (
              <div
                key={virtualItem.key}
                style={{
                  position: 'absolute',
                  top: virtualItem.start,
                  height: virtualItem.size,
                }}
              >
                {items[virtualItem.index].name}
              </div>
            ))}
          </div>
        </div>
      );
    }
    

    Error Handling

    Error Boundaries

    class ErrorBoundary extends Component<Props, State> {
      state = { hasError: false, error: null };
    
      static getDerivedStateFromError(error: Error) {
        return { hasError: true, error };
      }
    
      componentDidCatch(error: Error, info: ErrorInfo) {
        console.error('Error caught:', error, info);
      }
    
      render() {
        if (this.state.hasError) {
          return <ErrorFallback error={this.state.error} />;
        }
        return this.props.children;
      }
    }
    

    Accessibility Patterns

    // Focus management
    const modalRef = useRef<HTMLDivElement>(null);
    useEffect(() => {
      modalRef.current?.focus();
    }, []);
    
    // ARIA attributes
    <button
      aria-label="Close modal"
      aria-expanded={isOpen}
      aria-controls="modal-content"
    >
      <CloseIcon />
    </button>
    
    // Keyboard navigation
    const handleKeyDown = (e: KeyboardEvent) => {
      switch (e.key) {
        case 'ArrowDown':
          setFocusedIndex(i => Math.min(i + 1, items.length - 1));
          break;
        case 'ArrowUp':
          setFocusedIndex(i => Math.max(i - 1, 0));
          break;
        case 'Enter':
          handleSelect(focusedIndex);
          break;
      }
    };
    
    Repository
    claudeforge/orchestrator
    Files