Next.jsディレクトリのベストプラクティス

📌 ホームページ(Landing Page)のベストディレクトリ構成

目的

  • SEO & パフォーマンスを重視(SSR / ISR 活用)

  • 軽量 & 高速(画像最適化、サーバー負荷削減)

  • デザイン & UX に優れた構成(TailwindCSS + shadcn/ui + Framer Motion)

技術要件:
Next.js App Router(ページ & API 管理)
TypeScript(型安全な開発)
TailwindCSS(ユーティリティベースのデザイン)
shadcn/ui(高品質な UI コンポーネント)
Framer Motion(スムーズなアニメーション)
Zod(型安全なバリデーション)
Zustand(シンプルな状態管理)
React Query(API キャッシュ & フェッチ管理)
NextAuth.js(ユーザー認証)
Sentry(エラーロギング & パフォーマンス監視)

📌 Next.js App Router を活用したスケーラブルなディレクトリ構成(Admin + Portfolio 対応)

この構成は、スケーラビリティ・拡張性・パフォーマンス最適化 を考慮した設計になっています。

  • components/sections/ページごとのセクションを整理

  • components/ui/ボタン・モーダル・トーストなどの共通コンポーネントを一元管理

  • app/admin/管理者専用のダッシュボード & 記事・ユーザー管理

  • app/portfolio/作品紹介ページ(動的ルーティング)

  • store/Zustand による状態管理

  • hooks/再利用可能なカスタムフック

  • lib/API クライアント・認証処理・ユーティリティ関数


🚀 スケーラブルなディレクトリ構成

📦 my-project
├── 📂 app
│   ├── layout.tsx               # ✅ 全体レイアウト
│   ├── page.tsx                 # ✅ ホームページ
│   ├── loading.tsx              # ✅ ローディング画面
│   ├── not-found.tsx            # ✅ 404 ページ
│   ├── error.tsx                # ✅ エラーページ (Sentry 用)
│   ├── 📂 api                   # ✅ API エンドポイント
│   │   ├── auth/route.ts        # 認証 API (NextAuth.js)
│   │   ├── contact/route.ts     # お問い合わせフォーム API
│   │   ├── subscribe/route.ts   # メール購読 API
│   │   ├── analytics/route.ts   # アクセス解析 API
│   ├── 📂 blog                  # ✅ ブログページ
│   │   ├── page.tsx             # ブログ一覧ページ
│   │   ├── [slug]/page.tsx      # 記事詳細ページ
│   ├── 📂 portfolio             # ✅ 作品紹介ページ(動的ルーティング)
│   │   ├── page.tsx             # 作品一覧
│   │   ├── [slug]/page.tsx      # 作品詳細ページ
│   ├── 📂 admin                 # ✅ 管理画面
│   │   ├── layout.tsx           # 管理画面の共通レイアウト
│   │   ├── page.tsx             # ダッシュボード
│   │   ├── 📂 articles          # 記事管理
│   │   │   ├── page.tsx         # 記事一覧
│   │   │   ├── new/page.tsx     # 記事作成
│   │   │   ├── [id]/edit.tsx    # 記事編集
│   │   ├── 📂 users             # ユーザー管理
│   │   │   ├── page.tsx         # ユーザー一覧
│   │   │   ├── [id]/edit.tsx    # ユーザー編集
│   │   ├── 📂 portfolio         # 作品管理
│   │   │   ├── page.tsx         # 作品一覧
│   │   │   ├── new/page.tsx     # 作品登録
│   │   │   ├── [id]/edit.tsx    # 作品編集
├── 📂 components
│   ├── 📂 sections              # ✅ 各セクションごとに整理
│   │   ├── Hero.tsx             # ヒーローセクション
│   │   ├── About.tsx            # 会社概要
│   │   ├── Services.tsx         # サービス紹介
│   │   ├── Testimonials.tsx     # お客様の声
│   │   ├── Pricing.tsx          # 料金プラン
│   │   ├── Contact.tsx          # お問い合わせ
│   │   ├── Portfolio.tsx        # ポートフォリオ一覧
│   │   ├── FAQ.tsx              # よくある質問
│   │   ├── Footer.tsx           # フッター
│   ├── 📂 ui                    # ✅ 再利用可能な UI コンポーネント
│   │   ├── button.tsx           # ボタン
│   │   ├── card.tsx             # カードデザイン
│   │   ├── input.tsx            # 入力フィールド
│   │   ├── navbar.tsx           # ナビゲーションバー
│   │   ├── modal.tsx            # モーダル
│   │   ├── pagination.tsx       # ページネーション
│   │   ├── accordion.tsx        # アコーディオン
│   │   ├── tabs.tsx             # タブ切り替え
│   │   ├── toast.tsx            # トースト通知
│   │   ├── skeleton.tsx         # ローディングスケルトン
│   ├── 📂 layout                # ✅ レイアウト関連
│   │   ├── header.tsx           # ヘッダー
│   │   ├── sidebar.tsx          # サイドバー
├── 📂 hooks                     # ✅ カスタムフック
│   ├── useAuth.ts               # 認証情報取得
│   ├── useTheme.ts              # ダークモード切り替え
│   ├── useScroll.ts             # スクロールイベント処理
│   ├── useModal.ts              # モーダルの開閉管理
├── 📂 store                     # ✅ Zustand を使った状態管理
│   ├── useAuthStore.ts          # 認証管理
│   ├── useThemeStore.ts         # テーマ管理
├── 📂 lib                       # ✅ ユーティリティ関数
│   ├── api.ts                   # API クライアント(React Query 用)
│   ├── auth.ts                  # 認証関連処理
│   ├── prisma.ts                # Prisma クライアント設定
│   ├── cn.ts                    # clsx + tailwind-merge ヘルパー
├── 📂 styles                    # ✅ グローバルスタイル
│   ├── globals.css              # TailwindCSS のグローバルスタイル
│   ├── tailwind.css             # TailwindCSS の設定
├── 📂 public                     # ✅ 静的アセット
│   ├── images/                  # 画像ファイル
│   │   ├── hero.webp
│   │   ├── logo.svg
│   ├── icons/                   # アイコン
│   │   ├── facebook.svg
│   │   ├── instagram.svg
├── 📂 prisma                     # ✅ データベーススキーマ
│   ├── schema.prisma             # Prisma のスキーマ定義
│   ├── seed.ts                   # 初期データ投入スクリプト
├── tailwind.config.ts            # TailwindCSS 設定
├── next.config.js                # Next.js 設定
├── tsconfig.json                 # TypeScript 設定
├── package.json                  # パッケージ管理
└── .eslintrc.js                  # ESLint 設定

✅ ポイント

🔥 Admin 機能強化(記事・ユーザー・ポートフォリオ管理)
🔥 NextAuth.js による認証(app/api/auth/route.ts)
🔥 Zustand + React Query で状態管理 & API キャッシュ
🔥 Sentry でエラーロギングを実装


📌 0 から作る最適な順番(Next.js App Router + TailwindCSS + Zustand + React Query)

この手順は、スケーラビリティ・メンテナンス性・パフォーマンス最適化 を考慮した、最も効率的な開発順序 です。


🚀 開発の最適なステップ

🟢 1️⃣ プロジェクトのセットアップ

まず、Next.js + TypeScript + TailwindCSS + shadcn/ui をセットアップ。

# 1. Next.js App Router プロジェクトを作成
npx create-next-app@latest my-project --typescript --tailwind --eslint --app
cd my-project

# 2. 必要なパッケージをインストール
npm install @tanstack/react-query zustand next-auth @auth/prisma-adapter \
  @hookform/resolvers react-hook-form zod prisma @prisma/client \
  @sentry/nextjs framer-motion clsx tailwind-merge

📌 インストールするもの:
React Query(API キャッシュ & フェッチ管理)
Zustand(状態管理)
NextAuth.js(認証)
Prisma(データベース ORM)
Zod(バリデーション)
Sentry(エラーロギング)
Framer Motion(アニメーション)
clsx & tailwind-merge(Tailwind クラス管理)


🟢 2️⃣ TailwindCSS & shadcn/ui のセットアップ

# 1. TailwindCSS の設定
npx tailwindcss init -p

📌 tailwind.config.ts を編集:

import { type Config } from "tailwindcss";
export default {
  content: ["./app/**/*.{js,ts,jsx,tsx}", "./components/**/*.{js,ts,jsx,tsx}"],
  theme: { extend: {} },
  plugins: [],
} satisfies Config;
# 2. shadcn/ui の設定
npx shadcn-ui@latest init

🟢 3️⃣ ディレクトリ構成を作成

📌 mkdir コマンドで作成:

mkdir -p components/{ui,layout,sections} hooks store lib prisma public/images
mkdir -p app/{api,admin,portfolio,blog}
mkdir -p app/api/{auth,contact,subscribe,analytics}
mkdir -p app/admin/{articles,users,portfolio}

📌 フォルダの役割:

  • app/api/ → API ルート

  • components/ui/ → 共通 UI コンポーネント

  • components/layout/ → ヘッダー・フッター

  • components/sections/ → セクションごとのコンポーネント

  • store/ → Zustand による状態管理

  • hooks/ → カスタムフック


🟢 4️⃣ Prisma 設定

npx prisma init

📌 prisma/schema.prisma を編集:

generator client {
  provider = "prisma-client-js"
}
datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}
model User {
  id        String  @id @default(uuid())
  email     String  @unique
  password  String?
  name      String?
  articles  Article[]
}
model Article {
  id        String  @id @default(uuid())
  title     String
  content   String
  authorId  String
  author    User    @relation(fields: [authorId], references: [id])
  createdAt DateTime @default(now())
}
# マイグレーション & クライアント生成
npx prisma migrate dev --name init
npx prisma generate

🟢 5️⃣ Zustand で状態管理

📌 store/useAuthStore.ts

import { create } from "zustand";

interface AuthState {
  user: { id: string; name: string } | null;
  setUser: (user: AuthState["user"]) => void;
}

export const useAuthStore = create<AuthState>((set) => ({
  user: null,
  setUser: (user) => set({ user }),
}));

🟢 6️⃣ API 実装

📌 app/api/auth/route.ts

import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import { PrismaAdapter } from "@auth/prisma-adapter";
import { prisma } from "@/lib/prisma";

export default NextAuth({
  adapter: PrismaAdapter(prisma),
  providers: [
    CredentialsProvider({
      name: "Credentials",
      credentials: { email: { label: "Email" }, password: { label: "Password" } },
      async authorize(credentials) {
        const user = await prisma.user.findUnique({ where: { email: credentials?.email } });
        return user || null;
      },
    }),
  ],
});

🟢 7️⃣ ページ & セクションの作成

📌 components/sections/Hero.tsx

import { motion } from "framer-motion";

export default function Hero() {
  return (
    <motion.section
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      transition={{ duration: 0.5 }}
      className="h-screen flex items-center justify-center bg-gray-900 text-white"
    >
      <h1 className="text-5xl font-bold">Welcome to My Landing Page</h1>
    </motion.section>
  );
}

📌 app/page.tsx

import Hero from "@/components/sections/Hero";

export default function HomePage() {
  return <Hero />;
}

🟢 8️⃣ フォーム & バリデーション(Zod + React Hook Form)

📌 components/ui/form.tsx

import { useForm } from "react-hook-form";
import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";

const schema = z.object({
  email: z.string().email("Invalid email"),
});

export default function ContactForm() {
  const { register, handleSubmit, formState: { errors } } = useForm({
    resolver: zodResolver(schema),
  });

  return (
    <form onSubmit={handleSubmit(console.log)}>
      <Input {...register("email")} placeholder="Email" />
      {errors.email && <p>{errors.email.message}</p>}
      <Button type="submit">Submit</Button>
    </form>
  );
}

🟢 9️⃣ デプロイ準備

# Vercel にデプロイ
npm run build
vercel deploy

✅ まとめ

💡 最適な開発順序

1️⃣ プロジェクトセットアップ(Next.js + Tailwind + shadcn/ui)
2️⃣ ディレクトリ構成の作成
3️⃣ Prisma 設定(データベース構築)
4️⃣ Zustand + API 実装(状態管理 & 認証)
5️⃣ ページ & セクション作成(UI & アニメーション)
6️⃣ フォーム & バリデーション(Zod + React Hook Form)
7️⃣ デプロイ(Vercel)


参考




いいなと思ったら応援しよう!