frontend-patterns — community frontend-patterns, kanokna, community, ide skills, Claude Code, Cursor, Windsurf

v1.0.0
GitHub

About this Skill

Ideal for Full Stack Agents requiring advanced frontend development capabilities with React, Next.js, and Angular Spring Boot application and Angular application

vonomarap vonomarap
[0]
[0]
Updated: 3/5/2026

Agent Capability Analysis

The frontend-patterns skill by vonomarap is an open-source community AI agent skill for Claude Code and other IDE workflows, helping agents execute tasks with better context, repeatability, and domain-specific guidance.

Ideal Agent Persona

Ideal for Full Stack Agents requiring advanced frontend development capabilities with React, Next.js, and Angular

Core Value

Empowers agents to craft performant user interfaces using composition over inheritance, leveraging TypeScript and modern frontend patterns for efficient component design, and integrating with frameworks like Spring Boot for seamless backend connectivity

Capabilities Granted for frontend-patterns

Implementing reusable UI components with React and Next.js
Optimizing application performance using efficient frontend patterns
Debugging complex frontend issues with Angular and TypeScript

! Prerequisites & Limits

  • Requires knowledge of TypeScript and JavaScript
  • Focused on React, Next.js, and Angular frameworks
  • Limited to frontend development, does not cover backend or full-stack development
Labs Demo

Browser Sandbox Environment

⚡️ Ready to unleash?

Experience this Agent in a zero-setup browser environment powered by WebContainers. No installation required.

Boot Container Sandbox

frontend-patterns

Install frontend-patterns, an AI agent skill for AI agent workflows and automation. Works with Claude Code, Cursor, and Windsurf with one-command setup.

SKILL.md
Readonly

Frontend Development Patterns

Modern frontend patterns for React, Next.js, and performant user interfaces.

Component Patterns

Composition Over Inheritance

typescript
1// ✅ GOOD: Component composition 2interface CardProps { 3 children: React.ReactNode 4 variant?: 'default' | 'outlined' 5} 6 7export function Card({ children, variant = 'default' }: CardProps) { 8 return <div className={`card card-${variant}`}>{children}</div> 9} 10 11export function CardHeader({ children }: { children: React.ReactNode }) { 12 return <div className="card-header">{children}</div> 13} 14 15export function CardBody({ children }: { children: React.ReactNode }) { 16 return <div className="card-body">{children}</div> 17} 18 19// Usage 20<Card> 21 <CardHeader>Title</CardHeader> 22 <CardBody>Content</CardBody> 23</Card>

Compound Components

typescript
1interface TabsContextValue { 2 activeTab: string 3 setActiveTab: (tab: string) => void 4} 5 6const TabsContext = createContext<TabsContextValue | undefined>(undefined) 7 8export function Tabs({ children, defaultTab }: { 9 children: React.ReactNode 10 defaultTab: string 11}) { 12 const [activeTab, setActiveTab] = useState(defaultTab) 13 14 return ( 15 <TabsContext.Provider value={{ activeTab, setActiveTab }}> 16 {children} 17 </TabsContext.Provider> 18 ) 19} 20 21export function TabList({ children }: { children: React.ReactNode }) { 22 return <div className="tab-list">{children}</div> 23} 24 25export function Tab({ id, children }: { id: string, children: React.ReactNode }) { 26 const context = useContext(TabsContext) 27 if (!context) throw new Error('Tab must be used within Tabs') 28 29 return ( 30 <button 31 className={context.activeTab === id ? 'active' : ''} 32 onClick={() => context.setActiveTab(id)} 33 > 34 {children} 35 </button> 36 ) 37} 38 39// Usage 40<Tabs defaultTab="overview"> 41 <TabList> 42 <Tab id="overview">Overview</Tab> 43 <Tab id="details">Details</Tab> 44 </TabList> 45</Tabs>

Render Props Pattern

typescript
1interface DataLoaderProps<T> { 2 url: string 3 children: (data: T | null, loading: boolean, error: Error | null) => React.ReactNode 4} 5 6export function DataLoader<T>({ url, children }: DataLoaderProps<T>) { 7 const [data, setData] = useState<T | null>(null) 8 const [loading, setLoading] = useState(true) 9 const [error, setError] = useState<Error | null>(null) 10 11 useEffect(() => { 12 fetch(url) 13 .then(res => res.json()) 14 .then(setData) 15 .catch(setError) 16 .finally(() => setLoading(false)) 17 }, [url]) 18 19 return <>{children(data, loading, error)}</> 20} 21 22// Usage 23<DataLoader<Market[]> url="/api/markets"> 24 {(markets, loading, error) => { 25 if (loading) return <Spinner /> 26 if (error) return <Error error={error} /> 27 return <MarketList markets={markets!} /> 28 }} 29</DataLoader>

Custom Hooks Patterns

State Management Hook

typescript
1export function useToggle(initialValue = false): [boolean, () => void] { 2 const [value, setValue] = useState(initialValue) 3 4 const toggle = useCallback(() => { 5 setValue(v => !v) 6 }, []) 7 8 return [value, toggle] 9} 10 11// Usage 12const [isOpen, toggleOpen] = useToggle()

Async Data Fetching Hook

typescript
1interface UseQueryOptions<T> { 2 onSuccess?: (data: T) => void 3 onError?: (error: Error) => void 4 enabled?: boolean 5} 6 7export function useQuery<T>( 8 key: string, 9 fetcher: () => Promise<T>, 10 options?: UseQueryOptions<T> 11) { 12 const [data, setData] = useState<T | null>(null) 13 const [error, setError] = useState<Error | null>(null) 14 const [loading, setLoading] = useState(false) 15 16 const refetch = useCallback(async () => { 17 setLoading(true) 18 setError(null) 19 20 try { 21 const result = await fetcher() 22 setData(result) 23 options?.onSuccess?.(result) 24 } catch (err) { 25 const error = err as Error 26 setError(error) 27 options?.onError?.(error) 28 } finally { 29 setLoading(false) 30 } 31 }, [fetcher, options]) 32 33 useEffect(() => { 34 if (options?.enabled !== false) { 35 refetch() 36 } 37 }, [key, refetch, options?.enabled]) 38 39 return { data, error, loading, refetch } 40} 41 42// Usage 43const { data: markets, loading, error, refetch } = useQuery( 44 'markets', 45 () => fetch('/api/markets').then(r => r.json()), 46 { 47 onSuccess: data => console.log('Fetched', data.length, 'markets'), 48 onError: err => console.error('Failed:', err) 49 } 50)

Debounce Hook

typescript
1export function useDebounce<T>(value: T, delay: number): T { 2 const [debouncedValue, setDebouncedValue] = useState<T>(value) 3 4 useEffect(() => { 5 const handler = setTimeout(() => { 6 setDebouncedValue(value) 7 }, delay) 8 9 return () => clearTimeout(handler) 10 }, [value, delay]) 11 12 return debouncedValue 13} 14 15// Usage 16const [searchQuery, setSearchQuery] = useState('') 17const debouncedQuery = useDebounce(searchQuery, 500) 18 19useEffect(() => { 20 if (debouncedQuery) { 21 performSearch(debouncedQuery) 22 } 23}, [debouncedQuery])

State Management Patterns

Context + Reducer Pattern

typescript
1interface State { 2 markets: Market[] 3 selectedMarket: Market | null 4 loading: boolean 5} 6 7type Action = 8 | { type: 'SET_MARKETS'; payload: Market[] } 9 | { type: 'SELECT_MARKET'; payload: Market } 10 | { type: 'SET_LOADING'; payload: boolean } 11 12function reducer(state: State, action: Action): State { 13 switch (action.type) { 14 case 'SET_MARKETS': 15 return { ...state, markets: action.payload } 16 case 'SELECT_MARKET': 17 return { ...state, selectedMarket: action.payload } 18 case 'SET_LOADING': 19 return { ...state, loading: action.payload } 20 default: 21 return state 22 } 23} 24 25const MarketContext = createContext<{ 26 state: State 27 dispatch: Dispatch<Action> 28} | undefined>(undefined) 29 30export function MarketProvider({ children }: { children: React.ReactNode }) { 31 const [state, dispatch] = useReducer(reducer, { 32 markets: [], 33 selectedMarket: null, 34 loading: false 35 }) 36 37 return ( 38 <MarketContext.Provider value={{ state, dispatch }}> 39 {children} 40 </MarketContext.Provider> 41 ) 42} 43 44export function useMarkets() { 45 const context = useContext(MarketContext) 46 if (!context) throw new Error('useMarkets must be used within MarketProvider') 47 return context 48}

Performance Optimization

Memoization

typescript
1// ✅ useMemo for expensive computations 2const sortedMarkets = useMemo(() => { 3 return markets.sort((a, b) => b.volume - a.volume) 4}, [markets]) 5 6// ✅ useCallback for functions passed to children 7const handleSearch = useCallback((query: string) => { 8 setSearchQuery(query) 9}, []) 10 11// ✅ React.memo for pure components 12export const MarketCard = React.memo<MarketCardProps>(({ market }) => { 13 return ( 14 <div className="market-card"> 15 <h3>{market.name}</h3> 16 <p>{market.description}</p> 17 </div> 18 ) 19})

Code Splitting & Lazy Loading

typescript
1import { lazy, Suspense } from 'react' 2 3// ✅ Lazy load heavy components 4const HeavyChart = lazy(() => import('./HeavyChart')) 5const ThreeJsBackground = lazy(() => import('./ThreeJsBackground')) 6 7export function Dashboard() { 8 return ( 9 <div> 10 <Suspense fallback={<ChartSkeleton />}> 11 <HeavyChart data={data} /> 12 </Suspense> 13 14 <Suspense fallback={null}> 15 <ThreeJsBackground /> 16 </Suspense> 17 </div> 18 ) 19}

Virtualization for Long Lists

typescript
1import { useVirtualizer } from '@tanstack/react-virtual' 2 3export function VirtualMarketList({ markets }: { markets: Market[] }) { 4 const parentRef = useRef<HTMLDivElement>(null) 5 6 const virtualizer = useVirtualizer({ 7 count: markets.length, 8 getScrollElement: () => parentRef.current, 9 estimateSize: () => 100, // Estimated row height 10 overscan: 5 // Extra items to render 11 }) 12 13 return ( 14 <div ref={parentRef} style={{ height: '600px', overflow: 'auto' }}> 15 <div 16 style={{ 17 height: `${virtualizer.getTotalSize()}px`, 18 position: 'relative' 19 }} 20 > 21 {virtualizer.getVirtualItems().map(virtualRow => ( 22 <div 23 key={virtualRow.index} 24 style={{ 25 position: 'absolute', 26 top: 0, 27 left: 0, 28 width: '100%', 29 height: `${virtualRow.size}px`, 30 transform: `translateY(${virtualRow.start}px)` 31 }} 32 > 33 <MarketCard market={markets[virtualRow.index]} /> 34 </div> 35 ))} 36 </div> 37 </div> 38 ) 39}

Form Handling Patterns

Controlled Form with Validation

typescript
1interface FormData { 2 name: string 3 description: string 4 endDate: string 5} 6 7interface FormErrors { 8 name?: string 9 description?: string 10 endDate?: string 11} 12 13export function CreateMarketForm() { 14 const [formData, setFormData] = useState<FormData>({ 15 name: '', 16 description: '', 17 endDate: '' 18 }) 19 20 const [errors, setErrors] = useState<FormErrors>({}) 21 22 const validate = (): boolean => { 23 const newErrors: FormErrors = {} 24 25 if (!formData.name.trim()) { 26 newErrors.name = 'Name is required' 27 } else if (formData.name.length > 200) { 28 newErrors.name = 'Name must be under 200 characters' 29 } 30 31 if (!formData.description.trim()) { 32 newErrors.description = 'Description is required' 33 } 34 35 if (!formData.endDate) { 36 newErrors.endDate = 'End date is required' 37 } 38 39 setErrors(newErrors) 40 return Object.keys(newErrors).length === 0 41 } 42 43 const handleSubmit = async (e: React.FormEvent) => { 44 e.preventDefault() 45 46 if (!validate()) return 47 48 try { 49 await createMarket(formData) 50 // Success handling 51 } catch (error) { 52 // Error handling 53 } 54 } 55 56 return ( 57 <form onSubmit={handleSubmit}> 58 <input 59 value={formData.name} 60 onChange={e => setFormData(prev => ({ ...prev, name: e.target.value }))} 61 placeholder="Market name" 62 /> 63 {errors.name && <span className="error">{errors.name}</span>} 64 65 {/* Other fields */} 66 67 <button type="submit">Create Market</button> 68 </form> 69 ) 70}

Error Boundary Pattern

typescript
1interface ErrorBoundaryState { 2 hasError: boolean 3 error: Error | null 4} 5 6export class ErrorBoundary extends React.Component< 7 { children: React.ReactNode }, 8 ErrorBoundaryState 9> { 10 state: ErrorBoundaryState = { 11 hasError: false, 12 error: null 13 } 14 15 static getDerivedStateFromError(error: Error): ErrorBoundaryState { 16 return { hasError: true, error } 17 } 18 19 componentDidCatch(error: Error, errorInfo: React.ErrorInfo) { 20 console.error('Error boundary caught:', error, errorInfo) 21 } 22 23 render() { 24 if (this.state.hasError) { 25 return ( 26 <div className="error-fallback"> 27 <h2>Something went wrong</h2> 28 <p>{this.state.error?.message}</p> 29 <button onClick={() => this.setState({ hasError: false })}> 30 Try again 31 </button> 32 </div> 33 ) 34 } 35 36 return this.props.children 37 } 38} 39 40// Usage 41<ErrorBoundary> 42 <App /> 43</ErrorBoundary>

Animation Patterns

Framer Motion Animations

typescript
1import { motion, AnimatePresence } from 'framer-motion' 2 3// ✅ List animations 4export function AnimatedMarketList({ markets }: { markets: Market[] }) { 5 return ( 6 <AnimatePresence> 7 {markets.map(market => ( 8 <motion.div 9 key={market.id} 10 initial={{ opacity: 0, y: 20 }} 11 animate={{ opacity: 1, y: 0 }} 12 exit={{ opacity: 0, y: -20 }} 13 transition={{ duration: 0.3 }} 14 > 15 <MarketCard market={market} /> 16 </motion.div> 17 ))} 18 </AnimatePresence> 19 ) 20} 21 22// ✅ Modal animations 23export function Modal({ isOpen, onClose, children }: ModalProps) { 24 return ( 25 <AnimatePresence> 26 {isOpen && ( 27 <> 28 <motion.div 29 className="modal-overlay" 30 initial={{ opacity: 0 }} 31 animate={{ opacity: 1 }} 32 exit={{ opacity: 0 }} 33 onClick={onClose} 34 /> 35 <motion.div 36 className="modal-content" 37 initial={{ opacity: 0, scale: 0.9, y: 20 }} 38 animate={{ opacity: 1, scale: 1, y: 0 }} 39 exit={{ opacity: 0, scale: 0.9, y: 20 }} 40 > 41 {children} 42 </motion.div> 43 </> 44 )} 45 </AnimatePresence> 46 ) 47}

Accessibility Patterns

Keyboard Navigation

typescript
1export function Dropdown({ options, onSelect }: DropdownProps) { 2 const [isOpen, setIsOpen] = useState(false) 3 const [activeIndex, setActiveIndex] = useState(0) 4 5 const handleKeyDown = (e: React.KeyboardEvent) => { 6 switch (e.key) { 7 case 'ArrowDown': 8 e.preventDefault() 9 setActiveIndex(i => Math.min(i + 1, options.length - 1)) 10 break 11 case 'ArrowUp': 12 e.preventDefault() 13 setActiveIndex(i => Math.max(i - 1, 0)) 14 break 15 case 'Enter': 16 e.preventDefault() 17 onSelect(options[activeIndex]) 18 setIsOpen(false) 19 break 20 case 'Escape': 21 setIsOpen(false) 22 break 23 } 24 } 25 26 return ( 27 <div 28 role="combobox" 29 aria-expanded={isOpen} 30 aria-haspopup="listbox" 31 onKeyDown={handleKeyDown} 32 > 33 {/* Dropdown implementation */} 34 </div> 35 ) 36}

Focus Management

typescript
1export function Modal({ isOpen, onClose, children }: ModalProps) { 2 const modalRef = useRef<HTMLDivElement>(null) 3 const previousFocusRef = useRef<HTMLElement | null>(null) 4 5 useEffect(() => { 6 if (isOpen) { 7 // Save currently focused element 8 previousFocusRef.current = document.activeElement as HTMLElement 9 10 // Focus modal 11 modalRef.current?.focus() 12 } else { 13 // Restore focus when closing 14 previousFocusRef.current?.focus() 15 } 16 }, [isOpen]) 17 18 return isOpen ? ( 19 <div 20 ref={modalRef} 21 role="dialog" 22 aria-modal="true" 23 tabIndex={-1} 24 onKeyDown={e => e.key === 'Escape' && onClose()} 25 > 26 {children} 27 </div> 28 ) : null 29}

Remember: Modern frontend patterns enable maintainable, performant user interfaces. Choose patterns that fit your project complexity.

FAQ & Installation Steps

These questions and steps mirror the structured data on this page for better search understanding.

? Frequently Asked Questions

What is frontend-patterns?

Ideal for Full Stack Agents requiring advanced frontend development capabilities with React, Next.js, and Angular Spring Boot application and Angular application

How do I install frontend-patterns?

Run the command: npx killer-skills add vonomarap/kanokna/frontend-patterns. It works with Cursor, Windsurf, VS Code, Claude Code, and 19+ other IDEs.

What are the use cases for frontend-patterns?

Key use cases include: Implementing reusable UI components with React and Next.js, Optimizing application performance using efficient frontend patterns, Debugging complex frontend issues with Angular and TypeScript.

Which IDEs are compatible with frontend-patterns?

This skill is compatible with Cursor, Windsurf, VS Code, Trae, Claude Code, OpenClaw, Aider, Codex, OpenCode, Goose, Cline, Roo Code, Kiro, Augment Code, Continue, GitHub Copilot, Sourcegraph Cody, and Amazon Q Developer. Use the Killer-Skills CLI for universal one-command installation.

Are there any limitations for frontend-patterns?

Requires knowledge of TypeScript and JavaScript. Focused on React, Next.js, and Angular frameworks. Limited to frontend development, does not cover backend or full-stack development.

How To Install

  1. 1. Open your terminal

    Open the terminal or command line in your project directory.

  2. 2. Run the install command

    Run: npx killer-skills add vonomarap/kanokna/frontend-patterns. The CLI will automatically detect your IDE or AI agent and configure the skill.

  3. 3. Start using the skill

    The skill is now active. Your AI agent can use frontend-patterns immediately in the current project.

Related Skills

Looking for an alternative to frontend-patterns or another community skill for your workflow? Explore these related open-source skills.

View All

widget-generator

Logo of f
f

f.k.a. Awesome ChatGPT Prompts. Share, discover, and collect prompts from the community. Free and open source — self-host for your organization with complete privacy.

149.6k
0
AI

flags

Logo of vercel
vercel

flags is a Next.js feature management skill that enables developers to efficiently add or modify framework feature flags, streamlining React application development.

138.4k
0
Browser

zustand

Logo of lobehub
lobehub

The ultimate space for work and life — to find, build, and collaborate with agent teammates that grow with you. We are taking agent harness to the next level — enabling multi-agent collaboration, effortless agent team design, and introducing agents as the unit of work interaction.

72.8k
0
AI

data-fetching

Logo of lobehub
lobehub

The ultimate space for work and life — to find, build, and collaborate with agent teammates that grow with you. We are taking agent harness to the next level — enabling multi-agent collaboration, effortless agent team design, and introducing agents as the unit of work interaction.

72.8k
0
AI