Opik Frontend Patterns
comet-ml/opik
Sets the conventions for the Opik React frontend: TanStack Query for data, Zustand for shared state, one-way layer imports and a fix for Google Translate crashes.
Modern React 19+ patterns with TypeScript including function components, hooks, state management, TanStack Query integration, form handling with Zod, error boundaries, and performance optimization.
$ npx skills add MadAppGang/claude-code --skill react-typescript -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install MadAppGang/claude-code react-typescript --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/MadAppGang/claude-code.git skills-src && mkdir -p .claude/skills && cp -r skills-src/plugins/dev/skills/frontend/react-typescript .claude/skills/react-typescript && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "react-typescript" agent skill from https://github.com/MadAppGang/claude-code/tree/main/plugins/dev/skills/frontend/react-typescript into .claude/skills/react-typescript/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "react-typescript", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/MadAppGang/claude-code/tree/main/plugins/dev/skills/frontend/react-typescriptType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add MadAppGang/claude-code --skill react-typescript -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install MadAppGang/claude-code react-typescript --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/MadAppGang/claude-code.git skills-src && mkdir -p .agents/skills && cp -r skills-src/plugins/dev/skills/frontend/react-typescript .agents/skills/react-typescript && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "react-typescript" agent skill from https://github.com/MadAppGang/claude-code/tree/main/plugins/dev/skills/frontend/react-typescript into .agents/skills/react-typescript/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "react-typescript", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add MadAppGang/claude-code --skill react-typescript -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install MadAppGang/claude-code react-typescript --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/MadAppGang/claude-code.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/plugins/dev/skills/frontend/react-typescript .cursor/skills/react-typescript && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "react-typescript" agent skill from https://github.com/MadAppGang/claude-code/tree/main/plugins/dev/skills/frontend/react-typescript into .cursor/skills/react-typescript/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "react-typescript", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/MadAppGang/claude-code.git --path plugins/dev/skills/frontend/react-typescript--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add MadAppGang/claude-code --skill react-typescript -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install MadAppGang/claude-code react-typescript --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/MadAppGang/claude-code.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/plugins/dev/skills/frontend/react-typescript .gemini/skills/react-typescript && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "react-typescript" agent skill from https://github.com/MadAppGang/claude-code/tree/main/plugins/dev/skills/frontend/react-typescript into .gemini/skills/react-typescript/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "react-typescript", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install MadAppGang/claude-code react-typescriptInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add MadAppGang/claude-code --skill react-typescript -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/MadAppGang/claude-code.git skills-src && mkdir -p .github/skills && cp -r skills-src/plugins/dev/skills/frontend/react-typescript .github/skills/react-typescript && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "react-typescript" agent skill from https://github.com/MadAppGang/claude-code/tree/main/plugins/dev/skills/frontend/react-typescript into .github/skills/react-typescript/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "react-typescript", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add MadAppGang/claude-code --skill react-typescript -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install MadAppGang/claude-code react-typescript --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/MadAppGang/claude-code.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/plugins/dev/skills/frontend/react-typescript .opencode/skills/react-typescript && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "react-typescript" agent skill from https://github.com/MadAppGang/claude-code/tree/main/plugins/dev/skills/frontend/react-typescript into .opencode/skills/react-typescript/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "react-typescript", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
react-typescriptModern React 19+ patterns with TypeScript including function components, hooks, state management, TanStack Query integration, form handling with Zod, error boundaries, and performance optimization.
React Typescript is an agent skill from MadAppGang/claude-code. Modern React 19+ patterns with TypeScript including function components, hooks, state management, TanStack Query integration, form handling with Zod, error boundaries, and performance optimization. Use when building React applications, implementing components, or setting up state management.
Its SKILL.md is about 4.1k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Frontend & Design, covering Forms and validation, State management and Error handling. It works with React, TypeScript, TanStack and Zod. The repository describes itself as: claude code plugins marketplace. The licence is MIT.
Read from SKILL.md and the folder at commit 6097ad4. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are typescript).
From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names these keys or tokens, usually read from environment variables:
API_KEYVITE_SECRET_API_KEYSECRET_API_KEYFrom names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
React Typescript loads about 4.1k tokens when it runs. Until then it costs about 77 tokens; SKILL.md has 402 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from MadAppGang/claude-code at commit 6097ad4, republished under its MIT licence (© MadAppGang). 402 words, ~4,119 tokens.
.claude/skills/react-typescript/SKILL.md (or your agent's skills folder).Modern React 19+ patterns with TypeScript for building robust frontend applications.
interface UserCardProps {
user: User;
onSelect?: (user: User) => void;
className?: string;
}
export function UserCard({ user, onSelect, className }: UserCardProps) {
return (
<div className={className} onClick={() => onSelect?.(user)}>
<h3>{user.name}</h3>
<p>{user.email}</p>
</div>
);
}interface ContainerProps {
children: React.ReactNode;
title?: string;
}
export function Container({ children, title }: ContainerProps) {
return (
<div className="container">
{title && <h2>{title}</h2>}
{children}
</div>
);
}interface ListProps<T> {
items: T[];
renderItem: (item: T) => React.ReactNode;
keyExtractor: (item: T) => string;
}
export function List<T>({ items, renderItem, keyExtractor }: ListProps<T>) {
return (
<ul>
{items.map(item => (
<li key={keyExtractor(item)}>{renderItem(item)}</li>
))}
</ul>
);
}interface UseCounterOptions {
initialValue?: number;
min?: number;
max?: number;
}
export function useCounter({ initialValue = 0, min, max }: UseCounterOptions = {}) {
const [count, setCount] = useState(initialValue);
const increment = useCallback(() => {
setCount(c => (max !== undefined ? Math.min(c + 1, max) : c + 1));
}, [max]);
const decrement = useCallback(() => {
setCount(c => (min !== undefined ? Math.max(c - 1, min) : c - 1));
}, [min]);
const reset = useCallback(() => setCount(initialValue), [initialValue]);
return { count, increment, decrement, reset };
}interface UseFetchResult<T> {
data: T | null;
loading: boolean;
error: Error | null;
refetch: () => Promise<void>;
}
export function useFetch<T>(url: string): UseFetchResult<T> {
const [data, setData] = useState<T | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<Error | null>(null);
const fetchData = useCallback(async () => {
setLoading(true);
setError(null);
try {
const response = await fetch(url);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const result = await response.json();
setData(result);
} catch (e) {
setError(e instanceof Error ? e : new Error('Unknown error'));
} finally {
setLoading(false);
}
}, [url]);
useEffect(() => {
fetchData();
}, [fetchData]);
return { data, loading, error, refetch: fetchData };
}interface AuthContextValue {
user: User | null;
login: (credentials: Credentials) => Promise<void>;
logout: () => void;
isAuthenticated: boolean;
}
const AuthContext = createContext<AuthContextValue | null>(null);
export function AuthProvider({ children }: { children: React.ReactNode }) {
const [user, setUser] = useState<User | null>(null);
const login = async (credentials: Credentials) => {
const user = await authService.login(credentials);
setUser(user);
};
const logout = () => {
authService.logout();
setUser(null);
};
return (
<AuthContext.Provider
value={{ user, login, logout, isAuthenticated: !!user }}
>
{children}
</AuthContext.Provider>
);
}
export function useAuth() {
const context = useContext(AuthContext);
if (!context) throw new Error('useAuth must be used within AuthProvider');
return context;
}interface StoreState {
count: number;
users: User[];
increment: () => void;
setUsers: (users: User[]) => void;
}
export const useStore = create<StoreState>((set) => ({
count: 0,
users: [],
increment: () => set((state) => ({ count: state.count + 1 })),
setUsers: (users) => set({ users }),
}));export function useUser(userId: string) {
return useQuery({
queryKey: ['user', userId],
queryFn: () => api.getUser(userId),
staleTime: 5 * 60 * 1000, // 5 minutes
});
}
// Usage
function UserProfile({ userId }: { userId: string }) {
const { data: user, isLoading, error } = useUser(userId);
if (isLoading) return <Spinner />;
if (error) return <ErrorMessage error={error} />;
if (!user) return <NotFound />;
return <UserCard user={user} />;
}export function useUpdateUser() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (data: UpdateUserInput) => api.updateUser(data),
onMutate: async (newData) => {
await queryClient.cancelQueries({ queryKey: ['user', newData.id] });
const previous = queryClient.getQueryData(['user', newData.id]);
queryClient.setQueryData(['user', newData.id], (old: User) => ({
...old,
...newData,
}));
return { previous };
},
onError: (err, newData, context) => {
queryClient.setQueryData(['user', newData.id], context?.previous);
},
onSettled: (data, error, variables) => {
queryClient.invalidateQueries({ queryKey: ['user', variables.id] });
},
});
}const userSchema = z.object({
name: z.string().min(2, 'Name must be at least 2 characters'),
email: z.string().email('Invalid email'),
age: z.number().min(18, 'Must be 18 or older'),
});
type UserFormData = z.infer<typeof userSchema>;
export function UserForm({ onSubmit }: { onSubmit: (data: UserFormData) => void }) {
const {
register,
handleSubmit,
formState: { errors, isSubmitting },
} = useForm<UserFormData>({
resolver: zodResolver(userSchema),
});
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register('name')} placeholder="Name" />
{errors.name && <span>{errors.name.message}</span>}
<input {...register('email')} type="email" placeholder="Email" />
{errors.email && <span>{errors.email.message}</span>}
<input {...register('age', { valueAsNumber: true })} type="number" />
{errors.age && <span>{errors.age.message}</span>}
<button type="submit" disabled={isSubmitting}>
{isSubmitting ? 'Saving...' : 'Save'}
</button>
</form>
);
}interface ErrorBoundaryProps {
children: React.ReactNode;
fallback?: React.ReactNode;
}
interface ErrorBoundaryState {
hasError: boolean;
error: Error | null;
}
export class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
state: ErrorBoundaryState = { hasError: false, error: null };
static getDerivedStateFromError(error: Error): ErrorBoundaryState {
return { hasError: true, error };
}
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
console.error('ErrorBoundary caught:', error, errorInfo);
}
render() {
if (this.state.hasError) {
return this.props.fallback ?? <DefaultErrorFallback error={this.state.error} />;
}
return this.props.children;
}
}// Memoize expensive computations
const sortedUsers = useMemo(() => {
return users.sort((a, b) => a.name.localeCompare(b.name));
}, [users]);
// Memoize callbacks
const handleClick = useCallback((id: string) => {
setSelectedId(id);
}, []);
// Memoize components
const MemoizedUserCard = memo(UserCard);// Lazy load components
const AdminPanel = lazy(() => import('./AdminPanel'));
function App() {
return (
<Suspense fallback={<Spinner />}>
<AdminPanel />
</Suspense>
);
}src/
├── components/
│ ├── common/ # Shared components
│ │ ├── Button/
│ │ │ ├── Button.tsx
│ │ │ ├── Button.test.tsx
│ │ │ └── index.ts
│ │ └── Input/
│ ├── features/ # Feature components
│ │ ├── auth/
│ │ └── users/
│ └── layout/ # Layout components
├── hooks/ # Custom hooks
├── stores/ # State management
├── services/ # API services
├── types/ # TypeScript types
├── utils/ # Utilities
└── App.tsxinterface ApiResponse<T> {
data: T;
message: string;
success: boolean;
}
interface PaginatedResponse<T> {
items: T[];
total: number;
page: number;
pageSize: number;
}type ClickHandler = React.MouseEventHandler<HTMLButtonElement>;
type ChangeHandler = React.ChangeEventHandler<HTMLInputElement>;
type SubmitHandler = React.FormEventHandler<HTMLFormElement>;React + TypeScript patterns for modern frontend development
The React Compiler automatically optimizes components for performance. Write code that works well with it:
Best Practices:
"use no memo" while refactoringExample - Pure Component:
// ✅ Compiler-friendly - pure function
function UserCard({ user }: { user: User }) {
const displayName = `${user.firstName} ${user.lastName}`
const isVIP = user.points > 1000
return (
<div>
<h2>{displayName}</h2>
{isVIP && <Badge>VIP</Badge>}
</div>
)
}
// ❌ Avoid - unnecessary effects
function UserCard({ user }: { user: User }) {
const [displayName, setDisplayName] = useState('')
useEffect(() => {
setDisplayName(`${user.firstName} ${user.lastName}`)
}, [user])
return <div><h2>{displayName}</h2></div>
}Verification:
Opt-Out When Needed:
'use no memo'
// Component code that can't be optimized yet
function ProblematicComponent() {
// ... code with compiler issues
}For SPA mutations, choose one approach per feature:
<form action={fn}>, useActionState, useOptimisticuseMutationDon't duplicate logic between both approaches.
Best for:
Basic Action:
async function createTodoAction(formData: FormData) {
const text = formData.get('text') as string
// Validation
if (!text || text.length < 3) {
return { error: 'Text must be at least 3 characters' }
}
// API call
await api.post('/todos', { text })
return { success: true }
}
// Component
function TodoForm() {
return (
<form action={createTodoAction}>
<input name="text" required />
<button type="submit">Add Todo</button>
</form>
)
}With State (useActionState):
import { useActionState } from 'react'
function TodoForm() {
const [state, formAction, isPending] = useActionState(
createTodoAction,
{ error: null, success: false }
)
return (
<form action={formAction}>
{state.error && <ErrorMessage>{state.error}</ErrorMessage>}
<input name="text" required />
<button type="submit" disabled={isPending}>
{isPending ? 'Adding...' : 'Add Todo'}
</button>
</form>
)
}With Optimistic Updates (useOptimistic):
import { useOptimistic } from 'react'
function TaskList({ initialTodos }: { initialTodos: Todo[] }) {
const [optimisticTodos, addOptimisticTodo] = useOptimistic(
initialTodos,
(state, newTodo: string) => [
...state,
{ id: `temp-${Date.now()}`, text: newTodo, completed: false }
]
)
async function handleSubmit(formData: FormData) {
const text = formData.get('text') as string
addOptimisticTodo(text)
await createTodoAction(formData)
}
return (
<>
<ul>
{optimisticTodos.map(todo => (
<li key={todo.id} style={{ opacity: todo.id.startsWith('temp-') ? 0.5 : 1 }}>
{todo.text}
</li>
))}
</ul>
<form action={handleSubmit}>
<input name="text" required />
<button type="submit">Add</button>
</form>
</>
)
}The use hook unwraps Promises and Context, enabling new patterns.
With Promises:
import { use, Suspense } from 'react'
function UserProfile({ userPromise }: { userPromise: Promise<User> }) {
const user = use(userPromise)
return <div>{user.name}</div>
}
// Usage
function App() {
const userPromise = fetchUser(1)
return (
<Suspense fallback={<Spinner />}>
<UserProfile userPromise={userPromise} />
</Suspense>
)
}With Context:
import { use, createContext } from 'react'
const ThemeContext = createContext<string>('light')
function Button() {
const theme = use(ThemeContext)
return <button className={theme}>Click me</button>
}When to Use:
use shines when you already have a Promise from a parent componentCompound Components:
// ✅ Good - composable, flexible
<Card>
<Card.Header>
<Card.Title>Dashboard</Card.Title>
</Card.Header>
<Card.Content>
{/* content */}
</Card.Content>
</Card>
// Implementation
function Card({ children }: { children: React.ReactNode }) {
return <div className="card">{children}</div>
}
Card.Header = function CardHeader({ children }: { children: React.ReactNode }) {
return <header className="card-header">{children}</header>
}
Card.Title = function CardTitle({ children }: { children: React.ReactNode }) {
return <h2 className="card-title">{children}</h2>
}
Card.Content = function CardContent({ children }: { children: React.ReactNode }) {
return <div className="card-content">{children}</div>
}| Scenario | Recommendation |
|---|---|
| Form submission with validation | React Actions |
| Button click mutation | TanStack Query |
| Needs optimistic updates + rollback | TanStack Query |
| Integrates with existing cache | TanStack Query |
| SSR/RSC application | React Actions |
| SPA with complex data flow | TanStack Query |
| Simple CRUD with forms | React Actions |
Rule of Thumb: For SPAs with TanStack Query already in use, prefer Query mutations for consistency. Only use Actions for form-heavy features where the form-centric API is beneficial.
XSS Prevention:
// ❌ Dangerous
<div dangerouslySetInnerHTML={{ __html: userInput }} />
// ✅ Sanitize first
import DOMPurify from 'dompurify'
<div dangerouslySetInnerHTML={{
__html: DOMPurify.sanitize(userInput)
}} />
// ✅ Best - avoid dangerouslySetInnerHTML
<div>{userInput}</div>Environment Variables:
// ❌ Exposes secrets
const API_KEY = process.env.VITE_SECRET_API_KEY
// ✅ Separate public/private
// Public (can be in client): VITE_PUBLIC_API_URL
// Private (server only): SECRET_API_KEY© MadAppGang, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in plugins/dev/skills/frontend/react-typescript of MadAppGang/claude-code.
Open the folder on GitHubat commit 6097ad4
React Typescript next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| React Typescript this skillMadAppGang/claude-code | 284 | — | ~4.1k | Automated safety check: Pass | MIT | |
| Opik Frontend Patternscomet-ml/opik | 22k | — | ~1.1k | Automated safety check: Pass | Apache-2.0 | |
| Buzzformbuildnbuzz/buzzform | 101 | — | ~1.5k | Automated safety check: Pass | MIT | |
| React ExpertJeffallan/claude-skills | 12k | — | ~1.4k | Automated safety check: Pass | MIT | |
| React Idiomsirahardianto/awesome-agv | 157 | — | ~3.8k | Automated safety check: Pass | MIT | |
| Frontend Developmentavibebuilder/claude-prime | 120 | — | ~1.3k | Automated safety check: Pass | MIT |
comet-ml/opik
Sets the conventions for the Opik React frontend: TanStack Query for data, Zustand for shared state, one-way layer imports and a fix for Google Translate crashes.
buildnbuzz/buzzform
A skill your agent uses when working with BuzzForm schema-driven forms, @buildnbuzz/form-core, @buildnbuzz/form-react, or any related APIs like defineSchema, InferType, FormProvider, useDataField…
Jeffallan/claude-skills
Builds React 19 components in TypeScript with Server Components, useActionState forms, custom hooks and state libraries, checked with tsc and React Testing Library.
irahardianto/awesome-agv
React 19+ patterns: custom hooks, Suspense boundaries, state management, component composition, and web performance.
avibebuilder/claude-prime
A skill your agent uses for ANY work involving React, Next.js, TypeScript, or Tailwind in the browser layer.
softspark/ai-toolkit
TypeScript types: generics, discriminated unions, Zod, satisfies, branded types.
MadAppGang/claude-code
Analyzes API documentation from OpenAPI specs to provide TypeScript interfaces, request/response formats, and implementation guidance.
MadAppGang/claude-code
Content brief template and creation methodology for SEO-optimized content.
MadAppGang/claude-code
A skill your agent uses when detecting project technology stack from files/configs/directory structure, auto-loading framework-specific skills, or analyzing multi-stack fullstack projects (e.g…
MadAppGang/claude-code
On-page SEO optimization techniques including keyword density, meta tags, heading structure, and readability.
MadAppGang/claude-code
Techniques for expanding seed keywords and clustering by topic and intent.
MadAppGang/claude-code
SERP analysis techniques for intent classification, feature identification, and competitive intelligence.
Works with
Categories
Modern React 19+ patterns with TypeScript including function components, hooks, state management, TanStack Query integration, form handling with Zod, error boundaries, and performance optimization. React Typescript is an agent skill from MadAppGang/claude-code. Modern React 19+ patterns with TypeScript including function components, hooks, state management, TanStack Query integration, form handling with Zod, error boundaries, and performance optimization.
React Typescript fits situations like: building React applications; implementing components; setting up state management.
Run `npx skills add MadAppGang/claude-code --skill react-typescript -a claude-code`. Or copy the skill folder (plugins/dev/skills/frontend/react-typescript in MadAppGang/claude-code) into .claude/skills/react-typescript in your project. Claude Code loads it when a task matches its description.
Run `npx skills add MadAppGang/claude-code --skill react-typescript -a codex`. Or copy the skill folder (plugins/dev/skills/frontend/react-typescript in MadAppGang/claude-code) into .agents/skills/react-typescript in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add MadAppGang/claude-code --skill react-typescript -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/react-typescript, .gemini/skills/react-typescript, .github/skills/react-typescript and .opencode/skills/react-typescript in your project.
Going by SKILL.md and its folder, React Typescript needs credentials named API_KEY, VITE_SECRET_API_KEY and SECRET_API_KEY.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
React Typescript is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 4.1k tokens (SKILL.md is roughly 16k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with React Typescript: Opik Frontend Patterns (comet-ml/opik, 22k stars), Buzzform (buildnbuzz/buzzform, 101 stars), React Expert (Jeffallan/claude-skills, 12k stars) and React Idioms (irahardianto/awesome-agv, 157 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
MadAppGang (a GitHub organization) maintains it in MadAppGang/claude-code, which has 284 GitHub stars. The repository holds 69 skills in this directory. The repository was last updated on March 15, 2026.
Source: MadAppGang/claude-code on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.