Dev Study
← 解説「ルートグループ — ( ) でURLに出ないフォルダを作る」に戻る

サンプルコードで身につける: ルートグループ — ( ) でURLに出ないフォルダを作る

解説で学んだ概念を、5つの具体例で確認します。素朴な例から実務寄りの例へと進みます。

1最小のルートグループ

丸括弧のフォルダが URL に現れない、という規則だけを示す最小の例です。(marketing) という名前はコードを読む人のための整理用ラベルで、ユーザーが見る URL には一切影響しません。

// 丸括弧のフォルダは URL に現れない
//
// app/
// └── (marketing)/
//     ├── page.tsx          → /        (※ /marketing にはならない)
//     └── about/page.tsx    → /about   (※ /marketing/about ではない)
//
// (marketing) は開発者のための整理用ラベル。
// URL を変えずにフォルダだけをグループ分けできる。

2役割ごとにページをグループ分けする

宣伝ページ群と機能ページ群を、URL を変えずにフォルダ上で分類する例です。「コード上は分けたいが URL は今のままにしたい」というリニューアルや整理の場面で、ルートグループがちょうどはまります。

// 役割でグループ分けしても URL はフラットなまま
//
// app/
// ├── (marketing)/          ← 宣伝系のページ
// │   ├── page.tsx          → /
// │   ├── about/page.tsx    → /about
// │   └── pricing/page.tsx  → /pricing
// └── (shop)/               ← 買い物系のページ
//     ├── cart/page.tsx     → /cart
//     └── checkout/page.tsx → /checkout
//
// フォルダを見れば「どのページがどの役割か」が一目で分かる。

3グループごとに別のレイアウトを当てる

ルートグループの一番の目的である「URL は同じ階層のまま、レイアウトだけ分ける」を実装した例です。宣伝ページには宣伝用ナビ、買い物ページにはカート常時表示、のような骨格の分岐が URL に影響せず実現できます。

// app/(marketing)/layout.tsx — 宣伝ページだけに適用
export default function MarketingLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <div>
      <nav>製品紹介 / 料金 / 導入事例</nav>
      {children}
    </div>
  );
}

// app/(shop)/layout.tsx — 買い物ページだけに適用
export default function ShopLayout({ children }: { children: React.ReactNode }) {
  return (
    <div>
      <aside>カートの中身: 3点</aside>
      {children}
    </div>
  );
}

4グループ名を除いてURLを計算してみる

「丸括弧のセグメントは URL から取り除かれる」という規則を関数にして実行する例です。グループが違っても URL の計算結果が同じになり得る、というレッスン本文の衝突の注意点も最後の2行で確かめられます。

TypeScript

5ログイン画面のグループ化

認証系ページをグループ化して中央寄せのシンプルなレイアウトを当てる、実務で定番の構成です。ヘッダーやナビだらけの通常レイアウトを外し、ログインと新規登録だけ集中できる画面にする、という要求にそのまま応えられます。

// app/(auth)/login/page.tsx  → /login
// app/(auth)/signup/page.tsx → /signup

// app/(auth)/layout.tsx — 認証ページ共通の中央寄せレイアウト
export default function AuthLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <div style={{ display: "grid", placeItems: "center", minHeight: "100vh" }}>
      <div>
        <p>My Site</p>
        {children} {/* ログインや新規登録のフォームが入る */}
      </div>
    </div>
  );
}