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

nextjs-routing

Next.js App Router routing primitives: file-based routes, dynamic and catch-all segments, route groups, parallel routes, intercepting routes, middleware, programmatic navigation, link patterns. Use this skill to: - Pick the correct dynamic segment syntax for the route shape. - Use route groups to organize without affecting URLs. - Implement parallel/intercepting routes for modal-style navigation. - Build effective middleware for auth, redirects, A/B tests. - Use Link and useRouter correctly. Do NOT use this skill for: - Data fetching per route (see nextjs-data-fetching). - General file conventions (see nextjs-conventions). - RSC vs Client (see server-component-patterns).

インストール方法を見る

含まれるファイル(1)

  • SKILL.md8.7 KB

SKILL.md(原文)

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

Next.js Routing Patterns

App Router is file-based: folders are routes, page.tsx is the page UI. This skill covers the routing primitives beyond plain pages.

Dynamic segments

app/users/[id]/page.tsx                → /users/:id          → params.id: string
app/posts/[slug]/page.tsx              → /posts/:slug        → params.slug: string
app/docs/[...path]/page.tsx            → /docs/a/b/c          → params.path: string[]
app/optional/[[...path]]/page.tsx      → /optional AND /optional/a/b → params.path: string[] | undefined

In Next.js 15+, params is a Promise:

export default async function Page({ params }: { params: Promise<{ id: string }> }) {
  const { id } = await params;
  // ...
}

In Next.js 14 and earlier, params is a plain object — no await needed.

Route groups (organizational)

Folders in parens — DON'T appear in URL but allow:

  • Different layouts for different sections.
  • Logical organization without nested URLs.
app/(marketing)/about/page.tsx         → /about
app/(marketing)/pricing/page.tsx       → /pricing
app/(marketing)/layout.tsx             → applies to /about and /pricing

app/(app)/dashboard/page.tsx           → /dashboard
app/(app)/settings/page.tsx            → /settings
app/(app)/layout.tsx                   → applies to /dashboard and /settings

/about doesn't get the /(app)/ layout, even though they share app/'s root layout.

Parallel routes

Render two segments simultaneously in one layout — for dashboards, modal overlays, side panels.

app/dashboard/layout.tsx
app/dashboard/@analytics/page.tsx       → renders into {analytics} slot
app/dashboard/@team/page.tsx            → renders into {team} slot
app/dashboard/page.tsx                  → renders into {children} slot

The layout receives all slots:

// app/dashboard/layout.tsx
export default function Layout({
  children,
  analytics,
  team,
}: {
  children: React.ReactNode;
  analytics: React.ReactNode;
  team: React.ReactNode;
}) {
  return (
    <div>
      <main>{children}</main>
      <aside>{analytics}</aside>
      <aside>{team}</aside>
    </div>
  );
}

If a slot has no matching route for a navigation, provide default.tsx in the slot folder for fallback.

Intercepting routes (modals)

Render a different component for the SAME URL based on the navigation source. Common pattern: clicking a link from a list opens a modal; visiting the URL directly shows the full page.

app/photos/page.tsx                          → /photos (gallery)
app/photos/[id]/page.tsx                     → /photos/:id (full view, direct visits)
app/photos/(.)photos/[id]/page.tsx           → intercepts /photos/:id from /photos
app/photos/(..)settings/page.tsx             → intercepts from one level up
app/photos/(..)(..)about/page.tsx            → intercepts from two levels up
app/photos/(...)about/page.tsx               → intercepts from app root

Combine with parallel routes (@modal slot) for the modal pattern:

app/layout.tsx
app/page.tsx                                  → / (gallery)
app/@modal/(.)photos/[id]/page.tsx            → modal version
app/@modal/default.tsx                        → no-modal fallback
app/photos/[id]/page.tsx                      → direct visit URL

The layout slots {children} and {modal} — layout renders both, modal overlays.

Programmatic navigation

From Client Components

'use client';
import { useRouter, usePathname, useSearchParams } from 'next/navigation';

export function NavButton() {
  const router = useRouter();
  const pathname = usePathname();
  const searchParams = useSearchParams();

  return (
    <button onClick={() => router.push('/dashboard')}>
      Go to dashboard
    </button>
  );
}

router.push(href), router.replace(href), router.back(), router.forward(), router.refresh(), router.prefetch(href).

From Server Components / Server Actions

import { redirect, permanentRedirect } from 'next/navigation';

// In a Server Component
if (!user) redirect('/login');

// In a Server Action
export async function deleteAccount() {
  'use server';
  await db.users.delete({ where: { id: session.user.id } });
  redirect('/');
}

redirect() throws an internal exception (NEXT_REDIRECT) — don't catch it; let it propagate.

<Link>

Always use <Link> from next/link for internal navigation. Client-side routing, prefetching, faster perceived nav.

import Link from 'next/link';

<Link href="/dashboard">Dashboard</Link>;
<Link href={{ pathname: '/users', query: { filter: 'active' } }}>Active users</Link>;
<Link href="/external" replace prefetch={false}>...</Link>;

prefetch is true by default for visible Links — Next.js prefetches the route for instant navigation. Disable for rarely-visited or expensive routes.

For external URLs: plain <a href="https://..."> is fine.

Middleware

middleware.ts at the project root. Runs BEFORE every matched request — keep it lean.

import { NextResponse, type NextRequest } from 'next/server';

export function middleware(req: NextRequest) {
  // Auth check
  const token = req.cookies.get('session')?.value;
  if (!token && req.nextUrl.pathname.startsWith('/admin')) {
    return NextResponse.redirect(new URL('/login', req.url));
  }

  // Header rewrite
  const res = NextResponse.next();
  res.headers.set('X-Request-Id', crypto.randomUUID());
  return res;
}

export const config = {
  matcher: [
    // Skip static files and Next.js internals
    '/((?!_next/static|_next/image|favicon.ico|.*\\..*).*)',
  ],
};

Middleware capabilities

  • Read: cookies, headers, geolocation (req.geo), URL.
  • Write: rewrite URL (NextResponse.rewrite), redirect, modify response headers, set cookies.
  • Cannot: read request body (it's not consumed yet), import server-only Node APIs (it runs on edge).

Common patterns

  • Auth gate: redirect to /login if no session cookie.
  • A/B testing: rewrite to a variant based on cookie/geo/random.
  • Internationalization: rewrite to /en, /uk, /es based on Accept-Language.
  • Bot detection: redirect known bots to a static cached page.

redirects and rewrites in next.config.js

For static URL transformations that don't need request inspection:

module.exports = {
  async redirects() {
    return [
      { source: '/old-blog/:slug', destination: '/blog/:slug', permanent: true },
      { source: '/admin', destination: '/dashboard', permanent: false },
    ];
  },
  async rewrites() {
    return [
      // Proxy to a different backend
      { source: '/api/legacy/:path*', destination: 'https://legacy.example.com/:path*' },
    ];
  },
};

Redirects = HTTP 301/302 visible to client. Rewrites = invisible URL transformation.

Status codes from Route Handlers and pages

// In a Route Handler
return new NextResponse(null, { status: 204 });
return NextResponse.json({ error: 'not found' }, { status: 404 });

// In a page (RSC)
import { notFound } from 'next/navigation';
if (!data) notFound();   // throws, renders not-found.tsx, sets 404 status

For redirects with custom status:

NextResponse.redirect(url, 301);

Anti-patterns

  • ❌ Using <a href="/internal"> for internal links — no client-side routing, full reload.
  • ❌ useRouter from next/router (Pages Router) in App Router — use next/navigation instead.
  • ❌ Heavy logic in middleware.ts (it runs on every request and on edge).
  • ❌ redirect() inside try/catch — catches the internal NEXT_REDIRECT and breaks navigation.
  • ❌ Long-running computation in middleware — request stalls.
  • ❌ Reading request body in middleware — it's not consumed yet; use Route Handler instead.
  • ❌ <Link> to external URLs — Next.js will treat it as internal and may handle weirdly.
  • ❌ prefetch={true} on dozens of Links visible at once — wastes bandwidth.
  • ❌ Hard-coding URLs throughout the app — define route helpers in lib/routes.ts for type safety.

レビュー

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

同じリポジトリのスキル

概要と使いどころ

Angular 18-21 project structure, standalone components vs NgModule, control flow (@if/@for/@switch + *ngIf/*ngFor legacy), decorators, dependency injection (inject() function), lifecycle hooks, pipes, Angular Universal SSR pointer. Use this skill to: - Detect project style (standalone vs NgModule) and apply matching patterns. - Pick correct decorators and DI approach. - Use modern control flow (@if/@for/@switch) in Angular 17+ projects. - Apply `inject()` function over constructor injection where appropriate. - Wire bootstrap correctly (bootstrapApplication for standalone, AppModule for legacy). Do NOT use this skill for: - State management (see angular-state-and-rx). - Routing (see angular-routing). - Forms (see angular-forms). - Testing (see angular-testing).

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

AratKruglik/claude-sdlc362026年9月21日 更新

Angular forms: Reactive Forms (preferred — typed FormGroup/FormControl since Angular 14, FormBuilder, custom + async validators, FormArray, multi-step) and Template-driven (`[(ngModel)]` + FormsModule). Validation strategies, server error mapping, accessibility. Use this skill to: - Build Reactive Forms with typed FormGroup/FormControl. - Use FormBuilder для concise syntax. - Implement custom synchronous and async validators. - Wire FormArray for dynamic field lists. - Map server errors back to form fields. - Pick Reactive vs Template-driven (prefer Reactive). Do NOT use this skill for: - General conventions (see angular-conventions). - State management beyond forms (see angular-state-and-rx). - Routing (see angular-routing). - Testing forms (see angular-testing).

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

AratKruglik/claude-sdlc362026年9月21日 更新

Angular Router (built-in `@angular/router`) — route configuration for standalone and NgModule projects, functional guards (Angular 14.1+), lazy loading, route resolvers, typed params via signals/observables, programmatic navigation, route data and meta. Use this skill to: - Configure routes (standalone-style or NgModule-style). - Use functional guards (canActivate as function, preferred over class-based in 17+). - Lazy-load components or feature modules. - Implement auth guards via route meta + functional guards. - Read params/queries via `inject(ActivatedRoute)` + signals or RxJS. Do NOT use this skill for: - General conventions (see angular-conventions). - State management (see angular-state-and-rx). - Forms (see angular-forms). - Testing routes (see angular-testing).

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

AratKruglik/claude-sdlc362026年9月21日 更新

State management for Angular 18-21: signals (signal/computed/effect), services-as-state, NgRx Store + Effects + Selectors, NgRx Component Store, NgRx Signals (newer signal-based store). RxJS essentials — operators, async pipe, takeUntilDestroyed, signal/observable interop. Use this skill to: - Pick the right state tool (signals / services / NgRx variant / vue-query equivalent). - Use signals correctly (signal/computed/effect — when each). - Build a Pinia-style service-as-state singleton. - Set up NgRx Store + Effects + Selectors. - Use RxJS without leaking subscriptions (async pipe, takeUntilDestroyed, Subject patterns). - Bridge signals ↔ observables via toSignal / toObservable. Do NOT use this skill for: - General Angular conventions (see angular-conventions). - Routing state (see angular-routing). - Form state (see angular-forms). - Testing state (see angular-testing).

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

AratKruglik/claude-sdlc362026年9月21日 更新

Testing Angular 18-21: TestBed, component harnesses (@angular/cdk/testing), Karma+Jasmine (default historical) vs Jest (jest-preset-angular, modern), Angular Testing Library (RTL-style). HttpClient mocking via HttpTestingController. NgRx Effects testing. Cypress / Playwright e2e. Use this skill to: - Detect runner (Karma+Jasmine vs Jest) and configure correctly. - Write component tests with TestBed. - Use component harnesses for Material / custom UI components. - Mock HttpClient via provideHttpClientTesting + HttpTestingController. - Test signal-based inputs with componentRef.setInput(). - Test NgRx Effects with provideMockActions. Do NOT use this skill for: - General Angular conventions (see angular-conventions). - Routing patterns broadly (see angular-routing — covers testing routes briefly). - Form patterns broadly (see angular-forms).

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

AratKruglik/claude-sdlc362026年9月21日 更新

Shared conventions for every SDLC development-phase architect agent: hard rules, code quality bar, workflow steps (superpowers invocation, spec reading, codebase exploration, verification), and the report/compact-summary contract. Architects load this skill first, then apply their stack-specific instructions on top.

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

AratKruglik/claude-sdlc362026年9月21日 更新

AratKruglik のスキルをすべて見る

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