React Server Components patterns including streaming, data fetching, client/server component composition, and performance optimization.
Implements React Server Components with streaming, data fetching, and optimal server-client composition.
npx claudepluginhub a5c-ai/babysitterThis skill is limited to using the following tools:
README.mdExpert assistance for implementing React Server Components with proper patterns and composition strategies.
Invoke this skill when you need to:
| Parameter | Type | Required | Description |
|---|---|---|---|
| componentType | string | Yes | server, client, shared |
| dataFetching | boolean | No | Component fetches data |
| interactivity | array | No | Required client interactions |
| streaming | boolean | No | Enable streaming |
{
"componentType": "server",
"dataFetching": true,
"streaming": true,
"childComponents": [
{ "name": "InteractiveChart", "type": "client" }
]
}
// app/users/page.tsx - Server Component by default
import { db } from '@/lib/db';
import { UserCard } from './user-card';
async function getUsers() {
return db.user.findMany({
include: { posts: true },
});
}
export default async function UsersPage() {
const users = await getUsers();
return (
<div className="grid gap-4">
<h1>Users</h1>
{users.map((user) => (
<UserCard key={user.id} user={user} />
))}
</div>
);
}
// components/interactive-counter.tsx
'use client';
import { useState } from 'react';
export function InteractiveCounter({ initialCount }: { initialCount: number }) {
const [count, setCount] = useState(initialCount);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(c => c + 1)}>
Increment
</button>
</div>
);
}
// app/dashboard/page.tsx - Server Component
import { Suspense } from 'react';
import { db } from '@/lib/db';
import { InteractiveChart } from '@/components/interactive-chart';
import { ChartSkeleton } from '@/components/skeletons';
async function getAnalytics() {
return db.analytics.findMany({
orderBy: { date: 'desc' },
take: 30,
});
}
export default async function Dashboard() {
const analytics = await getAnalytics();
return (
<div>
<h1>Dashboard</h1>
{/* Pass server data to client component */}
<Suspense fallback={<ChartSkeleton />}>
<InteractiveChart data={analytics} />
</Suspense>
</div>
);
}
// components/interactive-chart.tsx - Client Component
'use client';
import { useState } from 'react';
import { LineChart } from 'recharts';
interface ChartProps {
data: AnalyticsData[];
}
export function InteractiveChart({ data }: ChartProps) {
const [timeRange, setTimeRange] = useState('7d');
const filteredData = filterByTimeRange(data, timeRange);
return (
<div>
<select
value={timeRange}
onChange={(e) => setTimeRange(e.target.value)}
>
<option value="7d">Last 7 days</option>
<option value="30d">Last 30 days</option>
</select>
<LineChart data={filteredData} />
</div>
);
}
// app/page.tsx
import { Suspense } from 'react';
import { SlowComponent, FastComponent } from '@/components';
export default function Page() {
return (
<div>
{/* Fast content renders immediately */}
<FastComponent />
{/* Slow content streams in */}
<Suspense fallback={<p>Loading slow content...</p>}>
<SlowComponent />
</Suspense>
</div>
);
}
// components/slow-component.tsx
async function getSlowData() {
await new Promise((resolve) => setTimeout(resolve, 2000));
return { data: 'Slow data loaded' };
}
export async function SlowComponent() {
const data = await getSlowData();
return <div>{data.data}</div>;
}
// app/actions.ts
'use server';
import { revalidatePath } from 'next/cache';
import { db } from '@/lib/db';
export async function createUser(formData: FormData) {
const name = formData.get('name') as string;
const email = formData.get('email') as string;
await db.user.create({
data: { name, email },
});
revalidatePath('/users');
}
export async function updateUser(id: string, formData: FormData) {
const name = formData.get('name') as string;
await db.user.update({
where: { id },
data: { name },
});
revalidatePath(`/users/${id}`);
}
// components/user-form.tsx
'use client';
import { useFormStatus } from 'react-dom';
import { createUser } from '@/app/actions';
function SubmitButton() {
const { pending } = useFormStatus();
return (
<button type="submit" disabled={pending}>
{pending ? 'Creating...' : 'Create User'}
</button>
);
}
export function UserForm() {
return (
<form action={createUser}>
<input name="name" placeholder="Name" required />
<input name="email" type="email" placeholder="Email" required />
<SubmitButton />
</form>
);
}
// Pattern: Server Component as children
// app/page.tsx
import { ClientWrapper } from '@/components/client-wrapper';
import { ServerContent } from '@/components/server-content';
export default function Page() {
return (
<ClientWrapper>
<ServerContent />
</ClientWrapper>
);
}
// components/client-wrapper.tsx
'use client';
export function ClientWrapper({ children }: { children: React.ReactNode }) {
const [isOpen, setIsOpen] = useState(true);
return (
<div>
<button onClick={() => setIsOpen(!isOpen)}>Toggle</button>
{isOpen && children}
</div>
);
}
Activates when the user asks about AI prompts, needs prompt templates, wants to search for prompts, or mentions prompts.chat. Use for discovering, retrieving, and improving prompts.
Search, retrieve, and install Agent Skills from the prompts.chat registry using MCP tools. Use when the user asks to find skills, browse skill catalogs, install a skill for Claude, or extend Claude's capabilities with reusable AI agent components.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.