RuleStack

Configs

Stacks

Compare

Diff

RuleStack

Configs

Stacks

Compare

Diff

Read API

RuleStack

Configs

Stacks

Compare

Diff

Read API

Configs/AGENTS.md/sickn33/agentic-awesome-skills

AGENTS.md

plugins/agentic-bundle-aas-web-app-builder/skills/react-best-practices/AGENTS.md
AGENTS.md

Quality

61/100

Scores the file, not the repository.

Length

7,381 words

57 headings · 105 code blocks

Repository

44k

— · pushed 1 days ago

Last changed

3 days ago

First indexed 3 days ago.
sickn33/agentic-awesome-skills/plugins/agentic-bundle-aas-web-app-builder/skills/react-best-practices/AGENTS.mdRawGitHub
1# React Best Practices
2 
3**Version 0.1.0**
4Vercel Engineering
5January 2026
6 
7> **Note:**
8> This document is mainly for agents and LLMs to follow when maintaining,
9> generating, or refactoring React and Next.js codebases at Vercel. Humans
10> may also find it useful, but guidance here is optimized for automation
11> and consistency by AI-assisted workflows.
12 
13---
14 
15## Abstract
16 
17Comprehensive performance optimization guide for React and Next.js applications, designed for AI agents and LLMs. Contains 40+ rules across 8 categories, prioritized by impact from critical (eliminating waterfalls, reducing bundle size) to incremental (advanced patterns). Each rule includes detailed explanations, real-world examples comparing incorrect vs. correct implementations, and specific impact metrics to guide automated refactoring and code generation.
18 
19---
20 
21## Table of Contents
22 
231. [Eliminating Waterfalls](#1-eliminating-waterfalls) — **CRITICAL**
24 - 1.1 [Defer Await Until Needed](#11-defer-await-until-needed)
25 - 1.2 [Dependency-Based Parallelization](#12-dependency-based-parallelization)
26 - 1.3 [Prevent Waterfall Chains in API Routes](#13-prevent-waterfall-chains-in-api-routes)
27 - 1.4 [Promise.all() for Independent Operations](#14-promiseall-for-independent-operations)
28 - 1.5 [Strategic Suspense Boundaries](#15-strategic-suspense-boundaries)
292. [Bundle Size Optimization](#2-bundle-size-optimization) — **CRITICAL**
30 - 2.1 [Avoid Barrel File Imports](#21-avoid-barrel-file-imports)
31 - 2.2 [Conditional Module Loading](#22-conditional-module-loading)
32 - 2.3 [Defer Non-Critical Third-Party Libraries](#23-defer-non-critical-third-party-libraries)
33 - 2.4 [Dynamic Imports for Heavy Components](#24-dynamic-imports-for-heavy-components)
34 - 2.5 [Preload Based on User Intent](#25-preload-based-on-user-intent)
353. [Server-Side Performance](#3-server-side-performance) — **HIGH**
36 - 3.1 [Cross-Request LRU Caching](#31-cross-request-lru-caching)
37 - 3.2 [Minimize Serialization at RSC Boundaries](#32-minimize-serialization-at-rsc-boundaries)
38 - 3.3 [Parallel Data Fetching with Component Composition](#33-parallel-data-fetching-with-component-composition)
39 - 3.4 [Per-Request Deduplication with React.cache()](#34-per-request-deduplication-with-reactcache)
40 - 3.5 [Use after() for Non-Blocking Operations](#35-use-after-for-non-blocking-operations)
414. [Client-Side Data Fetching](#4-client-side-data-fetching) — **MEDIUM-HIGH**
42 - 4.1 [Deduplicate Global Event Listeners](#41-deduplicate-global-event-listeners)
43 - 4.2 [Use SWR for Automatic Deduplication](#42-use-swr-for-automatic-deduplication)
445. [Re-render Optimization](#5-re-render-optimization) — **MEDIUM**
45 - 5.1 [Defer State Reads to Usage Point](#51-defer-state-reads-to-usage-point)
46 - 5.2 [Extract to Memoized Components](#52-extract-to-memoized-components)
47 - 5.3 [Narrow Effect Dependencies](#53-narrow-effect-dependencies)
48 - 5.4 [Subscribe to Derived State](#54-subscribe-to-derived-state)
49 - 5.5 [Use Functional setState Updates](#55-use-functional-setstate-updates)
50 - 5.6 [Use Lazy State Initialization](#56-use-lazy-state-initialization)
51 - 5.7 [Use Transitions for Non-Urgent Updates](#57-use-transitions-for-non-urgent-updates)
526. [Rendering Performance](#6-rendering-performance) — **MEDIUM**
53 - 6.1 [Animate SVG Wrapper Instead of SVG Element](#61-animate-svg-wrapper-instead-of-svg-element)
54 - 6.2 [CSS content-visibility for Long Lists](#62-css-content-visibility-for-long-lists)
55 - 6.3 [Hoist Static JSX Elements](#63-hoist-static-jsx-elements)
56 - 6.4 [Optimize SVG Precision](#64-optimize-svg-precision)
57 - 6.5 [Prevent Hydration Mismatch Without Flickering](#65-prevent-hydration-mismatch-without-flickering)
58 - 6.6 [Use Activity Component for Show/Hide](#66-use-activity-component-for-showhide)
59 - 6.7 [Use Explicit Conditional Rendering](#67-use-explicit-conditional-rendering)
607. [JavaScript Performance](#7-javascript-performance) — **LOW-MEDIUM**
61 - 7.1 [Batch DOM CSS Changes](#71-batch-dom-css-changes)
62 - 7.2 [Build Index Maps for Repeated Lookups](#72-build-index-maps-for-repeated-lookups)
63 - 7.3 [Cache Property Access in Loops](#73-cache-property-access-in-loops)
64 - 7.4 [Cache Repeated Function Calls](#74-cache-repeated-function-calls)
65 - 7.5 [Cache Storage API Calls](#75-cache-storage-api-calls)
66 - 7.6 [Combine Multiple Array Iterations](#76-combine-multiple-array-iterations)
67 - 7.7 [Early Length Check for Array Comparisons](#77-early-length-check-for-array-comparisons)
68 - 7.8 [Early Return from Functions](#78-early-return-from-functions)
69 - 7.9 [Hoist RegExp Creation](#79-hoist-regexp-creation)
70 - 7.10 [Use Loop for Min/Max Instead of Sort](#710-use-loop-for-minmax-instead-of-sort)
71 - 7.11 [Use Set/Map for O(1) Lookups](#711-use-setmap-for-o1-lookups)
72 - 7.12 [Use toSorted() Instead of sort() for Immutability](#712-use-tosorted-instead-of-sort-for-immutability)
738. [Advanced Patterns](#8-advanced-patterns) — **LOW**
74 - 8.1 [Store Event Handlers in Refs](#81-store-event-handlers-in-refs)
75 - 8.2 [useLatest for Stable Callback Refs](#82-uselatest-for-stable-callback-refs)
76 
77---
78 
79## 1. Eliminating Waterfalls
80 
81**Impact: CRITICAL**
82 
83Waterfalls are the #1 performance killer. Each sequential await adds full network latency. Eliminating them yields the largest gains.
84 
85### 1.1 Defer Await Until Needed
86 
87**Impact: HIGH (avoids blocking unused code paths)**
88 
89Move `await` operations into the branches where they're actually used to avoid blocking code paths that don't need them.
90 
91**Incorrect: blocks both branches**
92 
93```typescript
94async function handleRequest(userId: string, skipProcessing: boolean) {
95 const userData = await fetchUserData(userId)
96
97 if (skipProcessing) {
98 // Returns immediately but still waited for userData
99 return { skipped: true }
100 }
101
102 // Only this branch uses userData
103 return processUserData(userData)
104}
105```
106 
107**Correct: only blocks when needed**
108 
109```typescript
110async function handleRequest(userId: string, skipProcessing: boolean) {
111 if (skipProcessing) {
112 // Returns immediately without waiting
113 return { skipped: true }
114 }
115
116 // Fetch only when needed
117 const userData = await fetchUserData(userId)
118 return processUserData(userData)
119}
120```
121 
122**Another example: early return optimization**
123 
124```typescript
125// Incorrect: always fetches permissions
126async function updateResource(resourceId: string, userId: string) {
127 const permissions = await fetchPermissions(userId)
128 const resource = await getResource(resourceId)
129
130 if (!resource) {
131 return { error: 'Not found' }
132 }
133
134 if (!permissions.canEdit) {
135 return { error: 'Forbidden' }
136 }
137
138 return await updateResourceData(resource, permissions)
139}
140 
141// Correct: fetches only when needed
142async function updateResource(resourceId: string, userId: string) {
143 const resource = await getResource(resourceId)
144
145 if (!resource) {
146 return { error: 'Not found' }
147 }
148
149 const permissions = await fetchPermissions(userId)
150
151 if (!permissions.canEdit) {
152 return { error: 'Forbidden' }
153 }
154
155 return await updateResourceData(resource, permissions)
156}
157```
158 
159This optimization is especially valuable when the skipped branch is frequently taken, or when the deferred operation is expensive.
160 
161### 1.2 Dependency-Based Parallelization
162 
163**Impact: CRITICAL (2-10× improvement)**
164 
165For operations with partial dependencies, use `better-all` to maximize parallelism. It automatically starts each task at the earliest possible moment.
166 
167**Incorrect: profile waits for config unnecessarily**
168 
169```typescript
170const [user, config] = await Promise.all([
171 fetchUser(),
172 fetchConfig()
173])
174const profile = await fetchProfile(user.id)
175```
176 
177**Correct: config and profile run in parallel**
178 
179```typescript
180import { all } from 'better-all'
181 
182const { user, config, profile } = await all({
183 async user() { return fetchUser() },
184 async config() { return fetchConfig() },
185 async profile() {
186 return fetchProfile((await this.$.user).id)
187 }
188})
189```
190 
191Reference: [https://github.com/shuding/better-all](https://github.com/shuding/better-all)
192 
193### 1.3 Prevent Waterfall Chains in API Routes
194 
195**Impact: CRITICAL (2-10× improvement)**
196 
197In API routes and Server Actions, start independent operations immediately, even if you don't await them yet.
198 
199**Incorrect: config waits for auth, data waits for both**
200 
201```typescript
202export async function GET(request: Request) {
203 const session = await auth()
204 const config = await fetchConfig()
205 const data = await fetchData(session.user.id)
206 return Response.json({ data, config })
207}
208```
209 
210**Correct: auth and config start immediately**
211 
212```typescript
213export async function GET(request: Request) {
214 const sessionPromise = auth()
215 const configPromise = fetchConfig()
216 const session = await sessionPromise
217 const [config, data] = await Promise.all([
218 configPromise,
219 fetchData(session.user.id)
220 ])
221 return Response.json({ data, config })
222}
223```
224 
225For operations with more complex dependency chains, use `better-all` to automatically maximize parallelism (see Dependency-Based Parallelization).
226 
227### 1.4 Promise.all() for Independent Operations
228 
229**Impact: CRITICAL (2-10× improvement)**
230 
231When async operations have no interdependencies, execute them concurrently using `Promise.all()`.
232 
233**Incorrect: sequential execution, 3 round trips**
234 
235```typescript
236const user = await fetchUser()
237const posts = await fetchPosts()
238const comments = await fetchComments()
239```
240 
241**Correct: parallel execution, 1 round trip**
242 
243```typescript
244const [user, posts, comments] = await Promise.all([
245 fetchUser(),
246 fetchPosts(),
247 fetchComments()
248])
249```
250 
251### 1.5 Strategic Suspense Boundaries
252 
253**Impact: HIGH (faster initial paint)**
254 
255Instead of awaiting data in async components before returning JSX, use Suspense boundaries to show the wrapper UI faster while data loads.
256 
257**Incorrect: wrapper blocked by data fetching**
258 
259```tsx
260async function Page() {
261 const data = await fetchData() // Blocks entire page
262
263 return (
264 <div>
265 <div>Sidebar</div>
266 <div>Header</div>
267 <div>
268 <DataDisplay data={data} />
269 </div>
270 <div>Footer</div>
271 </div>
272 )
273}
274```
275 
276The entire layout waits for data even though only the middle section needs it.
277 
278**Correct: wrapper shows immediately, data streams in**
279 
280```tsx
281function Page() {
282 return (
283 <div>
284 <div>Sidebar</div>
285 <div>Header</div>
286 <div>
287 <Suspense fallback={<Skeleton />}>
288 <DataDisplay />
289 </Suspense>
290 </div>
291 <div>Footer</div>
292 </div>
293 )
294}
295 
296async function DataDisplay() {
297 const data = await fetchData() // Only blocks this component
298 return <div>{data.content}</div>
299}
300```
301 
302Sidebar, Header, and Footer render immediately. Only DataDisplay waits for data.
303 
304**Alternative: share promise across components**
305 
306```tsx
307function Page() {
308 // Start fetch immediately, but don't await
309 const dataPromise = fetchData()
310
311 return (
312 <div>
313 <div>Sidebar</div>
314 <div>Header</div>
315 <Suspense fallback={<Skeleton />}>
316 <DataDisplay dataPromise={dataPromise} />
317 <DataSummary dataPromise={dataPromise} />
318 </Suspense>
319 <div>Footer</div>
320 </div>
321 )
322}
323 
324function DataDisplay({ dataPromise }: { dataPromise: Promise<Data> }) {
325 const data = use(dataPromise) // Unwraps the promise
326 return <div>{data.content}</div>
327}
328 
329function DataSummary({ dataPromise }: { dataPromise: Promise<Data> }) {
330 const data = use(dataPromise) // Reuses the same promise
331 return <div>{data.summary}</div>
332}
333```
334 
335Both components share the same promise, so only one fetch occurs. Layout renders immediately while both components wait together.
336 
337**When NOT to use this pattern:**
338 
339- Critical data needed for layout decisions (affects positioning)
340 
341- SEO-critical content above the fold
342 
343- Small, fast queries where suspense overhead isn't worth it
344 
345- When you want to avoid layout shift (loading → content jump)
346 
347**Trade-off:** Faster initial paint vs potential layout shift. Choose based on your UX priorities.
348 
349---
350 
351## 2. Bundle Size Optimization
352 
353**Impact: CRITICAL**
354 
355Reducing initial bundle size improves Time to Interactive and Largest Contentful Paint.
356 
357### 2.1 Avoid Barrel File Imports
358 
359**Impact: CRITICAL (200-800ms import cost, slow builds)**
360 
361Import directly from source files instead of barrel files to avoid loading thousands of unused modules. **Barrel files** are entry points that re-export multiple modules (e.g., `index.js` that does `export * from './module'`).
362 
363Popular icon and component libraries can have **up to 10,000 re-exports** in their entry file. For many React packages, **it takes 200-800ms just to import them**, affecting both development speed and production cold starts.
364 
365**Why tree-shaking doesn't help:** When a library is marked as external (not bundled), the bundler can't optimize it. If you bundle it to enable tree-shaking, builds become substantially slower analyzing the entire module graph.
366 
367**Incorrect: imports entire library**
368 
369```tsx
370import { Check, X, Menu } from 'lucide-react'
371// Loads 1,583 modules, takes ~2.8s extra in dev
372// Runtime cost: 200-800ms on every cold start
373 
374import { Button, TextField } from '@mui/material'
375// Loads 2,225 modules, takes ~4.2s extra in dev
376```
377 
378**Correct: imports only what you need**
379 
380```tsx
381import Check from 'lucide-react/dist/esm/icons/check'
382import X from 'lucide-react/dist/esm/icons/x'
383import Menu from 'lucide-react/dist/esm/icons/menu'
384// Loads only 3 modules (~2KB vs ~1MB)
385 
386import Button from '@mui/material/Button'
387import TextField from '@mui/material/TextField'
388// Loads only what you use
389```
390 
391**Alternative: Next.js 13.5+**
392 
393```js
394// next.config.js - use optimizePackageImports
395module.exports = {
396 experimental: {
397 optimizePackageImports: ['lucide-react', '@mui/material']
398 }
399}
400 
401// Then you can keep the ergonomic barrel imports:
402import { Check, X, Menu } from 'lucide-react'
403// Automatically transformed to direct imports at build time
404```
405 
406Direct imports provide 15-70% faster dev boot, 28% faster builds, 40% faster cold starts, and significantly faster HMR.
407 
408Libraries commonly affected: `lucide-react`, `@mui/material`, `@mui/icons-material`, `@tabler/icons-react`, `react-icons`, `@headlessui/react`, `@radix-ui/react-*`, `lodash`, `ramda`, `date-fns`, `rxjs`, `react-use`.
409 
410Reference: [https://vercel.com/blog/how-we-optimized-package-imports-in-next-js](https://vercel.com/blog/how-we-optimized-package-imports-in-next-js)
411 
412### 2.2 Conditional Module Loading
413 
414**Impact: HIGH (loads large data only when needed)**
415 
416Load large data or modules only when a feature is activated.
417 
418**Example: lazy-load animation frames**
419 
420```tsx
421function AnimationPlayer({ enabled }: { enabled: boolean }) {
422 const [frames, setFrames] = useState<Frame[] | null>(null)
423 
424 useEffect(() => {
425 if (enabled && !frames && typeof window !== 'undefined') {
426 import('./animation-frames.js')
427 .then(mod => setFrames(mod.frames))
428 .catch(() => setEnabled(false))
429 }
430 }, [enabled, frames])
431 
432 if (!frames) return <Skeleton />
433 return <Canvas frames={frames} />
434}
435```
436 
437The `typeof window !== 'undefined'` check prevents bundling this module for SSR, optimizing server bundle size and build speed.
438 
439### 2.3 Defer Non-Critical Third-Party Libraries
440 
441**Impact: MEDIUM (loads after hydration)**
442 
443Analytics, logging, and error tracking don't block user interaction. Load them after hydration.
444 
445**Incorrect: blocks initial bundle**
446 
447```tsx
448import { Analytics } from '@vercel/analytics/react'
449 
450export default function RootLayout({ children }) {
451 return (
452 <html>
453 <body>
454 {children}
455 <Analytics />
456 </body>
457 </html>
458 )
459}
460```
461 
462**Correct: loads after hydration**
463 
464```tsx
465import dynamic from 'next/dynamic'
466 
467const Analytics = dynamic(
468 () => import('@vercel/analytics/react').then(m => m.Analytics),
469 { ssr: false }
470)
471 
472export default function RootLayout({ children }) {
473 return (
474 <html>
475 <body>
476 {children}
477 <Analytics />
478 </body>
479 </html>
480 )
481}
482```
483 
484### 2.4 Dynamic Imports for Heavy Components
485 
486**Impact: CRITICAL (directly affects TTI and LCP)**
487 
488Use `next/dynamic` to lazy-load large components not needed on initial render.
489 
490**Incorrect: Monaco bundles with main chunk ~300KB**
491 
492```tsx
493import { MonacoEditor } from './monaco-editor'
494 
495function CodePanel({ code }: { code: string }) {
496 return <MonacoEditor value={code} />
497}
498```
499 
500**Correct: Monaco loads on demand**
501 
502```tsx
503import dynamic from 'next/dynamic'
504 
505const MonacoEditor = dynamic(
506 () => import('./monaco-editor').then(m => m.MonacoEditor),
507 { ssr: false }
508)
509 
510function CodePanel({ code }: { code: string }) {
511 return <MonacoEditor value={code} />
512}
513```
514 
515### 2.5 Preload Based on User Intent
516 
517**Impact: MEDIUM (reduces perceived latency)**
518 
519Preload heavy bundles before they're needed to reduce perceived latency.
520 
521**Example: preload on hover/focus**
522 
523```tsx
524function EditorButton({ onClick }: { onClick: () => void }) {
525 const preload = () => {
526 if (typeof window !== 'undefined') {
527 void import('./monaco-editor')
528 }
529 }
530 
531 return (
532 <button
533 onMouseEnter={preload}
534 onFocus={preload}
535 onClick={onClick}
536 >
537 Open Editor
538 </button>
539 )
540}
541```
542 
543**Example: preload when feature flag is enabled**
544 
545```tsx
546function FlagsProvider({ children, flags }: Props) {
547 useEffect(() => {
548 if (flags.editorEnabled && typeof window !== 'undefined') {
549 void import('./monaco-editor').then(mod => mod.init())
550 }
551 }, [flags.editorEnabled])
552 
553 return <FlagsContext.Provider value={flags}>
554 {children}
555 </FlagsContext.Provider>
556}
557```
558 
559The `typeof window !== 'undefined'` check prevents bundling preloaded modules for SSR, optimizing server bundle size and build speed.
560 
561---
562 
563## 3. Server-Side Performance
564 
565**Impact: HIGH**
566 
567Optimizing server-side rendering and data fetching eliminates server-side waterfalls and reduces response times.
568 
569### 3.1 Cross-Request LRU Caching
570 
571**Impact: HIGH (caches across requests)**
572 
573`React.cache()` only works within one request. For data shared across sequential requests (user clicks button A then button B), use an LRU cache.
574 
575**Implementation:**
576 
577```typescript
578import { LRUCache } from 'lru-cache'
579 
580const cache = new LRUCache<string, any>({
581 max: 1000,
582 ttl: 5 * 60 * 1000 // 5 minutes
583})
584 
585export async function getUser(id: string) {
586 const cached = cache.get(id)
587 if (cached) return cached
588 
589 const user = await db.user.findUnique({ where: { id } })
590 cache.set(id, user)
591 return user
592}
593 
594// Request 1: DB query, result cached
595// Request 2: cache hit, no DB query
596```
597 
598Use when sequential user actions hit multiple endpoints needing the same data within seconds.
599 
600**With Vercel's [Fluid Compute](https://vercel.com/docs/fluid-compute):** LRU caching is especially effective because multiple concurrent requests can share the same function instance and cache. This means the cache persists across requests without needing external storage like Redis.
601 
602**In traditional serverless:** Each invocation runs in isolation, so consider Redis for cross-process caching.
603 
604Reference: [https://github.com/isaacs/node-lru-cache](https://github.com/isaacs/node-lru-cache)
605 
606### 3.2 Minimize Serialization at RSC Boundaries
607 
608**Impact: HIGH (reduces data transfer size)**
609 
610The React Server/Client boundary serializes all object properties into strings and embeds them in the HTML response and subsequent RSC requests. This serialized data directly impacts page weight and load time, so **size matters a lot**. Only pass fields that the client actually uses.
611 
612**Incorrect: serializes all 50 fields**
613 
614```tsx
615async function Page() {
616 const user = await fetchUser() // 50 fields
617 return <Profile user={user} />
618}
619 
620'use client'
621function Profile({ user }: { user: User }) {
622 return <div>{user.name}</div> // uses 1 field
623}
624```
625 
626**Correct: serializes only 1 field**
627 
628```tsx
629async function Page() {
630 const user = await fetchUser()
631 return <Profile name={user.name} />
632}
633 
634'use client'
635function Profile({ name }: { name: string }) {
636 return <div>{name}</div>
637}
638```
639 
640### 3.3 Parallel Data Fetching with Component Composition
641 
642**Impact: CRITICAL (eliminates server-side waterfalls)**
643 
644React Server Components execute sequentially within a tree. Restructure with composition to parallelize data fetching.
645 
646**Incorrect: Sidebar waits for Page's fetch to complete**
647 
648```tsx
649export default async function Page() {
650 const header = await fetchHeader()
651 return (
652 <div>
653 <div>{header}</div>
654 <Sidebar />
655 </div>
656 )
657}
658 
659async function Sidebar() {
660 const items = await fetchSidebarItems()
661 return <nav>{items.map(renderItem)}</nav>
662}
663```
664 
665**Correct: both fetch simultaneously**
666 
667```tsx
668async function Header() {
669 const data = await fetchHeader()
670 return <div>{data}</div>
671}
672 
673async function Sidebar() {
674 const items = await fetchSidebarItems()
675 return <nav>{items.map(renderItem)}</nav>
676}
677 
678export default function Page() {
679 return (
680 <div>
681 <Header />
682 <Sidebar />
683 </div>
684 )
685}
686```
687 
688**Alternative with children prop:**
689 
690```tsx
691async function Layout({ children }: { children: ReactNode }) {
692 const header = await fetchHeader()
693 return (
694 <div>
695 <div>{header}</div>
696 {children}
697 </div>
698 )
699}
700 
701async function Sidebar() {
702 const items = await fetchSidebarItems()
703 return <nav>{items.map(renderItem)}</nav>
704}
705 
706export default function Page() {
707 return (
708 <Layout>
709 <Sidebar />
710 </Layout>
711 )
712}
713```
714 
715### 3.4 Per-Request Deduplication with React.cache()
716 
717**Impact: MEDIUM (deduplicates within request)**
718 
719Use `React.cache()` for server-side request deduplication. Authentication and database queries benefit most.
720 
721**Usage:**
722 
723```typescript
724import { cache } from 'react'
725 
726export const getCurrentUser = cache(async () => {
727 const session = await auth()
728 if (!session?.user?.id) return null
729 return await db.user.findUnique({
730 where: { id: session.user.id }
731 })
732})
733```
734 
735Within a single request, multiple calls to `getCurrentUser()` execute the query only once.
736 
737### 3.5 Use after() for Non-Blocking Operations
738 
739**Impact: MEDIUM (faster response times)**
740 
741Use Next.js's `after()` to schedule work that should execute after a response is sent. This prevents logging, analytics, and other side effects from blocking the response.
742 
743**Incorrect: blocks response**
744 
745```tsx
746import { logUserAction } from '@/app/utils'
747 
748export async function POST(request: Request) {
749 // Perform mutation
750 await updateDatabase(request)
751
752 // Logging blocks the response
753 const userAgent = request.headers.get('user-agent') || 'unknown'
754 await logUserAction({ userAgent })
755
756 return new Response(JSON.stringify({ status: 'success' }), {
757 status: 200,
758 headers: { 'Content-Type': 'application/json' }
759 })
760}
761```
762 
763**Correct: non-blocking**
764 
765```tsx
766import { after } from 'next/server'
767import { headers, cookies } from 'next/headers'
768import { logUserAction } from '@/app/utils'
769 
770export async function POST(request: Request) {
771 // Perform mutation
772 await updateDatabase(request)
773
774 // Log after response is sent
775 after(async () => {
776 const userAgent = (await headers()).get('user-agent') || 'unknown'
777 const sessionCookie = (await cookies()).get('session-id')?.value || 'anonymous'
778
779 logUserAction({ sessionCookie, userAgent })
780 })
781
782 return new Response(JSON.stringify({ status: 'success' }), {
783 status: 200,
784 headers: { 'Content-Type': 'application/json' }
785 })
786}
787```
788 
789The response is sent immediately while logging happens in the background.
790 
791**Common use cases:**
792 
793- Analytics tracking
794 
795- Audit logging
796 
797- Sending notifications
798 
799- Cache invalidation
800 
801- Cleanup tasks
802 
803**Important notes:**
804 
805- `after()` runs even if the response fails or redirects
806 
807- Works in Server Actions, Route Handlers, and Server Components
808 
809Reference: [https://nextjs.org/docs/app/api-reference/functions/after](https://nextjs.org/docs/app/api-reference/functions/after)
810 
811---
812 
813## 4. Client-Side Data Fetching
814 
815**Impact: MEDIUM-HIGH**
816 
817Automatic deduplication and efficient data fetching patterns reduce redundant network requests.
818 
819### 4.1 Deduplicate Global Event Listeners
820 
821**Impact: LOW (single listener for N components)**
822 
823Use `useSWRSubscription()` to share global event listeners across component instances.
824 
825**Incorrect: N instances = N listeners**
826 
827```tsx
828function useKeyboardShortcut(key: string, callback: () => void) {
829 useEffect(() => {
830 const handler = (e: KeyboardEvent) => {
831 if (e.metaKey && e.key === key) {
832 callback()
833 }
834 }
835 window.addEventListener('keydown', handler)
836 return () => window.removeEventListener('keydown', handler)
837 }, [key, callback])
838}
839```
840 
841When using the `useKeyboardShortcut` hook multiple times, each instance will register a new listener.
842 
843**Correct: N instances = 1 listener**
844 
845```tsx
846import useSWRSubscription from 'swr/subscription'
847 
848// Module-level Map to track callbacks per key
849const keyCallbacks = new Map<string, Set<() => void>>()
850 
851function useKeyboardShortcut(key: string, callback: () => void) {
852 // Register this callback in the Map
853 useEffect(() => {
854 if (!keyCallbacks.has(key)) {
855 keyCallbacks.set(key, new Set())
856 }
857 keyCallbacks.get(key)!.add(callback)
858 
859 return () => {
860 const set = keyCallbacks.get(key)
861 if (set) {
862 set.delete(callback)
863 if (set.size === 0) {
864 keyCallbacks.delete(key)
865 }
866 }
867 }
868 }, [key, callback])
869 
870 useSWRSubscription('global-keydown', () => {
871 const handler = (e: KeyboardEvent) => {
872 if (e.metaKey && keyCallbacks.has(e.key)) {
873 keyCallbacks.get(e.key)!.forEach(cb => cb())
874 }
875 }
876 window.addEventListener('keydown', handler)
877 return () => window.removeEventListener('keydown', handler)
878 })
879}
880 
881function Profile() {
882 // Multiple shortcuts will share the same listener
883 useKeyboardShortcut('p', () => { /* ... */ })
884 useKeyboardShortcut('k', () => { /* ... */ })
885 // ...
886}
887```
888 
889### 4.2 Use SWR for Automatic Deduplication
890 
891**Impact: MEDIUM-HIGH (automatic deduplication)**
892 
893SWR enables request deduplication, caching, and revalidation across component instances.
894 
895**Incorrect: no deduplication, each instance fetches**
896 
897```tsx
898function UserList() {
899 const [users, setUsers] = useState([])
900 useEffect(() => {
901 fetch('/api/users')
902 .then(r => r.json())
903 .then(setUsers)
904 }, [])
905}
906```
907 
908**Correct: multiple instances share one request**
909 
910```tsx
911import useSWR from 'swr'
912 
913function UserList() {
914 const { data: users } = useSWR('/api/users', fetcher)
915}
916```
917 
918**For immutable data:**
919 
920```tsx
921import { useImmutableSWR } from '@/lib/swr'
922 
923function StaticContent() {
924 const { data } = useImmutableSWR('/api/config', fetcher)
925}
926```
927 
928**For mutations:**
929 
930```tsx
931import { useSWRMutation } from 'swr/mutation'
932 
933function UpdateButton() {
934 const { trigger } = useSWRMutation('/api/user', updateUser)
935 return <button onClick={() => trigger()}>Update</button>
936}
937```
938 
939Reference: [https://swr.vercel.app](https://swr.vercel.app)
940 
941---
942 
943## 5. Re-render Optimization
944 
945**Impact: MEDIUM**
946 
947Reducing unnecessary re-renders minimizes wasted computation and improves UI responsiveness.
948 
949### 5.1 Defer State Reads to Usage Point
950 
951**Impact: MEDIUM (avoids unnecessary subscriptions)**
952 
953Don't subscribe to dynamic state (searchParams, localStorage) if you only read it inside callbacks.
954 
955**Incorrect: subscribes to all searchParams changes**
956 
957```tsx
958function ShareButton({ chatId }: { chatId: string }) {
959 const searchParams = useSearchParams()
960 
961 const handleShare = () => {
962 const ref = searchParams.get('ref')
963 shareChat(chatId, { ref })
964 }
965 
966 return <button onClick={handleShare}>Share</button>
967}
968```
969 
970**Correct: reads on demand, no subscription**
971 
972```tsx
973function ShareButton({ chatId }: { chatId: string }) {
974 const handleShare = () => {
975 const params = new URLSearchParams(window.location.search)
976 const ref = params.get('ref')
977 shareChat(chatId, { ref })
978 }
979 
980 return <button onClick={handleShare}>Share</button>
981}
982```
983 
984### 5.2 Extract to Memoized Components
985 
986**Impact: MEDIUM (enables early returns)**
987 
988Extract expensive work into memoized components to enable early returns before computation.
989 
990**Incorrect: computes avatar even when loading**
991 
992```tsx
993function Profile({ user, loading }: Props) {
994 const avatar = useMemo(() => {
995 const id = computeAvatarId(user)
996 return <Avatar id={id} />
997 }, [user])
998 
999 if (loading) return <Skeleton />
1000 return <div>{avatar}</div>
1001}
1002```
1003 
1004**Correct: skips computation when loading**
1005 
1006```tsx
1007const UserAvatar = memo(function UserAvatar({ user }: { user: User }) {
1008 const id = useMemo(() => computeAvatarId(user), [user])
1009 return <Avatar id={id} />
1010})
1011 
1012function Profile({ user, loading }: Props) {
1013 if (loading) return <Skeleton />
1014 return (
1015 <div>
1016 <UserAvatar user={user} />
1017 </div>
1018 )
1019}
1020```
1021 
1022**Note:** If your project has [React Compiler](https://react.dev/learn/react-compiler) enabled, manual memoization with `memo()` and `useMemo()` is not necessary. The compiler automatically optimizes re-renders.
1023 
1024### 5.3 Narrow Effect Dependencies
1025 
1026**Impact: LOW (minimizes effect re-runs)**
1027 
1028Specify primitive dependencies instead of objects to minimize effect re-runs.
1029 
1030**Incorrect: re-runs on any user field change**
1031 
1032```tsx
1033useEffect(() => {
1034 console.log(user.id)
1035}, [user])
1036```
1037 
1038**Correct: re-runs only when id changes**
1039 
1040```tsx
1041useEffect(() => {
1042 console.log(user.id)
1043}, [user.id])
1044```
1045 
1046**For derived state, compute outside effect:**
1047 
1048```tsx
1049// Incorrect: runs on width=767, 766, 765...
1050useEffect(() => {
1051 if (width < 768) {
1052 enableMobileMode()
1053 }
1054}, [width])
1055 
1056// Correct: runs only on boolean transition
1057const isMobile = width < 768
1058useEffect(() => {
1059 if (isMobile) {
1060 enableMobileMode()
1061 }
1062}, [isMobile])
1063```
1064 
1065### 5.4 Subscribe to Derived State
1066 
1067**Impact: MEDIUM (reduces re-render frequency)**
1068 
1069Subscribe to derived boolean state instead of continuous values to reduce re-render frequency.
1070 
1071**Incorrect: re-renders on every pixel change**
1072 
1073```tsx
1074function Sidebar() {
1075 const width = useWindowWidth() // updates continuously
1076 const isMobile = width < 768
1077 return <nav className={isMobile ? 'mobile' : 'desktop'}>
1078}
1079```
1080 
1081**Correct: re-renders only when boolean changes**
1082 
1083```tsx
1084function Sidebar() {
1085 const isMobile = useMediaQuery('(max-width: 767px)')
1086 return <nav className={isMobile ? 'mobile' : 'desktop'}>
1087}
1088```
1089 
1090### 5.5 Use Functional setState Updates
1091 
1092**Impact: MEDIUM (prevents stale closures and unnecessary callback recreations)**
1093 
1094When updating state based on the current state value, use the functional update form of setState instead of directly referencing the state variable. This prevents stale closures, eliminates unnecessary dependencies, and creates stable callback references.
1095 
1096**Incorrect: requires state as dependency**
1097 
1098```tsx
1099function TodoList() {
1100 const [items, setItems] = useState(initialItems)
1101
1102 // Callback must depend on items, recreated on every items change
1103 const addItems = useCallback((newItems: Item[]) => {
1104 setItems([...items, ...newItems])
1105 }, [items]) // ❌ items dependency causes recreations
1106
1107 // Risk of stale closure if dependency is forgotten
1108 const removeItem = useCallback((id: string) => {
1109 setItems(items.filter(item => item.id !== id))
1110 }, []) // ❌ Missing items dependency - will use stale items!
1111
1112 return <ItemsEditor items={items} onAdd={addItems} onRemove={removeItem} />
1113}
1114```
1115 
1116The first callback is recreated every time `items` changes, which can cause child components to re-render unnecessarily. The second callback has a stale closure bug—it will always reference the initial `items` value.
1117 
1118**Correct: stable callbacks, no stale closures**
1119 
1120```tsx
1121function TodoList() {
1122 const [items, setItems] = useState(initialItems)
1123
1124 // Stable callback, never recreated
1125 const addItems = useCallback((newItems: Item[]) => {
1126 setItems(curr => [...curr, ...newItems])
1127 }, []) // ✅ No dependencies needed
1128
1129 // Always uses latest state, no stale closure risk
1130 const removeItem = useCallback((id: string) => {
1131 setItems(curr => curr.filter(item => item.id !== id))
1132 }, []) // ✅ Safe and stable
1133
1134 return <ItemsEditor items={items} onAdd={addItems} onRemove={removeItem} />
1135}
1136```
1137 
1138**Benefits:**
1139 
11401. **Stable callback references** - Callbacks don't need to be recreated when state changes
1141 
11422. **No stale closures** - Always operates on the latest state value
1143 
11443. **Fewer dependencies** - Simplifies dependency arrays and reduces memory leaks
1145 
11464. **Prevents bugs** - Eliminates the most common source of React closure bugs
1147 
1148**When to use functional updates:**
1149 
1150- Any setState that depends on the current state value
1151 
1152- Inside useCallback/useMemo when state is needed
1153 
1154- Event handlers that reference state
1155 
1156- Async operations that update state
1157 
1158**When direct updates are fine:**
1159 
1160- Setting state to a static value: `setCount(0)`
1161 
1162- Setting state from props/arguments only: `setName(newName)`
1163 
1164- State doesn't depend on previous value
1165 
1166**Note:** If your project has [React Compiler](https://react.dev/learn/react-compiler) enabled, the compiler can automatically optimize some cases, but functional updates are still recommended for correctness and to prevent stale closure bugs.
1167 
1168### 5.6 Use Lazy State Initialization
1169 
1170**Impact: MEDIUM (wasted computation on every render)**
1171 
1172Pass a function to `useState` for expensive initial values. Without the function form, the initializer runs on every render even though the value is only used once.
1173 
1174**Incorrect: runs on every render**
1175 
1176```tsx
1177function FilteredList({ items }: { items: Item[] }) {
1178 // buildSearchIndex() runs on EVERY render, even after initialization
1179 const [searchIndex, setSearchIndex] = useState(buildSearchIndex(items))
1180 const [query, setQuery] = useState('')
1181
1182 // When query changes, buildSearchIndex runs again unnecessarily
1183 return <SearchResults index={searchIndex} query={query} />
1184}
1185 
1186function UserProfile() {
1187 // JSON.parse runs on every render
1188 const [settings, setSettings] = useState(
1189 JSON.parse(localStorage.getItem('settings') || '{}')
1190 )
1191
1192 return <SettingsForm settings={settings} onChange={setSettings} />
1193}
1194```
1195 
1196**Correct: runs only once**
1197 
1198```tsx
1199function FilteredList({ items }: { items: Item[] }) {
1200 // buildSearchIndex() runs ONLY on initial render
1201 const [searchIndex, setSearchIndex] = useState(() => buildSearchIndex(items))
1202 const [query, setQuery] = useState('')
1203
1204 return <SearchResults index={searchIndex} query={query} />
1205}
1206 
1207function UserProfile() {
1208 // JSON.parse runs only on initial render
1209 const [settings, setSettings] = useState(() => {
1210 const stored = localStorage.getItem('settings')
1211 return stored ? JSON.parse(stored) : {}
1212 })
1213
1214 return <SettingsForm settings={settings} onChange={setSettings} />
1215}
1216```
1217 
1218Use lazy initialization when computing initial values from localStorage/sessionStorage, building data structures (indexes, maps), reading from the DOM, or performing heavy transformations.
1219 
1220For simple primitives (`useState(0)`), direct references (`useState(props.value)`), or cheap literals (`useState({})`), the function form is unnecessary.
1221 
1222### 5.7 Use Transitions for Non-Urgent Updates
1223 
1224**Impact: MEDIUM (maintains UI responsiveness)**
1225 
1226Mark frequent, non-urgent state updates as transitions to maintain UI responsiveness.
1227 
1228**Incorrect: blocks UI on every scroll**
1229 
1230```tsx
1231function ScrollTracker() {
1232 const [scrollY, setScrollY] = useState(0)
1233 useEffect(() => {
1234 const handler = () => setScrollY(window.scrollY)
1235 window.addEventListener('scroll', handler, { passive: true })
1236 return () => window.removeEventListener('scroll', handler)
1237 }, [])
1238}
1239```
1240 
1241**Correct: non-blocking updates**
1242 
1243```tsx
1244import { startTransition } from 'react'
1245 
1246function ScrollTracker() {
1247 const [scrollY, setScrollY] = useState(0)
1248 useEffect(() => {
1249 const handler = () => {
1250 startTransition(() => setScrollY(window.scrollY))
1251 }
1252 window.addEventListener('scroll', handler, { passive: true })
1253 return () => window.removeEventListener('scroll', handler)
1254 }, [])
1255}
1256```
1257 
1258---
1259 
1260## 6. Rendering Performance
1261 
1262**Impact: MEDIUM**
1263 
1264Optimizing the rendering process reduces the work the browser needs to do.
1265 
1266### 6.1 Animate SVG Wrapper Instead of SVG Element
1267 
1268**Impact: LOW (enables hardware acceleration)**
1269 
1270Many browsers don't have hardware acceleration for CSS3 animations on SVG elements. Wrap SVG in a `<div>` and animate the wrapper instead.
1271 
1272**Incorrect: animating SVG directly - no hardware acceleration**
1273 
1274```tsx
1275function LoadingSpinner() {
1276 return (
1277 <svg
1278 className="animate-spin"
1279 width="24"
1280 height="24"
1281 viewBox="0 0 24 24"
1282 >
1283 <circle cx="12" cy="12" r="10" stroke="currentColor" />
1284 </svg>
1285 )
1286}
1287```
1288 
1289**Correct: animating wrapper div - hardware accelerated**
1290 
1291```tsx
1292function LoadingSpinner() {
1293 return (
1294 <div className="animate-spin">
1295 <svg
1296 width="24"
1297 height="24"
1298 viewBox="0 0 24 24"
1299 >
1300 <circle cx="12" cy="12" r="10" stroke="currentColor" />
1301 </svg>
1302 </div>
1303 )
1304}
1305```
1306 
1307This applies to all CSS transforms and transitions (`transform`, `opacity`, `translate`, `scale`, `rotate`). The wrapper div allows browsers to use GPU acceleration for smoother animations.
1308 
1309### 6.2 CSS content-visibility for Long Lists
1310 
1311**Impact: HIGH (faster initial render)**
1312 
1313Apply `content-visibility: auto` to defer off-screen rendering.
1314 
1315**CSS:**
1316 
1317```css
1318.message-item {
1319 content-visibility: auto;
1320 contain-intrinsic-size: 0 80px;
1321}
1322```
1323 
1324**Example:**
1325 
1326```tsx
1327function MessageList({ messages }: { messages: Message[] }) {
1328 return (
1329 <div className="overflow-y-auto h-screen">
1330 {messages.map(msg => (
1331 <div key={msg.id} className="message-item">
1332 <Avatar user={msg.author} />
1333 <div>{msg.content}</div>
1334 </div>
1335 ))}
1336 </div>
1337 )
1338}
1339```
1340 
1341For 1000 messages, browser skips layout/paint for ~990 off-screen items (10× faster initial render).
1342 
1343### 6.3 Hoist Static JSX Elements
1344 
1345**Impact: LOW (avoids re-creation)**
1346 
1347Extract static JSX outside components to avoid re-creation.
1348 
1349**Incorrect: recreates element every render**
1350 
1351```tsx
1352function LoadingSkeleton() {
1353 return <div className="animate-pulse h-20 bg-gray-200" />
1354}
1355 
1356function Container() {
1357 return (
1358 <div>
1359 {loading && <LoadingSkeleton />}
1360 </div>
1361 )
1362}
1363```
1364 
1365**Correct: reuses same element**
1366 
1367```tsx
1368const loadingSkeleton = (
1369 <div className="animate-pulse h-20 bg-gray-200" />
1370)
1371 
1372function Container() {
1373 return (
1374 <div>
1375 {loading && loadingSkeleton}
1376 </div>
1377 )
1378}
1379```
1380 
1381This is especially helpful for large and static SVG nodes, which can be expensive to recreate on every render.
1382 
1383**Note:** If your project has [React Compiler](https://react.dev/learn/react-compiler) enabled, the compiler automatically hoists static JSX elements and optimizes component re-renders, making manual hoisting unnecessary.
1384 
1385### 6.4 Optimize SVG Precision
1386 
1387**Impact: LOW (reduces file size)**
1388 
1389Reduce SVG coordinate precision to decrease file size. The optimal precision depends on the viewBox size, but in general reducing precision should be considered.
1390 
1391**Incorrect: excessive precision**
1392 
1393```svg
1394<path d="M 10.293847 20.847362 L 30.938472 40.192837" />
1395```
1396 
1397**Correct: 1 decimal place**
1398 
1399```svg
1400<path d="M 10.3 20.8 L 30.9 40.2" />
1401```
1402 
1403**Automate with SVGO:**
1404 
1405```bash
1406npx svgo --precision=1 --multipass icon.svg
1407```
1408 
1409### 6.5 Prevent Hydration Mismatch Without Flickering
1410 
1411**Impact: MEDIUM (avoids visual flicker and hydration errors)**
1412 
1413When rendering content that depends on client-side storage (localStorage, cookies), avoid both SSR breakage and post-hydration flickering by injecting a synchronous script that updates the DOM before React hydrates.
1414 
1415**Incorrect: breaks SSR**
1416 
1417```tsx
1418function ThemeWrapper({ children }: { children: ReactNode }) {
1419 // localStorage is not available on server - throws error
1420 const theme = localStorage.getItem('theme') || 'light'
1421
1422 return (
1423 <div className={theme}>
1424 {children}
1425 </div>
1426 )
1427}
1428```
1429 
1430Server-side rendering will fail because `localStorage` is undefined.
1431 
1432**Incorrect: visual flickering**
1433 
1434```tsx
1435function ThemeWrapper({ children }: { children: ReactNode }) {
1436 const [theme, setTheme] = useState('light')
1437
1438 useEffect(() => {
1439 // Runs after hydration - causes visible flash
1440 const stored = localStorage.getItem('theme')
1441 if (stored) {
1442 setTheme(stored)
1443 }
1444 }, [])
1445
1446 return (
1447 <div className={theme}>
1448 {children}
1449 </div>
1450 )
1451}
1452```
1453 
1454Component first renders with default value (`light`), then updates after hydration, causing a visible flash of incorrect content.
1455 
1456**Correct: no flicker, no hydration mismatch**
1457 
1458```tsx
1459function ThemeWrapper({ children }: { children: ReactNode }) {
1460 return (
1461 <>
1462 <div id="theme-wrapper">
1463 {children}
1464 </div>
1465 <script
1466 dangerouslySetInnerHTML={{
1467 __html: `
1468 (function() {
1469 try {
1470 var theme = localStorage.getItem('theme') || 'light';
1471 var el = document.getElementById('theme-wrapper');
1472 if (el) el.className = theme;
1473 } catch (e) {}
1474 })();
1475 `,
1476 }}
1477 />
1478 </>
1479 )
1480}
1481```
1482 
1483The inline script executes synchronously before showing the element, ensuring the DOM already has the correct value. No flickering, no hydration mismatch.
1484 
1485This pattern is especially useful for theme toggles, user preferences, authentication states, and any client-only data that should render immediately without flashing default values.
1486 
1487### 6.6 Use Activity Component for Show/Hide
1488 
1489**Impact: MEDIUM (preserves state/DOM)**
1490 
1491Use React's `<Activity>` to preserve state/DOM for expensive components that frequently toggle visibility.
1492 
1493**Usage:**
1494 
1495```tsx
1496import { Activity } from 'react'
1497 
1498function Dropdown({ isOpen }: Props) {
1499 return (
1500 <Activity mode={isOpen ? 'visible' : 'hidden'}>
1501 <ExpensiveMenu />
1502 </Activity>
1503 )
1504}
1505```
1506 
1507Avoids expensive re-renders and state loss.
1508 
1509### 6.7 Use Explicit Conditional Rendering
1510 
1511**Impact: LOW (prevents rendering 0 or NaN)**
1512 
1513Use explicit ternary operators (`? :`) instead of `&&` for conditional rendering when the condition can be `0`, `NaN`, or other falsy values that render.
1514 
1515**Incorrect: renders "0" when count is 0**
1516 
1517```tsx
1518function Badge({ count }: { count: number }) {
1519 return (
1520 <div>
1521 {count && <span className="badge">{count}</span>}
1522 </div>
1523 )
1524}
1525 
1526// When count = 0, renders: <div>0</div>
1527// When count = 5, renders: <div><span class="badge">5</span></div>
1528```
1529 
1530**Correct: renders nothing when count is 0**
1531 
1532```tsx
1533function Badge({ count }: { count: number }) {
1534 return (
1535 <div>
1536 {count > 0 ? <span className="badge">{count}</span> : null}
1537 </div>
1538 )
1539}
1540 
1541// When count = 0, renders: <div></div>
1542// When count = 5, renders: <div><span class="badge">5</span></div>
1543```
1544 
1545---
1546 
1547## 7. JavaScript Performance
1548 
1549**Impact: LOW-MEDIUM**
1550 
1551Micro-optimizations for hot paths can add up to meaningful improvements.
1552 
1553### 7.1 Batch DOM CSS Changes
1554 
1555**Impact: MEDIUM (reduces reflows/repaints)**
1556 
1557Avoid changing styles one property at a time. Group multiple CSS changes together via classes or `cssText` to minimize browser reflows.
1558 
1559**Incorrect: multiple reflows**
1560 
1561```typescript
1562function updateElementStyles(element: HTMLElement) {
1563 // Each line triggers a reflow
1564 element.style.width = '100px'
1565 element.style.height = '200px'
1566 element.style.backgroundColor = 'blue'
1567 element.style.border = '1px solid black'
1568}
1569```
1570 
1571**Correct: add class - single reflow**
1572 
1573```typescript
1574// CSS file
1575.highlighted-box {
1576 width: 100px;
1577 height: 200px;
1578 background-color: blue;
1579 border: 1px solid black;
1580}
1581 
1582// JavaScript
1583function updateElementStyles(element: HTMLElement) {
1584 element.classList.add('highlighted-box')
1585}
1586```
1587 
1588**Correct: change cssText - single reflow**
1589 
1590```typescript
1591function updateElementStyles(element: HTMLElement) {
1592 element.style.cssText = `
1593 width: 100px;
1594 height: 200px;
1595 background-color: blue;
1596 border: 1px solid black;
1597 `
1598}
1599```
1600 
1601**React example:**
1602 
1603```tsx
1604// Incorrect: changing styles one by one
1605function Box({ isHighlighted }: { isHighlighted: boolean }) {
1606 const ref = useRef<HTMLDivElement>(null)
1607
1608 useEffect(() => {
1609 if (ref.current && isHighlighted) {
1610 ref.current.style.width = '100px'
1611 ref.current.style.height = '200px'
1612 ref.current.style.backgroundColor = 'blue'
1613 }
1614 }, [isHighlighted])
1615
1616 return <div ref={ref}>Content</div>
1617}
1618 
1619// Correct: toggle class
1620function Box({ isHighlighted }: { isHighlighted: boolean }) {
1621 return (
1622 <div className={isHighlighted ? 'highlighted-box' : ''}>
1623 Content
1624 </div>
1625 )
1626}
1627```
1628 
1629Prefer CSS classes over inline styles when possible. Classes are cached by the browser and provide better separation of concerns.
1630 
1631### 7.2 Build Index Maps for Repeated Lookups
1632 
1633**Impact: LOW-MEDIUM (1M ops to 2K ops)**
1634 
1635Multiple `.find()` calls by the same key should use a Map.
1636 
1637**Incorrect (O(n) per lookup):**
1638 
1639```typescript
1640function processOrders(orders: Order[], users: User[]) {
1641 return orders.map(order => ({
1642 ...order,
1643 user: users.find(u => u.id === order.userId)
1644 }))
1645}
1646```
1647 
1648**Correct (O(1) per lookup):**
1649 
1650```typescript
1651function processOrders(orders: Order[], users: User[]) {
1652 const userById = new Map(users.map(u => [u.id, u]))
1653 
1654 return orders.map(order => ({
1655 ...order,
1656 user: userById.get(order.userId)
1657 }))
1658}
1659```
1660 
1661Build map once (O(n)), then all lookups are O(1).
1662 
1663For 1000 orders × 1000 users: 1M ops → 2K ops.
1664 
1665### 7.3 Cache Property Access in Loops
1666 
1667**Impact: LOW-MEDIUM (reduces lookups)**
1668 
1669Cache object property lookups in hot paths.
1670 
1671**Incorrect: 3 lookups × N iterations**
1672 
1673```typescript
1674for (let i = 0; i < arr.length; i++) {
1675 process(obj.config.settings.value)
1676}
1677```
1678 
1679**Correct: 1 lookup total**
1680 
1681```typescript
1682const value = obj.config.settings.value
1683const len = arr.length
1684for (let i = 0; i < len; i++) {
1685 process(value)
1686}
1687```
1688 
1689### 7.4 Cache Repeated Function Calls
1690 
1691**Impact: MEDIUM (avoid redundant computation)**
1692 
1693Use a module-level Map to cache function results when the same function is called repeatedly with the same inputs during render.
1694 
1695**Incorrect: redundant computation**
1696 
1697```typescript
1698function ProjectList({ projects }: { projects: Project[] }) {
1699 return (
1700 <div>
1701 {projects.map(project => {
1702 // slugify() called 100+ times for same project names
1703 const slug = slugify(project.name)
1704
1705 return <ProjectCard key={project.id} slug={slug} />
1706 })}
1707 </div>
1708 )
1709}
1710```
1711 
1712**Correct: cached results**
1713 
1714```typescript
1715// Module-level cache
1716const slugifyCache = new Map<string, string>()
1717 
1718function cachedSlugify(text: string): string {
1719 if (slugifyCache.has(text)) {
1720 return slugifyCache.get(text)!
1721 }
1722 const result = slugify(text)
1723 slugifyCache.set(text, result)
1724 return result
1725}
1726 
1727function ProjectList({ projects }: { projects: Project[] }) {
1728 return (
1729 <div>
1730 {projects.map(project => {
1731 // Computed only once per unique project name
1732 const slug = cachedSlugify(project.name)
1733
1734 return <ProjectCard key={project.id} slug={slug} />
1735 })}
1736 </div>
1737 )
1738}
1739```
1740 
1741**Simpler pattern for single-value functions:**
1742 
1743```typescript
1744let isLoggedInCache: boolean | null = null
1745 
1746function isLoggedIn(): boolean {
1747 if (isLoggedInCache !== null) {
1748 return isLoggedInCache
1749 }
1750
1751 isLoggedInCache = document.cookie.includes('auth=')
1752 return isLoggedInCache
1753}
1754 
1755// Clear cache when auth changes
1756function onAuthChange() {
1757 isLoggedInCache = null
1758}
1759```
1760 
1761Use a Map (not a hook) so it works everywhere: utilities, event handlers, not just React components.
1762 
1763Reference: [https://vercel.com/blog/how-we-made-the-vercel-dashboard-twice-as-fast](https://vercel.com/blog/how-we-made-the-vercel-dashboard-twice-as-fast)
1764 
1765### 7.5 Cache Storage API Calls
1766 
1767**Impact: LOW-MEDIUM (reduces expensive I/O)**
1768 
1769`localStorage`, `sessionStorage`, and `document.cookie` are synchronous and expensive. Cache reads in memory.
1770 
1771**Incorrect: reads storage on every call**
1772 
1773```typescript
1774function getTheme() {
1775 return localStorage.getItem('theme') ?? 'light'
1776}
1777// Called 10 times = 10 storage reads
1778```
1779 
1780**Correct: Map cache**
1781 
1782```typescript
1783const storageCache = new Map<string, string | null>()
1784 
1785function getLocalStorage(key: string) {
1786 if (!storageCache.has(key)) {
1787 storageCache.set(key, localStorage.getItem(key))
1788 }
1789 return storageCache.get(key)
1790}
1791 
1792function setLocalStorage(key: string, value: string) {
1793 localStorage.setItem(key, value)
1794 storageCache.set(key, value) // keep cache in sync
1795}
1796```
1797 
1798Use a Map (not a hook) so it works everywhere: utilities, event handlers, not just React components.
1799 
1800**Cookie caching:**
1801 
1802```typescript
1803let cookieCache: Record<string, string> | null = null
1804 
1805function getCookie(name: string) {
1806 if (!cookieCache) {
1807 cookieCache = Object.fromEntries(
1808 document.cookie.split('; ').map(c => c.split('='))
1809 )
1810 }
1811 return cookieCache[name]
1812}
1813```
1814 
1815**Important: invalidate on external changes**
1816 
1817```typescript
1818window.addEventListener('storage', (e) => {
1819 if (e.key) storageCache.delete(e.key)
1820})
1821 
1822document.addEventListener('visibilitychange', () => {
1823 if (document.visibilityState === 'visible') {
1824 storageCache.clear()
1825 }
1826})
1827```
1828 
1829If storage can change externally (another tab, server-set cookies), invalidate cache:
1830 
1831### 7.6 Combine Multiple Array Iterations
1832 
1833**Impact: LOW-MEDIUM (reduces iterations)**
1834 
1835Multiple `.filter()` or `.map()` calls iterate the array multiple times. Combine into one loop.
1836 
1837**Incorrect: 3 iterations**
1838 
1839```typescript
1840const admins = users.filter(u => u.isAdmin)
1841const testers = users.filter(u => u.isTester)
1842const inactive = users.filter(u => !u.isActive)
1843```
1844 
1845**Correct: 1 iteration**
1846 
1847```typescript
1848const admins: User[] = []
1849const testers: User[] = []
1850const inactive: User[] = []
1851 
1852for (const user of users) {
1853 if (user.isAdmin) admins.push(user)
1854 if (user.isTester) testers.push(user)
1855 if (!user.isActive) inactive.push(user)
1856}
1857```
1858 
1859### 7.7 Early Length Check for Array Comparisons
1860 
1861**Impact: MEDIUM-HIGH (avoids expensive operations when lengths differ)**
1862 
1863When comparing arrays with expensive operations (sorting, deep equality, serialization), check lengths first. If lengths differ, the arrays cannot be equal.
1864 
1865In real-world applications, this optimization is especially valuable when the comparison runs in hot paths (event handlers, render loops).
1866 
1867**Incorrect: always runs expensive comparison**
1868 
1869```typescript
1870function hasChanges(current: string[], original: string[]) {
1871 // Always sorts and joins, even when lengths differ
1872 return current.sort().join() !== original.sort().join()
1873}
1874```
1875 
1876Two O(n log n) sorts run even when `current.length` is 5 and `original.length` is 100. There is also overhead of joining the arrays and comparing the strings.
1877 
1878**Correct (O(1) length check first):**
1879 
1880```typescript
1881function hasChanges(current: string[], original: string[]) {
1882 // Early return if lengths differ
1883 if (current.length !== original.length) {
1884 return true
1885 }
1886 // Only sort/join when lengths match
1887 const currentSorted = current.toSorted()
1888 const originalSorted = original.toSorted()
1889 for (let i = 0; i < currentSorted.length; i++) {
1890 if (currentSorted[i] !== originalSorted[i]) {
1891 return true
1892 }
1893 }
1894 return false
1895}
1896```
1897 
1898This new approach is more efficient because:
1899 
1900- It avoids the overhead of sorting and joining the arrays when lengths differ
1901 
1902- It avoids consuming memory for the joined strings (especially important for large arrays)
1903 
1904- It avoids mutating the original arrays
1905 
1906- It returns early when a difference is found
1907 
1908### 7.8 Early Return from Functions
1909 
1910**Impact: LOW-MEDIUM (avoids unnecessary computation)**
1911 
1912Return early when result is determined to skip unnecessary processing.
1913 
1914**Incorrect: processes all items even after finding answer**
1915 
1916```typescript
1917function validateUsers(users: User[]) {
1918 let hasError = false
1919 let errorMessage = ''
1920
1921 for (const user of users) {
1922 if (!user.email) {
1923 hasError = true
1924 errorMessage = 'Email required'
1925 }
1926 if (!user.name) {
1927 hasError = true
1928 errorMessage = 'Name required'
1929 }
1930 // Continues checking all users even after error found
1931 }
1932
1933 return hasError ? { valid: false, error: errorMessage } : { valid: true }
1934}
1935```
1936 
1937**Correct: returns immediately on first error**
1938 
1939```typescript
1940function validateUsers(users: User[]) {
1941 for (const user of users) {
1942 if (!user.email) {
1943 return { valid: false, error: 'Email required' }
1944 }
1945 if (!user.name) {
1946 return { valid: false, error: 'Name required' }
1947 }
1948 }
1949 
1950 return { valid: true }
1951}
1952```
1953 
1954### 7.9 Hoist RegExp Creation
1955 
1956**Impact: LOW-MEDIUM (avoids recreation)**
1957 
1958Don't create RegExp inside render. Hoist to module scope or memoize with `useMemo()`.
1959 
1960**Incorrect: new RegExp every render**
1961 
1962```tsx
1963function Highlighter({ text, query }: Props) {
1964 const regex = new RegExp(`(${query})`, 'gi')
1965 const parts = text.split(regex)
1966 return <>{parts.map((part, i) => ...)}</>
1967}
1968```
1969 
1970**Correct: memoize or hoist**
1971 
1972```tsx
1973const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
1974 
1975function Highlighter({ text, query }: Props) {
1976 const regex = useMemo(
1977 () => new RegExp(`(${escapeRegex(query)})`, 'gi'),
1978 [query]
1979 )
1980 const parts = text.split(regex)
1981 return <>{parts.map((part, i) => ...)}</>
1982}
1983```
1984 
1985**Warning: global regex has mutable state**
1986 
1987```typescript
1988const regex = /foo/g
1989regex.test('foo') // true, lastIndex = 3
1990regex.test('foo') // false, lastIndex = 0
1991```
1992 
1993Global regex (`/g`) has mutable `lastIndex` state:
1994 
1995### 7.10 Use Loop for Min/Max Instead of Sort
1996 
1997**Impact: LOW (O(n) instead of O(n log n))**
1998 
1999Finding the smallest or largest element only requires a single pass through the array. Sorting is wasteful and slower.
2000 
2001**Incorrect (O(n log n) - sort to find latest):**
2002 
2003```typescript
2004interface Project {
2005 id: string
2006 name: string
2007 updatedAt: number
2008}
2009 
2010function getLatestProject(projects: Project[]) {
2011 const sorted = [...projects].sort((a, b) => b.updatedAt - a.updatedAt)
2012 return sorted[0]
2013}
2014```
2015 
2016Sorts the entire array just to find the maximum value.
2017 
2018**Incorrect (O(n log n) - sort for oldest and newest):**
2019 
2020```typescript
2021function getOldestAndNewest(projects: Project[]) {
2022 const sorted = [...projects].sort((a, b) => a.updatedAt - b.updatedAt)
2023 return { oldest: sorted[0], newest: sorted[sorted.length - 1] }
2024}
2025```
2026 
2027Still sorts unnecessarily when only min/max are needed.
2028 
2029**Correct (O(n) - single loop):**
2030 
2031```typescript
2032function getLatestProject(projects: Project[]) {
2033 if (projects.length === 0) return null
2034
2035 let latest = projects[0]
2036
2037 for (let i = 1; i < projects.length; i++) {
2038 if (projects[i].updatedAt > latest.updatedAt) {
2039 latest = projects[i]
2040 }
2041 }
2042
2043 return latest
2044}
2045 
2046function getOldestAndNewest(projects: Project[]) {
2047 if (projects.length === 0) return { oldest: null, newest: null }
2048
2049 let oldest = projects[0]
2050 let newest = projects[0]
2051
2052 for (let i = 1; i < projects.length; i++) {
2053 if (projects[i].updatedAt < oldest.updatedAt) oldest = projects[i]
2054 if (projects[i].updatedAt > newest.updatedAt) newest = projects[i]
2055 }
2056
2057 return { oldest, newest }
2058}
2059```
2060 
2061Single pass through the array, no copying, no sorting.
2062 
2063**Alternative: Math.min/Math.max for small arrays**
2064 
2065```typescript
2066const numbers = [5, 2, 8, 1, 9]
2067const min = Math.min(...numbers)
2068const max = Math.max(...numbers)
2069```
2070 
2071This works for small arrays but can be slower for very large arrays due to spread operator limitations. Use the loop approach for reliability.
2072 
2073### 7.11 Use Set/Map for O(1) Lookups
2074 
2075**Impact: LOW-MEDIUM (O(n) to O(1))**
2076 
2077Convert arrays to Set/Map for repeated membership checks.
2078 
2079**Incorrect (O(n) per check):**
2080 
2081```typescript
2082const allowedIds = ['a', 'b', 'c', ...]
2083items.filter(item => allowedIds.includes(item.id))
2084```
2085 
2086**Correct (O(1) per check):**
2087 
2088```typescript
2089const allowedIds = new Set(['a', 'b', 'c', ...])
2090items.filter(item => allowedIds.has(item.id))
2091```
2092 
2093### 7.12 Use toSorted() Instead of sort() for Immutability
2094 
2095**Impact: MEDIUM-HIGH (prevents mutation bugs in React state)**
2096 
2097`.sort()` mutates the array in place, which can cause bugs with React state and props. Use `.toSorted()` to create a new sorted array without mutation.
2098 
2099**Incorrect: mutates original array**
2100 
2101```typescript
2102function UserList({ users }: { users: User[] }) {
2103 // Mutates the users prop array!
2104 const sorted = useMemo(
2105 () => users.sort((a, b) => a.name.localeCompare(b.name)),
2106 [users]
2107 )
2108 return <div>{sorted.map(renderUser)}</div>
2109}
2110```
2111 
2112**Correct: creates new array**
2113 
2114```typescript
2115function UserList({ users }: { users: User[] }) {
2116 // Creates new sorted array, original unchanged
2117 const sorted = useMemo(
2118 () => users.toSorted((a, b) => a.name.localeCompare(b.name)),
2119 [users]
2120 )
2121 return <div>{sorted.map(renderUser)}</div>
2122}
2123```
2124 
2125**Why this matters in React:**
2126 
21271. Props/state mutations break React's immutability model - React expects props and state to be treated as read-only
2128 
21292. Causes stale closure bugs - Mutating arrays inside closures (callbacks, effects) can lead to unexpected behavior
2130 
2131**Browser support: fallback for older browsers**
2132 
2133```typescript
2134// Fallback for older browsers
2135const sorted = [...items].sort((a, b) => a.value - b.value)
2136```
2137 
2138`.toSorted()` is available in all modern browsers (Chrome 110+, Safari 16+, Firefox 115+, Node.js 20+). For older environments, use spread operator:
2139 
2140**Other immutable array methods:**
2141 
2142- `.toSorted()` - immutable sort
2143 
2144- `.toReversed()` - immutable reverse
2145 
2146- `.toSpliced()` - immutable splice
2147 
2148- `.with()` - immutable element replacement
2149 
2150---
2151 
2152## 8. Advanced Patterns
2153 
2154**Impact: LOW**
2155 
2156Advanced patterns for specific cases that require careful implementation.
2157 
2158### 8.1 Store Event Handlers in Refs
2159 
2160**Impact: LOW (stable subscriptions)**
2161 
2162Store callbacks in refs when used in effects that shouldn't re-subscribe on callback changes.
2163 
2164**Incorrect: re-subscribes on every render**
2165 
2166```tsx
2167function useWindowEvent(event: string, handler: () => void) {
2168 useEffect(() => {
2169 window.addEventListener(event, handler)
2170 return () => window.removeEventListener(event, handler)
2171 }, [event, handler])
2172}
2173```
2174 
2175**Correct: stable subscription**
2176 
2177```tsx
2178import { useEffectEvent } from 'react'
2179 
2180function useWindowEvent(event: string, handler: () => void) {
2181 const onEvent = useEffectEvent(handler)
2182 
2183 useEffect(() => {
2184 window.addEventListener(event, onEvent)
2185 return () => window.removeEventListener(event, onEvent)
2186 }, [event])
2187}
2188```
2189 
2190**Alternative: use `useEffectEvent` if you're on latest React:**
2191 
2192`useEffectEvent` provides a cleaner API for the same pattern: it creates a stable function reference that always calls the latest version of the handler.
2193 
2194### 8.2 useLatest for Stable Callback Refs
2195 
2196**Impact: LOW (prevents effect re-runs)**
2197 
2198Access latest values in callbacks without adding them to dependency arrays. Prevents effect re-runs while avoiding stale closures.
2199 
2200**Implementation:**
2201 
2202```typescript
2203function useLatest<T>(value: T) {
2204 const ref = useRef(value)
2205 useEffect(() => {
2206 ref.current = value
2207 }, [value])
2208 return ref
2209}
2210```
2211 
2212**Incorrect: effect re-runs on every callback change**
2213 
2214```tsx
2215function SearchInput({ onSearch }: { onSearch: (q: string) => void }) {
2216 const [query, setQuery] = useState('')
2217 
2218 useEffect(() => {
2219 const timeout = setTimeout(() => onSearch(query), 300)
2220 return () => clearTimeout(timeout)
2221 }, [query, onSearch])
2222}
2223```
2224 
2225**Correct: stable effect, fresh callback**
2226 
2227```tsx
2228function SearchInput({ onSearch }: { onSearch: (q: string) => void }) {
2229 const [query, setQuery] = useState('')
2230 const onSearchRef = useLatest(onSearch)
2231 
2232 useEffect(() => {
2233 const timeout = setTimeout(() => onSearchRef.current(query), 300)
2234 return () => clearTimeout(timeout)
2235 }, [query])
2236}
2237```
2238 
2239---
2240 
2241## References
2242 
22431. [https://react.dev](https://react.dev)
22442. [https://nextjs.org](https://nextjs.org)
22453. [https://swr.vercel.app](https://swr.vercel.app)
22464. [https://github.com/shuding/better-all](https://github.com/shuding/better-all)
22475. [https://github.com/isaacs/node-lru-cache](https://github.com/isaacs/node-lru-cache)
22486. [https://vercel.com/blog/how-we-optimized-package-imports-in-next-js](https://vercel.com/blog/how-we-optimized-package-imports-in-next-js)
22497. [https://vercel.com/blog/how-we-made-the-vercel-dashboard-twice-as-fast](https://vercel.com/blog/how-we-made-the-vercel-dashboard-twice-as-fast)
2250 

Commands it names

  • npx svgo --precision=1 --multipass icon.svg

Sections

  • React Best Practices
  • Abstract
  • Table of Contents
  • 1. Eliminating Waterfalls
  • 1.1 Defer Await Until Needed
  • 1.2 Dependency-Based Parallelization
  • 1.3 Prevent Waterfall Chains in API Routes
  • 1.4 Promise.all() for Independent Operations
  • 1.5 Strategic Suspense Boundaries
  • 2. Bundle Size Optimization
  • 2.1 Avoid Barrel File Imports
  • 2.2 Conditional Module Loading
  • 2.3 Defer Non-Critical Third-Party Libraries
  • 2.4 Dynamic Imports for Heavy Components
  • 2.5 Preload Based on User Intent
  • 3. Server-Side Performance
  • 3.1 Cross-Request LRU Caching
  • 3.2 Minimize Serialization at RSC Boundaries
  • 3.3 Parallel Data Fetching with Component Composition
  • 3.4 Per-Request Deduplication with React.cache()
  • 3.5 Use after() for Non-Blocking Operations
  • 4. Client-Side Data Fetching
  • 4.1 Deduplicate Global Event Listeners
  • 4.2 Use SWR for Automatic Deduplication
  • 5. Re-render Optimization
  • 5.1 Defer State Reads to Usage Point
  • 5.2 Extract to Memoized Components
  • 5.3 Narrow Effect Dependencies
  • 5.4 Subscribe to Derived State
  • 5.5 Use Functional setState Updates
  • 5.6 Use Lazy State Initialization
  • 5.7 Use Transitions for Non-Urgent Updates
  • 6. Rendering Performance
  • 6.1 Animate SVG Wrapper Instead of SVG Element
  • 6.2 CSS content-visibility for Long Lists
  • 6.3 Hoist Static JSX Elements
  • 6.4 Optimize SVG Precision
  • 6.5 Prevent Hydration Mismatch Without Flickering
  • 6.6 Use Activity Component for Show/Hide
  • 6.7 Use Explicit Conditional Rendering
  • 7. JavaScript Performance
  • 7.1 Batch DOM CSS Changes
  • 7.2 Build Index Maps for Repeated Lookups
  • 7.3 Cache Property Access in Loops
  • 7.4 Cache Repeated Function Calls
  • 7.5 Cache Storage API Calls
  • 7.6 Combine Multiple Array Iterations
  • 7.7 Early Length Check for Array Comparisons
  • 7.8 Early Return from Functions
  • 7.9 Hoist RegExp Creation
  • 7.10 Use Loop for Min/Max Instead of Sort
  • 7.11 Use Set/Map for O(1) Lookups
  • 7.12 Use toSorted() Instead of sort() for Immutability
  • 8. Advanced Patterns
  • 8.1 Store Event Handlers in Refs
  • 8.2 useLatest for Stable Callback Refs
  • References

What it covers

buildlint-formatcode-styledependenciesapiuiperformancedo-not

Stack — with the evidence

node

(0.95)

python

(0.80)

react

(0.70)

fastapi

(0.70)

supabase

(0.70)

tailwind

(0.70)

vite

(0.70)

vitest

(0.70)

eslint

(0.70)

typescript

(0.60)

javascript

(0.60)

github-actions

(0.60)

Format

AGENTS.md

A plain-markdown README for coding agents, deliberately unopinionated: no frontmatter, no globs, no vendor keys. That minimalism is why it became the one file a dozen different agents will read, and why it carries the least per-file targeting power of any format here.

What the corpus says about it

Repository

Owner
sickn33
Language
—
License
—
Archived
no

All configs in this repo

Also in sickn33/agentic-awesome-skills

Diff this repo’s formats

One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?

The other instruction files in this repository
RepositoryFormatStackCoversScoreChanged
sickn33/agentic-awesome-skillsAGENTS.md · 44kAGENTS.mdnodepython+10buildteststylearch+390/1003 days ago
sickn33/agentic-awesome-skillsplugins/agentic-awesome-skills-claude/skills/dbos-golang/AGENTS.md · 44kAGENTS.mdpythonnode+10arch54/1003 days ago
sickn33/agentic-awesome-skillsplugins/agentic-awesome-skills-claude/skills/dbos-golang/CLAUDE.md · 44kCLAUDE.mdpythonnode+10arch54/1003 days ago
sickn33/agentic-awesome-skillsplugins/agentic-awesome-skills-claude/skills/dbos-python/AGENTS.md · 44kAGENTS.mdpythonnode+10arch54/1003 days ago
sickn33/agentic-awesome-skillsplugins/agentic-awesome-skills-claude/skills/dbos-python/CLAUDE.md · 44kCLAUDE.mdpythonnode+10arch54/1003 days ago
sickn33/agentic-awesome-skillsplugins/agentic-awesome-skills-claude/skills/dbos-typescript/AGENTS.md · 44kAGENTS.mdpythonnode+10archtypes54/1003 days ago
sickn33/agentic-awesome-skillsplugins/agentic-awesome-skills-claude/skills/dbos-typescript/CLAUDE.md · 44kCLAUDE.mdpythonnode+10archtypes54/1003 days ago
sickn33/agentic-awesome-skillsplugins/agentic-awesome-skills-claude/skills/loki-mode/CLAUDE.md · 44kCLAUDE.mdpythonnode+10testlint-formatstylearch+577/1003 days ago
sickn33/agentic-awesome-skillsplugins/agentic-awesome-skills-claude/skills/react-best-practices/AGENTS.md · 44kAGENTS.mdnodepython+10buildlint-formatstyledependencies+461/1003 days ago
sickn33/agentic-awesome-skillsplugins/agentic-awesome-skills/skills/dbos-golang/AGENTS.md · 44kAGENTS.mdpythonnode+10arch54/1003 days ago
sickn33/agentic-awesome-skillsplugins/agentic-awesome-skills/skills/dbos-golang/CLAUDE.md · 44kCLAUDE.mdpythonnode+10arch54/1003 days ago
sickn33/agentic-awesome-skillsplugins/agentic-awesome-skills/skills/dbos-python/AGENTS.md · 44kAGENTS.mdpythonnode+10arch54/1003 days ago
sickn33/agentic-awesome-skillsplugins/agentic-awesome-skills/skills/dbos-python/CLAUDE.md · 44kCLAUDE.mdpythonnode+10arch54/1003 days ago
sickn33/agentic-awesome-skillsplugins/agentic-awesome-skills/skills/dbos-typescript/AGENTS.md · 44kAGENTS.mdpythonnode+10archtypes54/1003 days ago
sickn33/agentic-awesome-skillsplugins/agentic-awesome-skills/skills/dbos-typescript/CLAUDE.md · 44kCLAUDE.mdpythonnode+10archtypes54/1003 days ago
sickn33/agentic-awesome-skillsplugins/agentic-awesome-skills/skills/postgres-best-practices/AGENTS.md · 44kAGENTS.mdnodepython+10styletypessecuritydatabase+345/1003 days ago
sickn33/agentic-awesome-skillsplugins/agentic-awesome-skills/skills/react-best-practices/AGENTS.md · 44kAGENTS.mdnodepython+10buildlint-formatstyledependencies+461/1003 days ago
sickn33/agentic-awesome-skillsplugins/agentic-bundle-aas-data-analytics/skills/postgres-best-practices/AGENTS.md · 44kAGENTS.mdnodepython+10styletypessecuritydatabase+345/1003 days ago
sickn33/agentic-awesome-skillsplugins/agentic-bundle-aas-data-engineering-platform/skills/postgres-best-practices/AGENTS.md · 44kAGENTS.mdnodepython+10styletypessecuritydatabase+345/1003 days ago
sickn33/agentic-awesome-skillsplugins/agentic-bundle-data-analytics/skills/postgres-best-practices/AGENTS.md · 44kAGENTS.mdnodepython+10styletypessecuritydatabase+345/1003 days ago
Diff against AGENTS.md Diff against plugins/agentic-awesome-skills-claude/skills/dbos-golang/AGENTS.md Diff against plugins/agentic-awesome-skills-claude/skills/dbos-golang/CLAUDE.md Diff against plugins/agentic-awesome-skills-claude/skills/dbos-python/AGENTS.md Diff against plugins/agentic-awesome-skills-claude/skills/dbos-python/CLAUDE.md Diff against plugins/agentic-awesome-skills-claude/skills/dbos-typescript/AGENTS.md Diff against plugins/agentic-awesome-skills-claude/skills/dbos-typescript/CLAUDE.md Diff against plugins/agentic-awesome-skills-claude/skills/loki-mode/CLAUDE.md Diff against plugins/agentic-awesome-skills-claude/skills/react-best-practices/AGENTS.md Diff against plugins/agentic-awesome-skills/skills/dbos-golang/AGENTS.md Diff against plugins/agentic-awesome-skills/skills/dbos-golang/CLAUDE.md Diff against plugins/agentic-awesome-skills/skills/dbos-python/AGENTS.md Diff against plugins/agentic-awesome-skills/skills/dbos-python/CLAUDE.md Diff against plugins/agentic-awesome-skills/skills/dbos-typescript/AGENTS.md Diff against plugins/agentic-awesome-skills/skills/dbos-typescript/CLAUDE.md Diff against plugins/agentic-awesome-skills/skills/postgres-best-practices/AGENTS.md Diff against plugins/agentic-awesome-skills/skills/react-best-practices/AGENTS.md Diff against plugins/agentic-bundle-aas-data-analytics/skills/postgres-best-practices/AGENTS.md Diff against plugins/agentic-bundle-aas-data-engineering-platform/skills/postgres-best-practices/AGENTS.md Diff against plugins/agentic-bundle-data-analytics/skills/postgres-best-practices/AGENTS.md

Similar configs

Same format, overlapping stack, ranked by quality.

Same format, overlapping stack, ranked by quality
RepositoryFormatStackCoversScoreChanged
OnlyTerp/prompt-cache-skillsAGENTS.md · 112AGENTS.mdpythongithub-actionssetupbuildtestlint-format+5100/1003 days ago
vllm-project/vllmAGENTS.md · 88kAGENTS.mdpythonpytorch+3setuptestlint-formatstyle+5100/1003 days ago
SkeneTechnologies/skene-cookbookAGENTS.md · 51AGENTS.mdpythoneslint+4setupbuildtestlint-format+7100/1002 days ago
duckduckgo/content-scope-scriptsspecial-pages/AGENTS.md · 70AGENTS.mdtypescriptjavascript+5buildteststylearch+3100/1003 days ago
mui/material-uiAGENTS.md · 99kAGENTS.mdtypescriptjavascript+13setupbuildtestlint-format+9100/1003 days ago
n8n-io/n8npackages/@n8n/agents/AGENTS.md · 199kAGENTS.mdtypescriptlangchain+16buildteststylearch+3100/1003 days ago
trick77/agents-md-syncAGENTS.md · 2AGENTS.mdtypescriptnode+4setupbuildteststyle+5100/1003 days ago
TryGhost/Ghoste2e/AGENTS.md · 55kAGENTS.mdtypescriptjavascript+12setupteststylearch+2100/1003 days ago
RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack