Rules
Öne çıkan·v1.0.0·2026-04-22React / Next.js Kuralları
Modern React 19 + Next.js (App Router) projeleri için kural seti — Server Component default, state hiyerarşisi, erişilebilirlik, performans bütçesi, form & data fetching disiplini. CLAUDE.md / .cursorrules için.
reactnextjsfrontendapp-routerrscrulesclaude-md
İçerik
Bu içeriği projenin CLAUDE.md / AGENTS.md / .cursorrules dosyasına yapıştır.
React / Next.js Kuralları
Server-first varsayılan
- Default: Server Component (RSC). Interactivity gerekmedikçe
"use client"yazma. "use client"kullanma kriterleri:useState,useReducer,useEffect, event handler, browser API, context consumer.- Hook içermeyen JSX + statik data = Server Component.
"use client"kopyala-yapıştır alışkanlığı yasak. - Client bundle'ına gereksiz kod girmesin:
lib/client/velib/server/ayrımı net.
Data fetching hiyerarşisi
Sırayla dene:
- Server Component + direct fetch / DB — en basit, zero client JS
- Server Action — form POST, mutation
- Route Handler (
route.ts) — API endpoint gerekliyse - React Query / SWR — gerçekten client-side polling, cache invalidation, optimistic update gerekliyse
useEffect+ fetch — son çare, neredeyse hiç
useEffect içinde data fetching yasak (race condition, loading state yönetimi, cleanup kabusu).
State hiyerarşisi
- Türetilebiliyorsa türet — yeni state oluşturma
- Server state (RSC, React Query cache) — kaynak tek nokta
- URL state — filter, search, modal open, page number (query params)
- Cookie / localStorage — session, tercihler
- Context — yavaş değişen global (theme, auth user, locale)
- Local
useState— son çare
Kural: yukarı taşınması gerekmeyen state'i aşağıda tut, aşağı indirilemeyeni yukarıya taşıma.
Component yapısı
- Component adı
PascalCase, dosya adı aynı (UserCard.tsx).index.tsxyok. - Props
UserCardPropsolarak export edilir. - Ref forwarding (
React.forwardRef) lazım olduğunda — her bileşene default eklenmiş değil. - 100 satırı geçen component mutlaka parçalanır.
- JSX içinde business logic yok — ya hook'a ya üst fonksiyona çıkar.
Server Component → Client Component prop geçişi
- Serializable olmak zorunda. Fonksiyon, class instance, Date (yes ama transform edilir), Map/Set → hayır.
- Event handler client-only, server'dan client'a geçirilemez. Çözüm: Server Action pass (
action={fn}). - Async component'i client'tan çağırma — sadece server → client yönü.
Form kuralları
- Server Action varsayılan.
action={serverAction}→ progressive enhancement + JS-less fallback. - React Hook Form + Zod karmaşık form / optimistic feedback gerektiğinde.
- Validation schema paylaşılır: client + server aynı Zod schema'yı kullanır.
formDataAPI'sini öğren — Object.fromEntries'a gerek yok, Zod ile direkt parse.- Submit sırasında button disable — double submit yasak.
Erişilebilirlik (a11y)
- Semantik HTML önce:
<button>,<a>,<nav>,<main>,<article>,<form>,<label>. <div onClick>yasak. İnteraktif element native tag ile yapılır.- ARIA sadece semantik HTML yetmediğinde. Yanlış ARIA → hiç ARIA'dan kötü.
- Her input'un görünür label'ı var. Placeholder label değildir.
- Klavye navigasyonu: Tab, Shift+Tab, Enter/Space, Escape. Her akış klavyeyle tamamlanabilir.
- Focus visible:
focus-visible:ring-2gibi bir pattern projede var. - Dinamik içerik:
aria-live="polite"status update için. - Renk kontrastı WCAG AA minimum: 4.5:1 normal metin, 3:1 büyük metin / UI.
Performans bütçesi
Core Web Vitals hedefleri:
- LCP < 2.5s
- INP < 200ms
- CLS < 0.1
Pratik kurallar
- Image:
next/imageher zaman.<img>sadece çok özel durumda, gerekçe ile. - Font:
next/font+display: swap. Sistem font'u fallback. - Third-party script:
next/script+strategy="afterInteractive"(veyalazyOnload). - Code split:
dynamic()ile ağır bileşenler (modal, chart, WYSIWYG editor). Suspenseboundary ağır veri fetch için.usehook (React 19) server component'te promise unwrap.- Bundle analiz:
ANALYZE=true next builddüzenli. - Initial JS budget: 150KB gzip üstü PR'da gerekçelenir.
Styling
- Tailwind CSS projesiyse utility-first kalır.
className="..."uzun string'ler okunaklı olsun (satır bölme + sıralama). - CSS-in-JS runtime (styled-components, emotion) yeni kodda yasak — RSC uyumu yok. CSS Modules veya vanilla-extract alternatif.
- Inline
stylesadece dinamik hesaplanmış değerler için (computed color, position). !importantyasak — specificity patlatma, design token ve cascade ile çöz.
Routing
- App Router kullanılır (Pages Router yok / migrate edildi).
- Route groups (
(marketing),(app)) yapıyı bölmek için. - Loading / error / not-found dosyaları her segment için düşünülür.
- Parallel & intercepted routes karmaşıklık ekler — gerçekten gerekli mi diye sor.
paramsPromise (Next 15+) —await params.
Caching
fetch()default cache: projenin tipine göre karar verilir (Next 15 default = no-cache).revalidateroute-level veya fetch-level — her ikisi bilinçli.revalidatePath/revalidateTagmutation sonrası.cachefunction (Reactcache()) sunucu tarafı request memoization için.
Error handling
- Route segment
error.tsx— runtime hata boundary'si. - Global error.tsx root'ta.
notFound()404 için (App Router).- Try/catch ile server action'da structured error response döner.
Env variables
NEXT_PUBLIC_*prefix'i client'a sızar — sır bilgi asla.- Zod ile validate:
env.tsstart-up'ta parse, runtime'daenv.XYZimport edilir. process.env.FOOdoğrudan kullanımı code review'da red flag.
Paketleme
- Monorepo'ysa Turborepo / Nx ile cache + paralel build.
packageJson.exportsyazılır (tree-shaking).sideEffects: falseuygunsa.
Test
- Unit: saf fonksiyonlar, hook'lar (
@testing-library/react-hooks). - Component: Testing Library +
userEvent. Implementation detail test etme (getByRole,getByLabelText>querySelector). - E2E: Playwright. Kritik yol: login → ana aksiyon → logout.
- Visual regression: Storybook + Chromatic (opsiyonel, projede kullanılıyorsa).
Yasak listesi (özet)
<div onClick>useEffectiçinde fetchkey={index}stable ID yokkendangerouslySetInnerHTMLyorumsuz"use client"hook'suz dosyadaNEXT_PUBLIC_ile hassas secret<img>yerinenext/imageseçeneği olduğu yerde<img>React.FC<Props>- Placeholder'ı label olarak kullanmak
- Pages Router (App Router migrate edildi varsayılıyor)
- CSS-in-JS runtime kütüphane yeni kodda
z-index: 9999— scale kullan- Global CSS'te
!important
Commit
Conventional Commits + "neden". feat(ui/button): ..., fix(forms): ....