nextjs_specialist
Next.js 15 App Router, Server Components, SSR/SSG optimizasyonu ve modern Next.js best practices.
npxskills add vuralserhat86/antigravity-agentic-skills--skill nextjs_specialistLoading…
Next.js 15 App Router, Server Components, SSR/SSG optimizasyonu ve modern Next.js best practices.
npxskills add vuralserhat86/antigravity-agentic-skills--skill nextjs_specialistLoading…
Next.js 15 App Router ve Server Components rehberi.
app/
├── layout.tsx # Root layout
├── page.tsx # Home page (/)
├── loading.tsx # Loading UI
├── error.tsx # Error boundary
├── not-found.tsx # 404 page
├── globals.css
│
├── (marketing)/ # Route group (URL'de görünmez)
│ ├── about/
│ │ └── page.tsx # /about
│ └── contact/
│ └── page.tsx # /contact
│
├── dashboard/
│ ├── layout.tsx # Nested layout
│ ├── page.tsx # /dashboard
│ └── settings/
│ └── page.tsx # /dashboard/settings
│
├── blog/
│ ├── page.tsx # /blog
│ └── [slug]/
│ └── page.tsx # /blog/:slug (dynamic)
│
└── api/
└── users/
└── route.ts # API route
| Dosya | Amaç |
|---|---|
layout.tsx | Shared layout, state korunur |
page.tsx | Unique route content |
loading.tsx | Suspense fallback |
error.tsx | Error boundary |
not-found.tsx | 404 handler |
route.ts | API endpoint |
// app/users/page.tsx
// ✅ Server Component - 'use client' yok
async function UsersPage() {
const users = await db.users.findMany(); // Direkt DB erişimi
return (
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
export default UsersPage;
'use client'; // ⚠️ Dosyanın en üstünde
import { useState } from 'react';
export function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(c => c + 1)}>
Count: {count}
</button>
);
}
// Server Component
import { Counter } from './Counter'; // Client Component
async function Dashboard() {
const data = await fetchData(); // Server'da çalışır
return (
<div>
<h1>{data.title}</h1>
<Counter /> {/* Client Component */}
</div>
);
}
| Server Component | Client Component |
|---|---|
| Data fetching | Interactivity (onClick, onChange) |
| Backend erişimi | Browser API (localStorage) |
| Sensitive logic | Hooks (useState, useEffect) |
| Büyük dependencies | Event listeners |
// Otomatik cache
async function Page() {
const res = await fetch('https://api.example.com/data');
const data = await res.json();
return <div>{data.title}</div>;
}
// Cache control
const res = await fetch(url, {
cache: 'force-cache', // Default - cache
// cache: 'no-store', // Her request'te fresh
// next: { revalidate: 60 }, // ISR - 60 saniye
});
// app/actions.ts
'use server';
export async function createUser(formData: FormData) {
const name = formData.get('name');
await db.users.create({ data: { name } });
revalidatePath('/users');
}
// app/users/page.tsx
import { createUser } from './actions';
export default function Page() {
return (
<form action={createUser}>
<input name="name" />
<button type="submit">Create</button>
</form>
);
}
// Default - build time'da generate
export default function Page() {
return <h1>Static Page</h1>;
}
// Dynamic segments için
export async function generateStaticParams() {
const posts = await getPosts();
return posts.map(post => ({ slug: post.slug }));
}
// Her request'te render
export const dynamic = 'force-dynamic';
export default async function Page() {
const data = await fetchRealTimeData();
return <div>{data.value}</div>;
}
export const revalidate = 60; // 60 saniye
export default async function Page() {
const data = await fetchData();
return <div>{data.value}</div>;
}
import Image from 'next/image';
<Image
src="/hero.jpg"
alt="Hero"
width={1200}
height={600}
priority // LCP için
placeholder="blur"
blurDataURL="data:image/..."
/>
// app/layout.tsx
import { Inter } from 'next/font/google';
const inter = Inter({
subsets: ['latin'],
display: 'swap',
});
export default function Layout({ children }) {
return (
<html className={inter.className}>
<body>{children}</body>
</html>
);
}
// Static
export const metadata = {
title: 'My App',
description: 'App description',
};
// Dynamic
export async function generateMetadata({ params }) {
const post = await getPost(params.slug);
return {
title: post.title,
openGraph: { images: [post.image] },
};
}
app/
├── @modal/
│ └── login/page.tsx
├── @sidebar/
│ └── page.tsx
└── layout.tsx
// layout.tsx
export default function Layout({ children, modal, sidebar }) {
return (
<>
{sidebar}
{children}
{modal}
</>
);
}
Next.js Specialist v1.1 - Enhanced
Kaynak: Next.js App Router Documentation & Vercel Security Guide
useState, onClick) gereken yaprak (leaf) nodları Client Component yap.Suspense sınırlarını belirle ve loading.tsx dosyalarını oluştur.Promise.all kullan).auth() çağır).next/image kullan ve sizes prop'unu doğru ayarla.next/font ile fontları optimize et (Layout shift'i önler).next/script ve strategy="lazyOnload" ile yükle.| Aşama | Doğrulama |
|---|---|
| 1 | "Hydration Error" alıyor musun? (Server/Client HTML uyuşmazlığı) |
| 2 | LCP (Largest Contentful Paint) < 2.5s mi? |
| 3 | Hassas veriler (API Key) Client bundle'a sızıyor mu? |
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Set up and use 1Password CLI (op). Use when installing the CLI, enabling desktop app integration, signing in (single or multi-account), or reading/injecting/running secrets via op.
CLI to manage emails via IMAP/SMTP. Use `himalaya` to list, read, write, reply, forward, search, and organize emails from the terminal. Supports multiple accounts and message composition with MML (MIME Meta Language).
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Set up and use 1Password CLI (op). Use when installing the CLI, enabling desktop app integration, signing in (single or multi-account), or reading/injecting/running secrets via op.
CLI to manage emails via IMAP/SMTP. Use `himalaya` to list, read, write, reply, forward, search, and organize emails from the terminal. Supports multiple accounts and message composition with MML (MIME Meta Language).