概要
(folderName) の形式でディレクトリを作ると、そのフォルダ名は URL に含まれず、グループ内に独立した layout.tsx を置ける。
認証済みユーザー用レイアウト(サイドバーあり)と未認証ページ(ログイン画面)で異なる UI を適用するのが代表的なユースケース。
インストール
# 追加インストールは不要
ディレクトリ構成
src/app/
├── (marketing)/ ← URL に含まれない
│ ├── layout.tsx ← マーケティング用 layout
│ ├── page.tsx → /
│ └── about/
│ └── page.tsx → /about
├── (dashboard)/ ← URL に含まれない
│ ├── layout.tsx ← ダッシュボード用 layout(サイドバーあり)
│ ├── dashboard/
│ │ └── page.tsx → /dashboard
│ └── settings/
│ └── page.tsx → /settings
└── layout.tsx ← ルート layout(全グループ共通)
実装例
// src/app/(marketing)/layout.tsx
export default function MarketingLayout({ children }: { children: React.ReactNode }) {
return (
<div>
<header className="border-b px-6 py-4 text-sm font-medium">TOOLS BOX</header>
<main className="mx-auto max-w-4xl px-6 py-8">{children}</main>
</div>
);
}
// src/app/(dashboard)/layout.tsx
export default function DashboardLayout({ children }: { children: React.ReactNode }) {
return (
<div className="flex min-h-screen">
<nav className="w-56 border-r p-4 text-sm">
<ul className="space-y-1">
<li>
<a href="/dashboard" className="block rounded px-3 py-2 hover:bg-gray-100">
ダッシュボード
</a>
</li>
<li>
<a href="/settings" className="block rounded px-3 py-2 hover:bg-gray-100">
設定
</a>
</li>
</ul>
</nav>
<main className="flex-1 p-6">{children}</main>
</div>
);
}
// src/app/(dashboard)/dashboard/page.tsx
export default function DashboardPage() {
return <h1 className="text-lg font-bold">ダッシュボード</h1>;
}
ポイント
(marketing)/(dashboard)はフォルダ名だが URL に現れない(/dashboardで直接アクセスできる)- グループごとに独立した
layout.tsxを持てるため、ヘッダー・サイドバー・フッターの構成を分けられる - ルートの
src/app/layout.tsxは全グループに共通して適用される(<html>/<body>はここに書く) - 認証フローと組み合わせる場合は
middleware.tsで保護対象パスを制御する