Backend tarafında Clean Architecture'a verdiğim önemi, frontend projelerinde de benzer bir disiplinle kurmaya çalışıyorum. React ve Next.js ile çalışırken, projenin küçükken kolay göründüğü ama büyüdükçe dağınıklaşan noktaları önceden öngörüp, baştan sağlam bir klasör ve katman yapısı kurmayı önemsiyorum. Bu yazıda kurumsal ölçekli bir Next.js projesinde kullandığım yapıyı paylaşıyorum.
Neden Next.js?
Saf React yerine Next.js'i tercih etmemin temel sebebi, sunucu tarafı render (SSR) ve statik üretim (SSG) seçeneklerini aynı framework içinde sunması. Kurumsal bir web sitesinde SEO ve ilk yükleme performansı kritik olduğu için, App Router ile Server Component'leri varsayılan olarak kullanıp, sadece etkileşim gerektiren (form, buton, state yönetimi) yerlerde Client Component'e geçiyorum. Bu ayrım, hem bundle boyutunu küçültüyor hem de sayfanın ilk gösterimini hızlandırıyor.
Klasör Yapısı: Feature-Based Organizasyon
Küçük projelerde components/, pages/ gibi teknik türe göre klasörleme yeterli olabiliyor, ama proje büyüdükçe bu yapı "hangi dosya hangi özelliğe ait?" sorusunu zorlaştırıyor. Bunun yerine özellik bazlı (feature-based) bir yapı kullanıyorum:
src/
features/
orders/
components/
hooks/
api.ts
types.ts
users/
components/
hooks/
api.ts
shared/
ui/
lib/
Bu sayede bir özelliği kaldırmak ya da başka bir projeye taşımak istediğimde, ilgili her şey tek bir klasörde duruyor.
Veri Katmanı ve API İletişimi
API çağrılarını component içine doğrudan yazmak yerine, her feature'ın kendi api.ts dosyasında topluyorum ve component'ler sadece bu fonksiyonları çağırıyor. React Query (TanStack Query) kullanarak sunucu durumunu (server state) yönetiyorum; bu sayede loading/error/cache mantığını her component'te tekrar tekrar yazmak zorunda kalmıyorum.
function useOrders() {
return useQuery({
queryKey: ['orders'],
queryFn: () => fetchOrders(),
staleTime: 60_000,
});
}
Tip Güvenliği ve API Sözleşmesi
Backend'im ASP.NET Core olduğunda, API'nin döndürdüğü DTO'larla frontend'teki TypeScript tiplerinin senkron kalması önemli bir sorun. Mümkün olduğunda backend'in OpenAPI/Swagger şemasından TypeScript tiplerini otomatik üretiyorum; bu, elle yazılan tiplerin zamanla API'den sapmasını engelliyor.
Ne Zaman Bu Kadar Yapı Kurmaya Değer?
Tek sayfalık bir landing page için bu kadar katman kurmuyorum elbette. Ama birden fazla geliştiricinin çalışacağı, aylarca yaşayacak bir ürün söz konusu olduğunda, baştan kurulan bu düzen, altı ay sonra "bu kodu nereye yazmalıyım?" sorusuna harcanan zamanı ciddi şekilde azaltıyor.
Sonuç
React ve Next.js ekosisteminde de aynı prensip geçerli: sınırları net çizmek. Server/Client Component ayrımı, feature-based klasörleme ve tip güvenli bir API sözleşmesi, projeyi büyüdükçe kırılgan hale getirmek yerine öngörülebilir tutuyor.