agni-kai
Zuko's Agni Kai for bakeoffs. The formal firebending duel, where competing implementations fight under the same rules and a judge…
Build modern React/Next.js frontends. Use when creating web applications, choosing frontend stack, structuring components, or implementing UI/UX designs. Covers React, Next.js, Tailwind CSS, and component patterns.
$ npx -y skills add tmcfarlane/team-avatar --skill frontend-builder --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/frontend-builderContext preview
The summary Claude sees to decide when to auto-load this skill.
Build modern React/Next.js frontends. Use when creating web applications, choosing frontend stack, structuring components, or implementing UI/UX designs. Covers React, Next.js, Tailwind CSS, and component patterns.
name: Frontend Builder description: Build modern React/Next.js frontends. Use when creating web applications, choosing frontend stack, structuring components, or implementing UI/UX designs. Covers React, Next.js, Tailwind CSS, and component patterns. version: 1.0.0
Build maintainable, performant React and Next.js frontends.
Break UI into small, reusable, single-purpose components
Keep state as close to where it's used as possible
Optimize rendering, code splitting, and asset loading
Clear naming, consistent patterns, helpful errors
**Use React + Vite when**:
**Use Next.js when**:
**Recommended for most projects**: Next.js (App Router)
---
**1. Page Components** (Route entry points):
// app/users/page.tsx (Next.js App Router)
export default function UsersPage() {
return (
<div>
<Header />
<UserList />
<Footer />
</div>
)
}**2. Feature Components** (Business logic):
// components/features/UserList.tsx
export function UserList() {
const { data, isLoading } = useUsers()
if (isLoading) return <LoadingSpinner />
return (
<div>
{data.map(user => <UserCard key={user.id} user={user} />)}
</div>
)
}**3. UI Components** (Reusable, no business logic):
// components/ui/button.tsx
export function Button({ children, variant = 'primary', ...props }) {
return (
<button
className={cn(buttonVariants[variant])}
{...props}
>
{children}
</button>
)
}// ✅ Good: Small, focused, typed
interface UserProfileProps {
user: User
onEdit?: () => void
}
export function UserProfile({ user, onEdit }: UserProfileProps) {
return (
<div className="flex gap-4">
<Avatar src={user.avatar} alt={user.name} />
<UserDetails user={user} />
{onEdit && <Button onClick={onEdit}>Edit</Button>}
</div>
)
}
// ❌ Bad: Giant, untyped, unclear
export function UserProfile(props) {
// 500 lines of JSX, multiple responsibilities
return <div>...</div>
}---
How many components need this state? │ ├─ One component → useState ├─ Parent + children → Props or useState + props ├─ Siblings → Lift to common parent ├─ Widely used (theme, auth) → Context API └─ Complex app state → Zustand or Redux
// For component-level state
function Counter() {
const [count, setCount] = useState(0)
const [isOpen, setIsOpen] = useState(false)
return (
<div>
<button onClick={() => setCount(count + 1)}>{count}</button>
</div>
)
}// For app-wide state (theme, auth, user)
const UserContext = createContext<UserContextType | undefined>(undefined)
export function UserProvider({ children }: { children: ReactNode }) {
const [user, setUser] = useState<User | null>(null)
return (
<UserContext.Provider value={{ user, setUser }}>
{children}
</UserContext.Provider>
)
}
export function useUser() {
const context = useContext(UserContext)
if (!context) throw new Error('useUser must be within UserProvider')
return context
}import { create } from 'zustand'
interface CounterStore {
count: number
increment: () => void
decrement: () => void
reset: () => void
}
export const useCounterStore = create<CounterStore>((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
decrement: () => set((state) => ({ count: state.count - 1 })),
reset: () => set({ count: 0 })
}))
// Usage
function Counter() {
const { count, increment } = useCounterStore()
return <button onClick={increment}>{count}</button>
}---
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
// Query (GET)
function Users() {
const { data, isLoading, error } = useQuery({
queryKey: ['users'],
queryFn: fetchUsers,
staleTime: 5 * 60 * 1000 // 5 minutes
})
if (isLoading) return <LoadingSpinner />
if (error) return <ErrorMessage error={error} />
return <UserList users={data} />
}
// Mutation (POST, PUT, DELETE)
function CreateUser() {
const queryClient = useQueryClient()
const mutation = useMutation({
mutationFn: createUser,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['users'] })
}
})
return (
<button onClick={() => mutation.mutate({ name: 'John' })}>
Create User
</button>
)
}// app/users/page.tsx
// Server Component - fetches on server
export default async function UsersPage() {
const users = await fetchUsers() // Runs on server
return <UserList users={users} />
}
// Client Component - for interactivity
'use client'
export function UserList({ users }: { users: User[] }) {
const [selected, setSelected] = useState<string | null>(null)
return (
<div>
{users.map(user => (
<UserCard
key={user.id}
user={user}
onClick={() => setSelected(user.id)}
/>
))}
</div>
)
}---
import { useForm } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import { z } from 'zod'Team Avatar: a universal agent orchestrator for Claude Code, Codex, and Cursor. Nine Avatar characters, 58 engineering skills. pstack with Avatar characters on top.
Zuko's Agni Kai for bakeoffs. The formal firebending duel, where competing implementations fight under the same rules and a judge…
Aang showing a new friend around the team. Explains Team Avatar to a user, the roster and who owns what, how to invoke a skill on…
Aang's operating mode for Team Avatar, principal-level engineering where each task goes to the character who owns that…
Aang choosing which bender takes which fight. Configures which model each Team Avatar character runs on, the default reasoning…
Sokka's battle map, the decision trail he keeps so anyone can see how the campaign was won. Use for show-me-your-work,…
Appa's morning departure for picking up paused or handed-off work. The team breaks camp, reads the map they left, and flies on…