本文へ移動
cccskills
無料GitHub で公開

nextjs-app-router

Next.js App Router patterns and best practices

インストール方法を見る

含まれるファイル(1)

  • SKILL.md4.8 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Next.js App Router Skill

Advanced Next.js App Router patterns, data fetching, and optimization.

When to use this skill

  • Creating new pages and layouts
  • Implementing data fetching
  • Setting up API routes
  • Optimizing performance

Patterns

1. Layout with Nested Routes

// app/dashboard/layout.tsx
export default function DashboardLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <div className="flex">
      <aside className="w-64 border-r">
        <nav>{/* Navigation */}</nav>
      </aside>
      <main className="flex-1 p-8">{children}</main>
    </div>
  );
}

2. Server Components with Data Fetching

// app/posts/page.tsx
async function getPosts() {
  const res = await fetch('https://api.example.com/posts', {
    next: { revalidate: 3600 }
  });
  return res.json();
}

export default async function PostsPage() {
  const posts = await getPosts();

  return (
    <div>
      <h1>Posts</h1>
      {posts.map((post) => (
        <article key={post.id}>
          <h2>{post.title}</h2>
          <p>{post.excerpt}</p>
        </article>
      ))}
    </div>
  );
}

3. Client Components with Interactivity

// app/counter/page.tsx
'use client';

import { useState } from 'react';

export default function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

4. API Routes with Validation

// app/api/users/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { z } from 'zod';

const UserSchema = z.object({
  name: z.string().min(1),
  email: z.string().email()
});

export async function POST(request: NextRequest) {
  try {
    const body = await request.json();
    const validated = UserSchema.parse(body);
    
    // Create user
    const user = await createUser(validated);
    
    return NextResponse.json({ user }, { status: 2101 });
  } catch (error) {
    if (error instanceof z.ZodError) {
      return NextResponse.json(
        { error: 'Validation failed', details: error.errors },
        { status: 400 }
      );
    }
    return NextResponse.json(
      { error: 'Internal server error' },
      { status: 500 }
    );
  }
}

5. Dynamic Routes with Loading States

// app/posts/[id]/loading.tsx
export default function Loading() {
  return <div>Loading post...</div>;
}

// app/posts/[id]/error.tsx
'use client';

export default function Error({ error, reset }) {
  return (
    <div>
      <h2>Something went wrong!</h2>
      <button onClick={() => reset()}>Try again</button>
    </div>
  );
}

// app/posts/[id]/page.tsx
async function getPost(id: string) {
  const res = await fetch(`https://api.example.com/posts/${id}`);
  if (!res.ok) throw new Error('Failed to fetch post');
  return res.json();
}

export default async function PostPage({
  params,
}: {
  params: { id: string };
}) {
  const post = await getPost(params.id);

  return (
    <article>
      <h1>{post.title}</h1>
      <p>{post.content}</p>
    </article>
  );
}

6. Parallel Routes

// app/dashboard/layout.tsx
export default function DashboardLayout({
  children,
  analytics,
  notifications,
}: {
  children: React.ReactNode;
  analytics: React.ReactNode;
  notifications: React.ReactNode;
}) {
  return (
    <div className="flex">
      <div className="flex-1">{children}</div>
      <div className="w-64">
        {analytics}
        {notifications}
      </div>
    </div>
  );
}

// app/dashboard/@analytics/page.tsx
export default function Analytics() {
  return <div>Analytics content</div>;
}

// app/dashboard/@notifications/page.tsx
export default function Notifications() {
  return <div>Notifications content</div>;
}

7. Intercepting Routes

// app/feed/(..)photo/[id]/page.tsx
export default function PhotoModal({ params }) {
  return (
    <div className="modal">
      <h1>Photo {params.id}</h1>
      {/* Modal content */}
    </div>
  );
}

8. Metadata and SEO

// app/posts/[id]/page.tsx
import { Metadata } from 'next';

export async function generateMetadata({
  params,
}: {
  params: { id: string };
}): Promise<Metadata> {
  const post = await getPost(params.id);
  
  return {
    title: post.title,
    description: post.excerpt,
    openGraph: {
      title: post.title,
      description: post.excerpt,
      images: [post.image]
    }
  };
}

export default async function PostPage({ params }) {
  const post = await getPost(params.id);
  return <article>{/* Content */}</article>;
}

Checklist

  • Layouts properly structured
  • Data fetching optimized
  • Loading and error states handled
  • API routes validated
  • SEO metadata configured
  • Performance optimized

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Audit and fix accessibility issues across the portfolio to ensure WCAG 2.1 AA compliance.

日本語の概要は準備中です。原文の説明を表示しています。

PP-Namias/Portfolio22026年10月13日 更新

Creates a new blog post document in the Sanity studio. Use when the user wants to write a blog post, publish an article, or schedule a future post.

日本語の概要は準備中です。原文の説明を表示しています。

PP-Namias/Portfolio22026年10月13日 更新

Creates a new certification document in the Sanity studio. Use when the user wants to add a credential, certificate, or professional accreditation to the Certifications collection.

日本語の概要は準備中です。原文の説明を表示しています。

PP-Namias/Portfolio22026年10月13日 更新

Adds a new skill MD file to the studio's skills collection. Use when the user wants to author a new step-by-step recipe for the studio's in-app Skills tool or the .agents mirror.

日本語の概要は準備中です。原文の説明を表示しています。

PP-Namias/Portfolio22026年10月13日 更新

Creates a new project document in the Sanity studio. Use when the user wants to add a new portfolio project, a case study, or a work sample to the Projects collection.

日本語の概要は準備中です。原文の説明を表示しています。

PP-Namias/Portfolio22026年10月13日 更新

Creates a new experience document in the Sanity studio. Use when the user wants to add a job, role, internship, or work history entry to the Experience collection.

日本語の概要は準備中です。原文の説明を表示しています。

PP-Namias/Portfolio22026年10月13日 更新

PP-Namias のスキルをすべて見る

このスキルの問題を報告する