agentleFS
joaoguirunasjoaoguirunas/team-os/.claude/skills/nextjs-react-best-practices/SKILL.md

nextjs-react-best-practices

Skill6 starsChanged 26 days agoMITView on GitHub

Melhores práticas de performance para React e Next.js (App Router) — eliminar waterfalls, reduzir bundle, otimizar Server Components, data fetching, re-renders e Core Web Vitals. Use ao escrever ou revisar componentes React, páginas Next.js, data fetching (server ou client), ou ao investigar bundle size, hydration e lentidão de render.

1 other project uses a version of this.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

5 rules. About 0 are common, 1 is distinctive, and 4 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈1

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 4

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    1.2 — Check cheap conditions before awaiting: Don't pay for a fetch you might discard.

    line 28
  2. Very specific:

    1.3 — Move await into the branch that needs it: If only one code path consumes the promise, await it there — start the promise early, …

    line 40
  3. Very specific:

    1.5 — Pass promises down, await in the leaf: Start fetches high in the tree, pass the promise as prop, resolve with use() or await inside …

    line 58
  4. Very specific:

    3.1 — Authenticate Server Actions like API routes: Every "use server" function is a public endpoint.

    line 81
  5. Very specific:

    Use Map/Set for repeated lookups instead of array.find/includes in loops (O(1) vs O(n)).

    line 141

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Next.js + React Best Practices

Skill de performance para código React/Next.js, destilada das regras da engenharia da Vercel (70 regras em 8 categorias, priorizadas por impacto). Usada pelos implementers frontend e fullstack — dev-dev-alpha, dev-dev-gamma, sites-dev-alpha, sites-dev-beta, sites-dev-gamma — e pelos reviewers dev-qa / sites-qa em code review. Aplique na escrita de componentes novos, em refactors e em auditorias de bundle/render.

1. Eliminating Waterfalls (CRITICAL)

1.1 — Parallelize independent async operations with Promise.all().

// ❌ Sequential — 3 round trips
const user = await getUser(id)
const posts = await getPosts(id)
const stats = await getStats(id)

// ✅ Parallel — 1 round trip window
const [user, posts, stats] = await Promise.all([
  getUser(id), getPosts(id), getStats(id),
])

1.2 — Check cheap conditions before awaiting. Don't pay for a fetch you might discard.

// ❌ fetch always runs
const data = await fetchExpensive()
if (!flag.enabled) return null

// ✅ bail out first
if (!flag.enabled) return null
const data = await fetchExpensive()

1.3 — Move await into the branch that needs it. If only one code path consumes the promise, await it there — start the promise early, await late.

1.4 — Stream with Suspense instead of blocking the whole page. Fetch fast data in the page; wrap slow sections in <Suspense fallback={...}> and let them stream in.

export default async function Page() {
  const header = await getHeader() // fast
  return (
    <>
      <Header data={header} />
      <Suspense fallback={<Skeleton />}>
        <SlowSection /> {/* awaits inside, streams later */}
      </Suspense>
    </>
  )
}

1.5 — Pass promises down, await in the leaf. Start fetches high in the tree, pass the promise as prop, resolve with use() or await inside the Suspense boundary.

2. Bundle Size (CRITICAL)

2.1 — Import directly, never through barrel files.

// ❌ pulls the whole library through the barrel
import { Button } from '@/components'
// ✅ pulls one module
import { Button } from '@/components/button'

2.2 — next/dynamic for heavy, conditionally-shown components (charts, editors, modals, maps): const Chart = dynamic(() => import('./chart'), { ssr: false }).

2.3 — Load third-party scripts after hydration with next/script (strategy="lazyOnload" or afterInteractive). Never a raw <script> blocking render.

2.4 — Defer modules until the feature activates — dynamic import() inside the event handler that needs it (e.g., load the export-to-PDF lib on click).

2.5 — Keep client boundaries small. "use client" marks the top of a client subtree — everything it imports ships to the browser. Push "use client" down to the leaf interactive components; keep pages and layouts as Server Components.

3. Server-Side Performance (HIGH)

3.1 — Authenticate Server Actions like API routes. Every "use server" function is a public endpoint. Validate session + input inside the action, never only in the calling UI.

3.2 — React.cache() for per-request deduplication of repeated reads (e.g., getCurrentUser() called by layout + page + components).

export const getCurrentUser = cache(async () => {
  const session = await auth()
  return session ? db.user.findUnique({ where: { id: session.userId } }) : null
})

3.3 — Cross-request caching: unstable_cache/"use cache" or an LRU for data shared between users; always define revalidation (revalidateTag/revalidatePath) at write time.

3.4 — after() for non-blocking work — logging, analytics, notifications run after the response is sent.

3.5 — Never fetch your own API routes from Server Components. Call the data layer (DB/service) directly; the HTTP hop to yourself is pure overhead.

4. Client-Side Data Fetching (MEDIUM-HIGH)

4.1 — Use SWR (or React Query) instead of useEffect + fetch. Automatic dedupe, cache, revalidation, race-condition safety.

// ❌ manual effect fetch: no dedupe, races, no cache
useEffect(() => { fetch('/api/user').then(...) }, [])
// ✅
const { data, error, isLoading } = useSWR('/api/user', fetcher)

4.2 — Deduplicate global listeners — one resize/scroll listener shared via a small store or context, not one per component instance.

4.3 — Passive listeners for scroll/touch: addEventListener('scroll', fn, { passive: true }).

4.4 — Version localStorage payloads ({ v: 2, data }) and handle both parse failure and stale versions on read.

5. Re-render Optimization (MEDIUM)

5.1 — Never define components inside components. The inner component remounts on every render, losing state and DOM.

5.2 — Hoist non-primitive default props (const EMPTY: Item[] = []) outside the component — inline []/{}/() => {} defeats memoization.

5.3 — Extract expensive subtrees into memo() components and pass primitive props; prefer restructuring (move state down, pass children) over sprinkling useMemo everywhere.

5.4 — Effects should depend on primitives: useEffect(fn, [user.id]), not [user].

5.5 — startTransition for non-urgent updates (filtering large lists, tab switches) so typing stays responsive.

6. Rendering Performance (MEDIUM)

6.1 — content-visibility: auto for long lists, or virtualize (react-window/virtua) above ~200 rows.

6.2 — Prefer ternaries over && for conditional JSX — {count && <X/>} renders a literal 0.

6.3 — Extract static JSX outside the component so it's created once.

6.4 — Animate a wrapper <div> with CSS transforms, not SVG internals; keep animations on transform/opacity (compositor-only).

6.5 — Expected hydration mismatches (timestamps, locale) → suppressHydrationWarning on that node, or render client-only via useEffect-gated state.

7. JavaScript Micro-Performance (LOW-MEDIUM)

  • Use Map/Set for repeated lookups instead of array.find/includes in loops (O(1) vs O(n)).
  • Combine chained filter().map() into one pass when the list is large and hot.
  • Batch DOM writes; toggle classes instead of many inline style mutations.
  • requestIdleCallback for non-critical deferred work.

8. Next.js App Router Essentials

  • generateMetadata for SEO; next/image always (never raw <img> for content images); next/font for zero-layout-shift fonts.
  • Route handlers e páginas dinâmicas: declare export const dynamic/revalidate explicitly quando o default implícito não for óbvio.
  • loading.tsx + error.tsx em toda rota com fetch — streaming UX e error boundary por segmento.
  • Server Components por padrão; client components apenas onde há interatividade real.
  • Mutations via Server Actions com revalidatePath/revalidateTag — não faça mutate + router.refresh() manual quando a action resolve.

Checklist de review (QA)

  • Nenhum await sequencial de operações independentes
  • Nenhum barrel import de libs de UI/ícones
  • "use client" apenas em folhas interativas
  • Server Actions autenticam e validam input
  • Fetch client-side via SWR/React Query, não useEffect cru
  • Nenhum componente definido dentro de componente
  • Imagens via next/image, fontes via next/font
  • Listas longas virtualizadas ou com content-visibility

Adaptado de vercel-labs/agent-skills → react-best-practices (skills.sh) — 2026-08-26. Seção 8 (Next.js) baseada em conhecimento próprio: a skill next-best-practices foi descontinuada (vercel-labs/next-skills arquivado; docs agora embutidas no framework).

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.