これまでの Next.js ブログサイト構築シリーズをまとめたページは以下の通りです。
前回の第7回では、 Next.js の「動的ルーティング」機能を使い、
トップページの新着記事一覧から個別記事のページへリンクを繋ぎ、
本文を表示する仕組みを構築しました。
記事の一覧表示と個別表示ができるようになりましたが、
どのページを開いても、上部にサイト名はなく、下部にもコピーライトがない、
いわゆる「外枠のない素っ気ない画面」のままです。
この記事では、 Next.js の layout.tsx を使い、
全ページに共通で表示されるヘッダーとフッターをコンポーネントとして実装する手順を解説します。
この記事を読むと、以下のことができるようになります。
componentsフォルダにヘッダーとフッターをコンポーネントとして作成するlayout.tsxに組み込んで、全ページに一括で適用する- 1ファイルの変更だけで全ページのデザインを管理できる構造を作る
作業の前に:コンポーネントとフォルダ構成を理解する
コンポーネントという考え方
実際の作業に入る前に、今回の核となる「コンポーネント」という考え方を整理しておきます。
Next.js( React )では、画面の部品をコンポーネントという単位で作ります。
レゴブロックをイメージすると分かりやすいと思います。「ヘッダー」というブロックと「フッター」というブロックをそれぞれ独立したファイルとして作っておき、あとから組み合わせる、という作り方です。
部品を独立したファイルに分けておくメリットは以下の通りです。
- サイト名を変えたいとき、
Header.tsxだけを修正すれば全ページに反映される - 同じ部品を複数のページで使い回せる
- コードが長くなりすぎず、管理しやすくなる
WordPress のウィジェットやテーマ設定に近いものと理解すると良いと思います。
今回の作業で完成するフォルダ構成
今回の作業が完了すると、フォルダ構成は以下のようになります。
example-blog/
├── app/
│ ├── layout.tsx ← 全ページ共通の外枠(今回編集)
│ ├── page.tsx ← トップページ(今回一部修正)
│ ├── globals.css
│ └── posts/
│ └── [id]/
│ └── page.tsx ← 個別記事ページ(今回一部修正)
├── components/ ← 今回新しく作成するフォルダ
│ ├── Header.tsx ← ヘッダー部品(今回新規作成)
│ └── Footer.tsx ← フッター部品(今回新規作成)
├── lib/
│ └── posts.ts
└── posts/
├── test-1.md
└── test-2.md
新しく登場するのは components フォルダとその中の2つのファイルです。
それ以外のファイルは、今回の作業で一部修正します。
layout.tsx にヘッダー・フッターを実装する手順
Step 1:コンポーネント用フォルダの作成
ヘッダーとフッターのファイルを保管するための専用フォルダを作成します。
Cursor のターミナルで以下のコマンドを実行してください。
mkdir ~/example-blog/components
mkdir は「 Make Directory 」の略で、新しいフォルダを作成するコマンドです。
Step 2:ヘッダーコンポーネントの作成
続いて、ヘッダーの部品ファイルを作成します。
nano ~/example-blog/components/Header.tsx
黒い画面( nano エディタ)が開いたら、以下のコードをすべて貼り付けます。
貼り付けたら Ctrl + O → Enter で保存し、 Ctrl + X でエディタを終了します。
import Link from 'next/link';
export default function Header() {
return (
<header className="bg-gray-900 border-b border-gray-700">
<div className="max-w-3xl mx-auto px-8 py-4 flex items-center justify-between">
{/* サイト名:クリックするとトップページへ戻る */}
<Link href="/" className="text-white text-xl font-bold hover:text-gray-300 transition-colors">
あなたのブログ名
</Link>
{/* ナビゲーションメニュー */}
<nav>
<ul className="flex gap-6">
<li>
<Link href="/" className="text-gray-400 hover:text-white transition-colors text-sm">
ホーム
</Link>
</li>
</ul>
</nav>
</div>
</header>
);
}
あなたのブログ名 の部分は、ご自身のブログ名に書き換えてください。
コードのポイント解説
1行目の import Link from 'next/link'; で、 Next.js 専用のリンク部品を読み込んでいます。通常の HTML の <a> タグでも同じようにリンクを作れますが、 Next.js では <Link> を使うことで、ページ全体を読み込み直さずに一瞬で画面が切り替わります。
3行目の export default function Header() の部分が、コンポーネントの定義です。export default をつけることで、他のファイルから import Header from '../components/Header' のように読み込めるようになります。
デザインの設定( className の部分)は、 Tailwind CSS のクラス名を空白区切りで並べて指定します。特にポイントになる部分は以下の通りです。
flex items-center justify-between:サイト名とナビゲーションを左右の端に配置するhover:text-gray-300:マウスが乗ったときに文字色を変えるホバーエフェクト(hover:プレフィックスをつけるのがルール)transition-colors:色の変化をなめらかにアニメーションさせる
ナビゲーションメニューの <li> ブロックを追加することで、後から「カテゴリー」などのリンクを増やせます。
Step 3:フッターコンポーネントの作成
次に、フッターの部品ファイルを作成します。
nano ~/example-blog/components/Footer.tsx
黒い画面が開いたら、以下のコードをすべて貼り付けて保存します( Ctrl + O → Enter → Ctrl + X )。
export default function Footer() {
return (
<footer className="bg-gray-900 border-t border-gray-700 mt-16">
<div className="max-w-3xl mx-auto px-8 py-6 text-center">
<p className="text-gray-500 text-sm">
© {new Date().getFullYear()} あなたのブログ名
</p>
</div>
</footer>
);
}
あなたのブログ名 の部分は、 Header.tsx に入力したものと同じブログ名に書き換えてください。
コードのポイント解説
コピーライト表示の {new Date().getFullYear()} は JavaScript のコードです。実行した時点の西暦を自動で取得します。「2026」と直接書かずに済むため、年が変わっても自動で更新されます。
{} で囲んだ部分が JavaScript のコードとして実行される、 JSX という記法です。 Next.js のコードでは、 HTML に似た構造の中に JavaScript を混ぜて書けます。
Step 4:layout.tsx にヘッダーとフッターを組み込む
今回の作業で最も重要なファイルが app/layout.tsx です。
このファイルは、 全ページ共通の外枠 を定義する Next.js の特別なファイルです。ここにヘッダーとフッターを組み込むことで、すべてのページに自動で適用されます。
nano ~/example-blog/app/layout.tsx
ファイルを開いたら、既存の中身をすべて削除します。 nano では Ctrl + K を繰り返すと1行ずつ削除できます。全行削除したら、以下のコードをまるごと貼り付けて保存します。
import type { Metadata } from "next";
import "./globals.css";
import Header from "../components/Header";
import Footer from "../components/Footer";
export const metadata: Metadata = {
title: "あなたのブログ名",
description: "ブログの説明文をここに入力してください",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="ja" suppressHydrationWarning>
<body className="bg-gray-950 text-white min-h-screen flex flex-col">
{/* ヘッダー:全ページの上部に表示 */}
<Header />
{/* children:各ページの本文がここに入る */}
<main className="flex-grow">
{children}
</main>
{/* フッター:全ページの下部に表示 */}
<Footer />
</body>
</html>
);
}
title と description の2か所を、ご自身のブログに合わせて書き換えてください。
title:ブラウザのタブに表示されるブログ名(Header.tsxに入力したものと同じにする)description:検索エンジンの検索結果に表示されるブログの説明文
コードのポイント解説
このコードの核心部分は {children} です。
children とは、「各ページの本文を受け取るための受け皿」です。トップページ( page.tsx )や個別記事ページの中身が、この {children} の位置に自動的に差し込まれます。
children の型として指定している React.ReactNode は、「 React が画面に表示できるものなら何でも受け取る」という意味です。文字列・画像・他のコンポーネントなど、どんな中身が来ても対応できる、最も汎用的な型指定です。
3つのファイルの関係を図で整理すると、以下のようになります。
layout.tsx(外枠)
├── Header.tsx(上部)
├── {children}( page.tsx の中身がここに差し込まれる)
└── Footer.tsx(下部)
layout.tsx を1か所変更するだけで、全ページのデザインが一括で変わるのが、この構造の最大のメリットです。
min-h-screen flex flex-col と flex-grow の組み合わせは、コンテンツが少ない短いページでもフッターが常に画面の一番下に来るようにするための設定です。
layout.tsx という1つのファイルで全ページの見た目を管理できるのは、合理的でとても良いです。
今後デザインを変えるときも、このファイルを編集するだけで済みますので、管理も楽になりそうです。
Step 5:各ページの <main> タグを <div> タグに修正する
layout.tsx 側で <main> タグを管理するようにしたため、各ページの page.tsx にある <main> タグと重複しないよう修正が必要です。
<main> タグは1ページに1つが HTML の基本ルールです。このまま放置すると <main> の中に <main> が入る入れ子になり、 SEO やアクセシビリティ上の問題が起きる可能性があります。各ページ側のタグを <div> に変更して対応します。
トップページ(app/page.tsx)の修正
nano ~/example-blog/app/page.tsx
ファイルを開いたら、一番上の方にある以下の行を探します。
<main className="max-w-3xl mx-auto p-8">
これを以下に書き換えます。
<div className="max-w-3xl mx-auto p-8">
あわせて、ファイルの末尾付近にある閉じタグ </main> も </div> に変更して保存します。
修正できたら、以下のコマンドで変更内容を確認できます。
grep -n "main\|div" ~/example-blog/app/page.tsx
<main> の行が消え、 <div> に置き換わっていれば修正完了です。
個別記事ページ(app/posts/[id]/page.tsx)の修正
nano ~/example-blog/app/posts/\[id\]/page.tsx
コマンドの \[id\] のように [ と ] の前にバックスラッシュ(\)をつけているのは、ターミナル上では [ が特殊文字として扱われるためです。バックスラッシュをつけることで「ただの文字として扱ってください」という意味になります。
同じく <main> を <div> に、 </main> を </div> に変更して保存します。
Step 6:動作確認
すべての準備が整いました。 Next.js を起動してブラウザで確認します。
cd ~/example-blog
npm run dev
起動したら、ブラウザでサイトにアクセスします。以下の点を確認してください。
- ページ上部にご自身のブログ名とナビゲーションが表示されているか
- サイト名をクリックするとトップページに戻るか
- ページ下部にコピーライトが表示されているか
- トップページと個別記事ページ、どちらでもヘッダーとフッターが表示されているか

トップページにブログ名と「ホーム」のナビゲーションが表示され、記事一覧の下にコピーライトのフッターが表示されています。

個別記事でも、トップページと同様にヘッダーとフッターが表示されています。
ブログ全体の見た目を変えずに、トップページと個別記事を表示できるので、デザインに統一感が出て、とてもいい感じになります。
ヘッダーとフッターがすべてのページで表示されれば成功です。
Cursor の Simple Browser を使った確認が便利
今回の作業を通じて、 Cursor の「 Simple Browser 」という機能がとても便利だと感じました。
Cursor の画面上部のメニューから「 View 」→「 Command Palette 」( Ctrl + Shift + P )を開き、「 Simple Browser 」と入力して選択します。 URL に http://localhost:3000 を入力すると、エディタの中にブラウザが表示されます。

上のスクリーンショットは、 Cursor の画面を左右に分割してコードとブラウザを並べて表示している様子です。
コードを編集しながら隣でリアルタイムに確認できるので、ブラウザを別で開く手間が省けます。
開発モード(npm run dev)を使うと、画面の左下に Next.js の開発用ツールバーが表示されます。これは開発モードのみ表示される、デバッグ用のメニューです。

上のスクリーンショットは、画面左下に表示される Next.js の開発用ツールバーです。
Route: Static:現在のページが静的ページとして生成されていることを示しているBundler: Turbopack: Next.js 15 から標準になった高速ビルドツールが動いていることを示している
本番用のビルド(npm run build)を実行すると自動的に消えるため、今は気にせず作業を進めて問題ありません。
まとめ
今回は、 Next.js の layout.tsx を使って、ヘッダーとフッターを全ページ共通のレイアウトとして実装する手順を解説しました。
components フォルダに部品を分けて作り、 layout.tsx に {children} で差し込む構造は、最初は少し手間に感じるかもしれません。しかし今後、ナビゲーションを増やしたいときは Header.tsx の <li> を追加するだけ、デザインを変えたいときは Tailwind CSS のクラス名を修正するだけで、全ページに一括で反映されます。
サイトとしての「外枠」が整ったことで、ようやくブログらしい見た目になってきました。
次回は、記事ごとに異なるタイトルやメタディスクリプション、アイキャッチ画像を Markdown のフロントマターから自動で読み込んで設定する、 SEO と OGP の対応を行います。




コメント