Ordinary-claude-skills rsc-data-optimizer
install
source · Clone the upstream repo
git clone https://github.com/Microck/ordinary-claude-skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/Microck/ordinary-claude-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills_categorized/arts-crafts/rsc-data-optimizer" ~/.claude/skills/microck-ordinary-claude-skills-rsc-data-optimizer-38b2ea && rm -rf "$T"
manifest:
skills_categorized/arts-crafts/rsc-data-optimizer/SKILL.mdsource content
RSC Data Fetching Optimizer
Optimize slow client-side data fetching to instant server-side rendering.
Quick Diagnosis
Search for these anti-patterns in the codebase:
# Find client-side fetching patterns rg -n "useEffect.*fetch|useState.*loading|useStore\(\)" --type tsx rg -n '"use client"' app/ --type tsx
Red flags:
+"use client"
+useEffect
= slow initial loadfetch()
foruseState(true)
= user sees spinnerisLoading
oruseStore()
for initial page data = waterfall fetchinguseContext
3-Step Conversion Workflow
Step 1: Identify Data Requirements
Determine what data the page needs on initial render:
- Static/rarely-changing data → Server Component (SSR)
- User-interactive data (filters, search) → Client Component
Step 2: Extract Interactive Sections
Move sections with
useInView, useState, onClick to separate Client Components:
// components/data-section.tsx "use client"; interface DataSectionProps { data: Item[]; // Receive data as props } export function DataSection({ data }: DataSectionProps) { const [ref, inView] = useInView(); // Client-side animation OK return <div ref={ref}>...</div>; }
Step 3: Convert Page to Server Component
// app/page.tsx - NO "use client" import { getData } from "@/lib/actions/data"; import { DataSection } from "@/components/data-section"; export default async function Page() { const data = await getData(); // Fetch on server return <DataSection data={data} />; }
Type Adapter Pattern
When DB types differ from frontend types:
import type { Item as DBItem } from "@/lib/database.types"; import type { Item } from "@/lib/types"; function adaptDBToFrontend(db: DBItem): Item { return { id: db.id, name: db.name, description: db.description ?? "", createdAt: new Date(db.created_at), }; } export default async function Page() { const dbItems = await getItems(); const items = dbItems.map(adaptDBToFrontend); return <ItemList items={items} />; }
When to Keep Client-Side
Keep
"use client" when:
- Real-time subscriptions (Supabase realtime)
- User-triggered fetching (search, filters, pagination)
- Data depends on client state (auth token, localStorage)
- Infinite scroll / load more patterns
Advanced Patterns
See references/patterns.md for:
- Parallel data fetching
- Streaming with Suspense
- Error boundaries
- Caching strategies
- Hybrid SSR + client patterns