with one click
nextjs-15-specialist
Use when working with Next.js 15 features, App Router, Server Components, Server Actions, or data fetching patterns. Ensures correct usage of Server vs Client Components and modern Next.js patterns.
Menu
Use when working with Next.js 15 features, App Router, Server Components, Server Actions, or data fetching patterns. Ensures correct usage of Server vs Client Components and modern Next.js patterns.
Professional frontend standards for building, scaffolding, extending, or reviewing any UI or frontend project — new or existing — even when standards aren't explicitly asked for. Keeps generated code consistent, reusable, secure, and production-quality. Framework-agnostic: React, Vue, Angular, Svelte, plain JS.
发布本地生成的 HTML、Markdown、TXT、PDF、Word 或 PPTX 到 ShareOne 平台,生成公网分享短链接;或者当用户提供 ShareOne 链接并要求下载文件、修改文件、拉取/处理评论时使用此技能。当用户要求“发布”、“分享”、“生成链接”、“上线”,或者“下载这个链接的文件”、“修改这个 ShareOne 链接的内容”、“拉取这个链接的评论”时,必须使用此技能。
Generate AI chat completions using GPT-4o through the verging.ai proxy API with streaming (SSE) and non-streaming response support.
Convert text to speech audio using OpenAI TTS-1-HD through the verging.ai proxy API. Supports multiple voices, playback speed control, and various audio output formats.
Generate AI images using DALL-E 3 or gpt-image-1 through the verging.ai proxy API. Supports standard and HD quality, multiple images per request, and returns CDN-hosted image URLs.
Analyze images using GPT-4o Vision through the verging.ai proxy API, supporting both image URL (JSON) and file upload (multipart) modes.
| name | nextjs-15-specialist |
| description | Use when working with Next.js 15 features, App Router, Server Components, Server Actions, or data fetching patterns. Ensures correct usage of Server vs Client Components and modern Next.js patterns. |
| allowed-tools | Read, Grep, Glob, WebFetch |
Complete Next.js 15 reference for Quetrex development.
This skill provides comprehensive guidance on all Next.js 15 App Router patterns, ensuring agents implement modern Next.js correctly the first time.
These rules are NON-NEGOTIABLE. Violations will break builds.
<Image> from next/image - NEVER use <img>// ✅ ALWAYS DO THIS
import Image from 'next/image'
<Image src="/logo.png" alt="Logo" width={200} height={100} />
<Image src={user.avatar} alt={user.name} width={40} height={40} />
// ❌ NEVER DO THIS - BUILD WILL FAIL
<img src="/logo.png" alt="Logo" />
<img src={user.avatar} alt={user.name} />
Why: Next.js Image component provides automatic optimization, lazy loading, and prevents layout shift. ESLint is configured to fail builds on <img> usage.
Use this skill when working with:
This skill includes comprehensive guides covering every Next.js 15 pattern:
45+ examples covering:
35+ examples covering:
35+ examples covering:
31+ examples covering:
26+ examples covering:
Executable Python script that checks:
Run with: python validate-patterns.py /path/to/src
Do you need interactivity (onClick, onChange, etc.)?
├─ YES → Client Component ('use client')
└─ NO → Server Component (default)
Do you need React hooks (useState, useEffect)?
├─ YES → Client Component
└─ NO → Server Component
Do you need browser APIs (window, localStorage)?
├─ YES → Client Component
└─ NO → Server Component
Do you need to fetch data?
├─ Use Server Component (preferred)
└─ Only use Client Component if data must be client-side
Is the component purely presentational?
└─ Server Component (better performance)
// app/projects/page.tsx
export default async function ProjectsPage() {
const projects = await db.project.findMany()
return <ProjectList projects={projects} />
}
// components/ProjectCard.tsx
'use client'
import { useState } from 'react'
export function ProjectCard({ project }: Props) {
const [loading, setLoading] = useState(false)
const handleDelete = async () => {
setLoading(true)
await deleteProject(project.id)
setLoading(false)
}
return (
<div>
<h2>{project.name}</h2>
<button onClick={handleDelete} disabled={loading}>
Delete
</button>
</div>
)
}
// app/actions.ts
'use server'
export async function createProject(formData: FormData) {
const name = formData.get('name') as string
const project = await db.project.create({ data: { name } })
revalidatePath('/projects')
return { success: true, project }
}
// app/projects/new/page.tsx
import { createProject } from '@/app/actions'
export default function NewProjectPage() {
return (
<form action={createProject}>
<input name="name" required />
<button type="submit">Create</button>
</form>
)
}
// app/dashboard/page.tsx
import { Suspense } from 'react'
export default function DashboardPage() {
return (
<div>
<Suspense fallback={<ProjectsSkeleton />}>
<ProjectsAsync />
</Suspense>
<Suspense fallback={<UsersSkeleton />}>
<UsersAsync />
</Suspense>
</div>
)
}
async function ProjectsAsync() {
const projects = await fetchProjects() // Slow query
return <ProjectList projects={projects} />
}
// app/blog/[slug]/page.tsx
import type { Metadata } from 'next'
export async function generateMetadata({
params,
}: {
params: Promise<{ slug: string }>
}): Promise<Metadata> {
const { slug } = await params
const post = await fetchPost(slug)
return {
title: post.title,
description: post.excerpt,
openGraph: {
title: post.title,
description: post.excerpt,
images: [post.coverImage],
},
}
}
// ✅ DO: Server Component (default)
export default async function ProjectsPage() {
const projects = await fetchProjects()
return <ProjectList projects={projects} />
}
// ❌ DON'T: Client Component when not needed
'use client'
export default function ProjectsPage() {
const [projects, setProjects] = useState([])
useEffect(() => {
fetchProjects().then(setProjects)
}, [])
return <ProjectList projects={projects} />
}
// Static content (cached forever)
const categories = await fetch('https://api.example.com/categories', {
cache: 'force-cache',
}).then(r => r.json())
// Dynamic content (no cache)
const user = await fetch('https://api.example.com/me', {
cache: 'no-store',
}).then(r => r.json())
// ISR (revalidate every hour)
const products = await fetch('https://api.example.com/products', {
next: { revalidate: 3600 },
}).then(r => r.json())
// app/dashboard/error.tsx
'use client'
export default function DashboardError({
error,
reset,
}: {
error: Error
reset: () => void
}) {
return (
<div>
<h2>Something went wrong!</h2>
<button onClick={reset}>Try again</button>
</div>
)
}
// app/dashboard/loading.tsx
export default function DashboardLoading() {
return <DashboardSkeleton />
}
// ✅ DO: Use next/image
import Image from 'next/image'
export function ProjectCard({ project }) {
return (
<Image
src={project.image}
alt={project.name}
width={400}
height={300}
/>
)
}
// ❌ DON'T: Use <img> tag
export function ProjectCard({ project }) {
return <img src={project.image} alt={project.name} />
}
// ❌ DON'T: This is a syntax error
'use client'
export default async function BadComponent() {
const data = await fetch('/api/data')
return <div>{data}</div>
}
// ✅ DO: Use Server Component or useEffect
export default async function GoodComponent() {
const data = await fetch('/api/data')
return <div>{data}</div>
}
// ❌ DON'T: Server Components can't use browser APIs
export default function BadComponent() {
const [state, setState] = useState(false) // Error!
return <div>{state}</div>
}
// ✅ DO: Add 'use client' directive
'use client'
export default function GoodComponent() {
const [state, setState] = useState(false)
return <div>{state}</div>
}
// ❌ DON'T: Unclear caching behavior
const data = await fetch('/api/data')
// ✅ DO: Explicit cache strategy
const data = await fetch('/api/data', {
cache: 'no-store', // or 'force-cache', or { next: { revalidate: 60 } }
})
// ❌ DON'T: Unoptimized images
<img src="/logo.png" alt="Logo" />
// ✅ DO: Use Next.js Image optimization
<Image src="/logo.png" alt="Logo" width={200} height={100} />
Solution: Add 'use client' to the component file.
Solution: Remove 'use client' or use useEffect instead of async component.
Solution: Environment variables in Client Components need NEXT_PUBLIC_ prefix.
Solution: Don't use headers() or cookies() after sending response. Call them before any streaming.
Run the pattern validator to check your code:
python .claude/skills/nextjs-15-specialist/validate-patterns.py src/
The validator checks for:
This skill ensures you:
When in doubt:
Last updated: 2025-11-23 Next.js Version: 15.5 Total Examples: 150+ Total Lines: 4,000+