Build ReactJS (Vite) web SPA features with React Router, Zustand client state, TanStack Query server state, Tailwind CSS styling, Framer Motion animations, and ApexCharts dashboards. Use this skill whenever someone asks to build a web page, create a Vite component, add a web dashboard, build a web SPA feature, or says things like "build the web UI for X", "create a web page for Y", "add a dashboard chart", "set up Vite routing", "build the admin panel", or "create a web form". Also trigger when someone mentions Vite configuration, Tailwind component styling, Framer Motion page transitions, or ApexCharts integration.
How this skill is triggered — by the user, by Claude, or both
Slash command
/sdh:reactjs-devsonnetThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Build production-ready ReactJS web SPA features using Vite, React Router, TanStack Query, Zustand, Tailwind CSS, Framer Motion, and ApexCharts. All features consume the shared Rails API backend.
Build production-ready ReactJS web SPA features using Vite, React Router, TanStack Query, Zustand, Tailwind CSS, Framer Motion, and ApexCharts. All features consume the shared Rails API backend.
@rules/reactjs.md
Create TypeScript types in web/src/domain/ or web/src/types/:
// web/src/domain/order.ts
export interface Order {
id: string;
status: OrderStatus;
totalAmount: number;
items: OrderItem[];
createdAt: string;
}
export type OrderStatus = 'pending' | 'confirmed' | 'shipped' | 'delivered' | 'cancelled';
Create TanStack Query hooks in web/src/api/:
// web/src/api/orders.ts
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { apiClient } from './client';
import type { Order, CreateOrderPayload } from '../domain/order';
export function useOrders(params?: { status?: string; page?: number }) {
return useQuery({
queryKey: ['orders', params],
queryFn: () => apiClient.get<Order[]>('/api/v1/orders', { params }),
staleTime: 30_000,
});
}
export function useCreateOrder() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (payload: CreateOrderPayload) => apiClient.post('/api/v1/orders', payload),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['orders'] }),
});
}
Create page components in web/src/pages/:
<Suspense> boundaries.Add lazy-loaded routes in web/src/router/index.tsx:
const OrdersPage = lazy(() => import('../pages/Orders'));
// Add to router config with appropriate auth guards
Use Framer Motion for page transitions and micro-interactions:
import { motion, AnimatePresence } from 'framer-motion';
<AnimatePresence mode="wait">
<motion.div
key={pathname}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -20 }}
transition={{ duration: 0.2 }}
>
{children}
</motion.div>
</AnimatePresence>
Use ApexCharts for dashboard visualizations:
import Chart from 'react-apexcharts';
<Chart
type="area"
height={350}
options={{ chart: { id: 'revenue' }, xaxis: { categories: months } }}
series={[{ name: 'Revenue', data: revenueData }]}
/>
Use react-hook-form + zod for all forms:
const schema = z.object({ email: z.string().email(), name: z.string().min(1) });
type FormData = z.infer<typeof schema>;
const { register, handleSubmit, formState: { errors } } = useForm<FormData>({
resolver: zodResolver(schema),
});
getByRole > getByLabelText > getByText > getByTestId.any typesvite-bundle-visualizernpx claudepluginhub kaakati/sdh-claude-skills --plugin sdhCreates bite-sized, testable implementation plans from specs or requirements, with file structure and task decomposition. Activates before coding multi-step tasks.