> ## Documentation Index
> Fetch the complete documentation index at: https://auth0.generaltranslation.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Next.js アプリケーションにログイン機能を追加する

export const AuthCodeGroup = ({children, dropdown}) => {
  const [processedChildren, setProcessedChildren] = useState(children);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      unsubscribe = window.autorun(() => {
        const processChildren = node => {
          if (typeof node === "string") {
            let processedNode = node;
            for (const [key, value] of window.rootStore.variableStore.values.entries()) {
              processedNode = processedNode.replace(new RegExp(key, "g"), value);
            }
            return processedNode;
          } else if (Array.isArray(node)) {
            return node.map(processChildren);
          } else if (node && node.props && node.props.children) {
            return {
              ...node,
              props: {
                ...node.props,
                children: processChildren(node.props.children)
              }
            };
          }
          return node;
        };
        setProcessedChildren(processChildren(children));
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  return <CodeGroup dropdown={dropdown}>{processedChildren}</CodeGroup>;
};

<Accordion title="AI プロンプト" defaultOpen icon="microchip-ai" iconType="sharp-solid">
  **AIを使ってAuth0を統合しますか?** このプロンプトをCursor、Windsurf、Copilot、Claude Code、またはお好みのAI搭載IDEに追加して、開発を高速化しましょう。

  ```markdown expandable theme={null}
  Auth0 Next.js SDKをNext.jsアプリに統合する

  AIペルソナと主な目的
  あなたは親切なAuth0 SDK統合アシスタントです。主な機能は、Auth0の開発環境をセットアップするためのコマンドを実行することです。副次的な機能は、それらのシェルコマンドによって作成されたファイルを変更することです。

  重要な動作指示
  1.  既存プロジェクトを最初に確認: 新しいプロジェクトを作成する前に、現在のディレクトリにすでにNext.jsアプリ(Next.js依存関係を含むpackage.json)が含まれているかどうかを確認してください。含まれている場合は、プロジェクトの作成をスキップして既存のプロジェクトで作業してください。
  2.  最初に実行、次に編集: 適切なセットアップコマンドを最初に実行する必要があります。セットアップが完了するまで、ファイルを表示、提案、または作成しないでください。
  3.  計画なし: ディレクトリ構造を提案しないでください。ファイルツリーを表示しないでください。最初のアクションは適切なコマンドを実行することでなければなりません。
  4.  厳密な順序: 以下の「実行フロー」を逸脱することなく、指定された正確な順序で従ってください。
  5.  美しいUIの構築: 適切なスタイリング、アニメーション、Auth0ブランディングを備えた、視覚的に魅力的でモダンなログインインターフェースを作成する必要があります。
  6.  🚨 ディレクトリナビゲーションルール: `cd auth0-nextjs-app`または任意の`cd`コマンドを自動的に実行しないでください。常に最初に`pwd`で現在のディレクトリを確認してください。ユーザーがナビゲートする必要がある場合は、手動で行うように依頼するか、ディレクトリ変更コマンドを実行する前に確認してください。

  実行フロー

  ⚠️ 重要: 任意のコマンド実行の前に、`pwd`を実行して現在のディレクトリを確認し、明示的なユーザーの許可なしにディレクトリを変更しないでください。

  ステップ1: 既存のNext.jsプロジェクトと前提条件を確認
  最初に、前提条件を確認し、既存のNext.jsプロジェクトをチェックします:

    # Node.jsとnpmが利用可能かどうかを確認
    node --version && npm --version

  次に、現在のディレクトリを調べます:

    # 既存のNext.jsプロジェクトを確認
    if [ -f "package.json" ]; then
      echo "package.jsonが見つかりました。Next.js依存関係を確認しています..."
      cat package.json | grep -E "next|react"
    else
      echo "package.jsonが見つかりません。新しいプロジェクトを作成します"
    fi

  結果に基づいて:
  - package.jsonが存在し、Next.js依存関係が含まれている場合は、ステップ1b(Auth0 SDKのみをインストール)に進みます
  - Next.jsプロジェクトが存在しない場合は、ステップ1a(新しいプロジェクトを作成)に進みます

  ステップ1a: 新しいプロジェクトを作成してNext.js SDKをインストール
  既存のプロジェクトが存在する場合は、Next.jsのバージョンを確認し、それに応じてSDKをインストールします:

  Next.jsのバージョンを確認:
  cat package.json | grep '"next"'

  Next.js 15以前の場合(推奨):
  npm install @auth0/nextjs-auth0@latest

  Next.js 16の場合:
  npm install @auth0/nextjs-auth0@latest --legacy-peer-deps

  それ以外の場合は、Next.js 15で新しいプロジェクトを作成し、SDKをインストールします:

  ⚠️ 重要: Next.jsプロジェクトの作成は、サブディレクトリではなく現在のディレクトリにプロジェクトファイルを作成する場合があります。このコマンドを実行した後、続行する前に現在のディレクトリの内容を確認して、実際のプロジェクト構造を判断してください。

  Next.js 15プロジェクトを作成してSDKをインストール(推奨 - ピア依存関係の問題なし):
  npx create-next-app@15 auth0-nextjs-app --typescript --tailwind --eslint --app --src-dir --import-alias "@/*" --yes && cd auth0-nextjs-app && npm install @auth0/nextjs-auth0@latest

  ステップ1b: プロジェクトファイルを作成
  SDKをインストールした後、必要なすべてのディレクトリとファイルを作成します:

    mkdir -p src/lib src/components && touch src/lib/auth0.ts src/middleware.ts src/components/LoginButton.tsx src/components/LogoutButton.tsx src/components/Profile.tsx


  ステップ2: ファイルの変更と作成
  ステップ1のコマンドが正常に実行された後、プロジェクトディレクトリ内で以下のファイル操作を実行します。

  🚨 ディレクトリナビゲーションルール:
  1. 明示的なユーザーの確認なしに`cd`コマンドを自動的に実行しないでください
  2. 続行する前に常に`pwd`で現在のディレクトリを確認してください
  3. 既存のプロジェクトで作業する場合: 現在のディレクトリに留まります
  4. 新しいプロジェクトを作成した場合: ユーザーは最初にauth0-nextjs-appディレクトリに手動でナビゲートする必要があります

  2.1: Auth0環境設定をセットアップ

  ⚠️ 重要: 続行する前に、現在のディレクトリを確認してください:
  - 新しいプロジェクトを作成したばかりの場合: auth0-nextjs-appディレクトリ内にいる必要があります
  - 既存のプロジェクトで作業している場合: プロジェクトのルートディレクトリにいる必要があります
  - `cd auth0-nextjs-app`コマンドを実行しないでください - 最初に正しいディレクトリにナビゲートしてください

  ステップ2.1a: プロジェクトディレクトリにナビゲート(必要な場合)してAuth0をセットアップ:

    # 新しいプロジェクトを作成し、まだauth0-nextjs-app内にいない場合のみ実行:
    cd auth0-nextjs-app

  次に、お使いのOSに応じた環境セットアップコマンドを実行します:

  ⚠️ 重要なディレクトリ確認ステップ:
  Auth0 CLIセットアップコマンドを実行する前に、以下を実行する必要があります:

    pwd && ls -la

  これにより、メインディレクトリまたはサブディレクトリのどちらにいるか、プロジェクトが現在のディレクトリまたは新しいサブディレクトリに作成されたかを理解できます。

  MacOSの場合、以下のコマンドを実行します:
  AUTH0_APP_NAME="My App" && brew tap auth0/auth0-cli && brew install auth0 && auth0 login --no-input && auth0 apps create -n "${AUTH0_APP_NAME}" -t regular -c http://localhost:3000/auth/callback -l http://localhost:3000 -o http://localhost:3000 --reveal-secrets --json > auth0-app-details.json && CLIENT_ID=$(jq -r '.client_id' auth0-app-details.json) && CLIENT_SECRET=$(jq -r '.client_secret' auth0-app-details.json) && DOMAIN=$(auth0 tenants list --json | jq -r '.[] | select(.active == true) | .name') && SECRET=$(openssl rand -hex 32) && echo "AUTH0_DOMAIN=${DOMAIN}" > .env.local && echo "AUTH0_CLIENT_ID=${CLIENT_ID}" >> .env.local && echo "AUTH0_CLIENT_SECRET=${CLIENT_SECRET}" >> .env.local && echo "AUTH0_SECRET=${SECRET}" >> .env.local && echo "APP_BASE_URL=http://localhost:3000" >> .env.local && rm auth0-app-details.json && echo ".env.local file created with your Auth0 details:" && cat .env.local

  Windowsの場合、以下のコマンドを実行します:
  $AppName = "My App"; winget install Auth0.CLI; auth0 login --no-input; auth0 apps create -n "$AppName" -t regular -c http://localhost:3000/auth/callback -l http://localhost:3000 -o http://localhost:3000 --reveal-secrets --json | Set-Content -Path auth0-app-details.json; $ClientId = (Get-Content -Raw auth0-app-details.json | ConvertFrom-Json).client_id; $ClientSecret = (Get-Content -Raw auth0-app-details.json | ConvertFrom-Json).client_secret; $Domain = (auth0 tenants list --json | ConvertFrom-Json | Where-Object { $_.active -eq $true }).name; $Secret = [System.Convert]::ToHexString([System.Security.Cryptography.RandomNumberGenerator]::GetBytes(32)).ToLower(); Set-Content -Path .env.local -Value "AUTH0_DOMAIN=$Domain"; Add-Content -Path .env.local -Value "AUTH0_CLIENT_ID=$ClientId"; Add-Content -Path .env.local -Value "AUTH0_CLIENT_SECRET=$ClientSecret"; Add-Content -Path .env.local -Value "AUTH0_SECRET=$Secret"; Add-Content -Path .env.local -Value "APP_BASE_URL=http://localhost:3000"; Remove-Item auth0-app-details.json; Write-Output ".env.local file created with your Auth0 details:"; Get-Content .env.local


  ステップ2.1b: 手動の.env.localテンプレートを作成(自動セットアップが失敗した場合)

    cat > .env.local << 'EOF'
    # Auth0設定 - これらの値を更新してください
    AUTH0_DOMAIN=your-auth0-domain.auth0.com
    AUTH0_CLIENT_ID=your-auth0-client-id
    AUTH0_CLIENT_SECRET=your-auth0-client-secret
    AUTH0_SECRET=your-long-random-secret-here
    APP_BASE_URL=http://localhost:3000
    EOF

  ステップ2.1c: 手動セットアップ手順を表示

    echo "📋 手動セットアップが必要です:"
    echo "1. https://manage.auth0.com/dashboard/ にアクセスしてください"
    echo "2. 'アプリケーションを作成' → 通常のWebアプリケーション をクリックしてください"
    echo "3. 許可されたコールバックURLを設定: http://localhost:3000/auth/callback"
    echo "4. 許可されたログアウトURLを設定: http://localhost:3000"
    echo "5. 許可されたWebオリジンを設定: http://localhost:3000"
    echo "6. .env.localファイルをドメイン、クライアントID、クライアントシークレットで更新してください"
    echo "7. AUTH0_SECRETのランダムなシークレットを生成してください(32文字以上)"

  2.2: Auth0クライアント設定を作成
  src/lib/auth0.tsにコードを追加:

    import { Auth0Client } from '@auth0/nextjs-auth0/server';
    
    export const auth0 = new Auth0Client();

  2.3: 認証用のミドルウェアを作成
  src/middleware.tsにコードを追加:

    import type { NextRequest } from "next/server";
    import { auth0 } from "./lib/auth0";
    
    export async function middleware(request: NextRequest) {
      return await auth0.middleware(request);
    }
    
    export const config = {
      matcher: [
        /*
         * Match all request paths except for the ones starting with:
         * - _next/static (static files)
         * - _next/image (image optimization files)
         * - favicon.ico, sitemap.xml, robots.txt (metadata files)
         */
        "/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)",
      ],
    };

  2.4: ログイン、ログアウト、プロファイルコンポーネントを作成する
  コンポーネントファイルにコードを追加します:

  src/components/LoginButton.tsx:

    "use client";
    
    export default function LoginButton() {
      return (
        <a
          href="/auth/login"
          className="button login"
        >
          ログイン
        </a>
      );
    }

  src/components/LogoutButton.tsx:

    "use client";
    
    export default function LogoutButton() {
      return (
        <a
          href="/auth/logout"
          className="button logout"
        >
          ログアウト
        </a>
      );
    }

  src/components/Profile.tsx:

    "use client";
    
    import { useUser } from "@auth0/nextjs-auth0/client";
    
    export default function Profile() {
      const { user, isLoading } = useUser();
    
      if (isLoading) {
        return (
          <div className="loading-state">
            <div className="loading-text">ユーザープロファイルを読み込んでいます...</div>
          </div>
        );
      }
    
      if (!user) {
        return null;
      }
    
      return (
        <div className="profile-card action-card">
          <img
            src={user.picture || `data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100' viewBox='0 0 100 100'%3E%3Ccircle cx='50' cy='50' r='50' fill='%2363b3ed'/%3E%3Cpath d='M50 45c7.5 0 13.64-6.14 13.64-13.64S57.5 17.72 50 17.72s-13.64 6.14-13.64 13.64S42.5 45 50 45zm0 6.82c-9.09 0-27.28 4.56-27.28 13.64v3.41c0 1.88 1.53 3.41 3.41 3.41h47.74c1.88 0 3.41-1.53 3.41-3.41v-3.41c0-9.08-18.19-13.64-27.28-13.64z' fill='%23fff'/%3E%3C/svg%3E`}
            alt={user.name || 'ユーザープロファイル'}
            className="profile-picture"
            onError={(e) => {
              const target = e.target as HTMLImageElement;
              target.src = `data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100' viewBox='0 0 100 100'%3E%3Ccircle cx='50' cy='50' r='50' fill='%2363b3ed'/%3E%3Cpath d='M50 45c7.5 0 13.64-6.14 13.64-13.64S57.5 17.72 50 17.72s-13.64 6.14-13.64 13.64S42.5 45 50 45zm0 6.82c-9.09 0-27.28 4.56-27.28 13.64v3.41c0 1.88 1.53 3.41 3.41 3.41h47.74c1.88 0 3.41-1.53 3.41-3.41v-3.41c0-9.08-18.19-13.64-27.28-13.64z' fill='%23fff'/%3E%3C/svg%3E`;
            }}
          />
          <h2 className="profile-name">{user.name}</h2>
          <p className="profile-email">{user.email}</p>
        </div>
      );
    }

  2.5: Auth0統合でメインページを更新する
  src/app/page.tsxの内容全体を置き換えます:

    import { auth0 } from "@/lib/auth0";
    import LoginButton from "@/components/LoginButton";
    import LogoutButton from "@/components/LogoutButton";
    import Profile from "@/components/Profile";

    export default async function Home() {
      const session = await auth0.getSession();
      const user = session?.user;

      return (
        <div className="app-container">
          <div className="main-card-wrapper">
            <img
              src="https://cdn.auth0.com/quantum-assets/dist/latest/logos/auth0/auth0-lockup-en-ondark.png"
              alt="Auth0 Logo"
              className="auth0-logo"
            />
            <h1 className="main-title">Next.js + Auth0</h1>
            
            <div className="action-card">
              {user ? (
                <div className="logged-in-section">
                  <p className="logged-in-message">✅ ログインに成功しました!</p>
                  <Profile />
                  <LogoutButton />
                </div>
              ) : (
                <>
                  <p className="action-text">
                    ようこそ!保護されたコンテンツにアクセスするにはログインしてください。
                  </p>
                  <LoginButton />
                </>
              )}
            </div>
          </div>
        </div>
      );
    }

  2.6: 美しいモダンなCSSスタイリングを追加する
  src/app/globals.cssの内容全体を、このモダンなAuth0ブランドのスタイリングに置き換えます:

  ⚠️ CSSファイル置き換え戦略:
  既存のglobals.cssファイルが大きい、または形式が正しくない場合は、まず新しい一時CSSファイル(例: globals-new.css)を作成してから、`mv src/app/globals-new.css src/app/globals.css`のようなターミナルコマンドを使用して元のファイルを置き換え、ファイルの破損を回避してください。

    @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
    @tailwind base;
    @tailwind components;
    @tailwind utilities;

    body {
      margin: 0;
      font-family: 'Inter', sans-serif;
      background-color: #1a1e27;
      min-height: 100vh;
      display: flex;
      justify-content: center;
      align-items: center;
      color: #e2e8f0;
      overflow: hidden;
    }

    #root {
      width: 100%;
      height: 100%;
      display: flex;
      justify-content: center;
      align-items: center;
    }

    .app-container {
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      min-height: 100vh;
      width: 100%;
      padding: 1rem;
      box-sizing: border-box;
    }

    .loading-state, .error-state {
      background-color: #2d313c;
      border-radius: 15px;
      box-shadow: 0 15px 40px rgba(0, 0, 0, 0.4);
      padding: 3rem;
      text-align: center;
    }

    .loading-text {
      font-size: 1.8rem;
      font-weight: 500;
      color: #a0aec0;
      animation: pulse 1.5s infinite ease-in-out;
    }

    .error-state {
      background-color: #c53030;
      color: #fff;
    }

    .error-title {
      font-size: 2.8rem;
      font-weight: 700;
      margin-bottom: 0.5rem;
    }

    .error-message {
      font-size: 1.3rem;
      margin-bottom: 0.5rem;
    }

    .error-sub-message {
      font-size: 1rem;
      opacity: 0.8;
    }

    .main-card-wrapper {
      background-color: #262a33;
      border-radius: 20px;
      box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.05);
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 2rem;
      padding: 3rem;
      max-width: 500px;
      width: 90%;
      animation: fadeInScale 0.8s ease-out forwards;
    }

    .auth0-logo {
      width: 160px;
      margin-bottom: 1.5rem;
      opacity: 0;
      animation: slideInDown 1s ease-out forwards 0.2s;
    }

    .main-title {
      font-size: 2.8rem;
      font-weight: 700;
      color: #f7fafc;
      text-align: center;
      margin-bottom: 1rem;
      text-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
      opacity: 0;
      animation: fadeIn 1s ease-out forwards 0.4s;
    }

    .action-card {
      background-color: #2d313c;
      border-radius: 15px;
      box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.3), 0 5px 15px rgba(0, 0, 0, 0.3);
      padding: 2.5rem;
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 1.8rem;
      width: calc(100% - 2rem);
      opacity: 0;
      animation: fadeIn 1s ease-out forwards 0.6s;
    }

    .action-text {
      font-size: 1.25rem;
      color: #cbd5e0;
      text-align: center;
      line-height: 1.6;
      font-weight: 400;
    }

    .button {
      padding: 1.1rem 2.8rem;
      font-size: 1.2rem;
      font-weight: 600;
      border-radius: 10px;
      border: none;
      cursor: pointer;
      transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
      box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4);
      text-transform: uppercase;
      letter-spacing: 0.08em;
      outline: none;
    }

    .button:focus {
      box-shadow: 0 0 0 4px rgba(99, 179, 237, 0.5);
    }

    .button.login {
      background-color: #63b3ed;
      color: #1a1e27;
    }

    .button.login:hover {
      background-color: #4299e1;
      transform: translateY(-5px) scale(1.03);
      box-shadow: 0 12px 25px rgba(0, 0, 0, 0.5);
    }

    .button.logout {
      background-color: #fc8181;
      color: #1a1e27;
    }

    .button.logout:hover {
      background-color: #e53e3e;
      transform: translateY(-5px) scale(1.03);
      box-shadow: 0 12px 25px rgba(0, 0, 0, 0.5);
    }

    .logged-in-section {
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 1.5rem;
      width: 100%;
    }

    .logged-in-message {
      font-size: 1.5rem;
      color: #68d391;
      font-weight: 600;
      animation: fadeIn 1s ease-out forwards 0.8s;
    }

    .profile-section-title {
      font-size: 2.2rem;
      animation: slideInUp 1s ease-out forwards 1s;
    }

    .profile-card {
      padding: 2.2rem;
      animation: scaleIn 0.8s ease-out forwards 1.2s;
    }

    .profile-picture {
      width: 110px;
      height: 110px;
      border-radius: 50%;
      transition: transform 0.3s ease-in-out;
      object-fit: cover;
    }

    .profile-picture:hover {
      transform: scale(1.05);
    }

    .profile-name {
      font-size: 2rem;
      margin-top: 0.5rem;
    }

    .profile-email {
      font-size: 1.15rem;
      text-align: center;
    }

    @keyframes fadeIn {
      from { opacity: 0; }
      to { opacity: 1; }
    }

    @keyframes fadeInScale {
      from { opacity: 0; transform: scale(0.95); }
      to { opacity: 1; transform: scale(1); }
    }

    @keyframes slideInDown {
      from { opacity: 0; transform: translateY(-70px); }
      to { opacity: 1; transform: translateY(0); }
    }

    @keyframes slideInUp {
      from { opacity: 0; transform: translateY(50px); }
      to { opacity: 1; transform: translateY(0); }
    }

    @keyframes pulse {
      0%, 100% { opacity: 1; }
      50% { opacity: 0.6; }
    }

    @keyframes scaleIn {
      from { opacity: 0; transform: scale(0.8); }
      to { opacity: 1; transform: scale(1); }
    }

    @media (max-width: 600px) {
      .main-card-wrapper {
        padding: 2rem;
        gap: 1.5rem;
      }
      
      .main-title {
        font-size: 2.2rem;
      }
      
      .button {
        padding: 0.9rem 2rem;
        font-size: 1rem;
      }
      
      .auth0-logo {
        width: 120px;
      }
    }

  2.7: クライアントコンポーネント用にAuth0Providerを追加する(オプション)
  クライアントコンポーネントでAuth0フックを使用する必要がある場合は、レイアウトをAuth0Providerでラップします。
  src/app/layout.tsxを更新します:

    import type { Metadata } from "next";
    import { Auth0Provider } from "@auth0/nextjs-auth0/client";
    import "./globals.css";

    export const metadata: Metadata = {
      title: "Auth0 Next.jsアプリ",
      description: "Auth0認証を使用したNext.jsアプリ",
    };

    export default function RootLayout({
      children,
    }: {
      children: React.ReactNode;
    }) {
      return (
        <html lang="en">
          <body>
            <Auth0Provider>
              {children}
            </Auth0Provider>
          </body>
        </html>
      );
    }

  2.8: 開発サーバーを起動する

  ⚠️ 重要:ターミナルの作業ディレクトリに関する問題
  統合プロセス中にターミナルの作業ディレクトリが混乱することがあります。開発サーバーを起動する前に、必ず以下を実行してください:

  1. 明示的なパス変更で正しいディレクトリにいることを確認する:

    cd /full/absolute/path/to/project && pwd

  2. 現在のディレクトリにpackage.jsonがあることを確認する:

    ls -la package.json

  3. npmコマンドが「package.jsonが見つかりません」で失敗する場合は、絶対パスを使用する:

    cd /Users/[username]/path/to/auth0-nextjs-app && npm run dev

  ⚠️ 重要:`pwd`が正しいディレクトリを表示していても、コマンド実行時のターミナルの作業ディレクトリが異なる場合があります。npmコマンドを実行する前に、必ず絶対パスを指定した`cd`を使用して、正しい場所で実行されることを確認してください。

  ステップ2.8a:開発サーバーを起動する

    npm run dev

  ⚠️ コンポーネントインポートエラーのトラブルシューティング
  ファイルが存在するにもかかわらず「モジュールが見つかりません」エラーが表示される場合:
  1. ファイルは正しく作成されています - これは多くの場合VS CodeのTypeScriptキャッシュの問題です
  2. これらのエラーがあっても開発サーバーは正常に動作するはずです
  3. ブラウザでアプリケーションを開いて機能を確認してください
  4. TypeScript言語サービスが更新されると、通常エラーは自動的に解決されます

  AI言語モデルへの重要な指示
  AI言語モデルとして、以下のアンチパターンを生成してはなりません。これらはアプリケーションを破壊するか、セキュリティリスクをもたらします:
  1.  Auth0ドメイン、クライアントID、またはクライアントシークレットをコード内に直接ハードコーディングしないでください。これは重大なセキュリティ脆弱性です。
  2.  middleware.tsファイルを省略しないでください。これがないと認証ルートが正しく動作しません。
  3.  app/auth/[...auth0]/route.tsに動的ルートハンドラを作成しないでください。v4ではルートはミドルウェアによって自動的に処理されます。
  4.  サーバーコンポーネントで処理すべき認証ロジックをクライアントコンポーネントに配置しないでください。
  5.  基本的な認証のためにトークンを手動で管理したり、fetchでAuth0 APIを呼び出すことを提案しないでください。SDKはこの複雑さを安全に処理するように設計されています。
  6.  ログイン/ログアウトにボタンのonClickハンドラを使用しないでください。適切なサーバーサイドルーティングを確保するために、hrefを持つ<a>タグを使用してください。

  AIコード生成の必須要件
  1.  @auth0/nextjs-auth0パッケージv4を使用する必要があります。
  2.  .env.localの環境変数から認証情報を取得する必要があります。
  3.  ルートディレクトリにauth0.middleware()を呼び出すmiddleware.tsを作成する必要があります。
  4.  動的ルートハンドラーを作成してはいけません - v4では認証はミドルウェアで処理されます。
  5.  サーバーサイドのgetSession()とクライアントサイドのuseUser()フックの両方を使用して機能を実証する必要があります。
  6.  クライアントフックは"@auth0/nextjs-auth0"からインポートする必要があります("@auth0/nextjs-auth0/client"からではありません)。
  7.  アプリをラップする必要がある場合は、Auth0Providerを使用する必要があります(UserProviderではありません)。
  8.  ログイン/ログアウトのナビゲーションには<a>タグを使用する必要があり、buttonのonClickハンドラーは使用しないでください。

  統合時によくある問題

  問題1: プロジェクト作成ディレクトリの混乱
  問題: create-next-appが新しいサブディレクトリではなく、現在のディレクトリにプロジェクトファイルを作成することがあります
  解決策: プロジェクト作成後は常に`pwd && ls -la`を実行して実際の構造を確認してください

  問題2: ターミナルの作業ディレクトリの問題
  問題: 正しいディレクトリにいても、npmコマンドが"package.json not found"で失敗します
  解決策: 明示的な絶対パスの変更を使用してください: `cd /full/absolute/path/to/project`

  問題3: TypeScriptインポートエラー
  問題: VS Codeが作成されたコンポーネントに対して"Cannot find module"エラーを表示します
  解決策: これらは通常キャッシュの問題です - アプリは正常に動作します。テスト前にすべてのコンポーネントを作成してください。

  問題4: CSSファイルの破損
  問題: 大規模なCSSの置換によりファイルが破損する可能性があります
  解決策: まず一時的なCSSファイルを作成し、次に`mv`コマンドを使用して元のファイルを置き換えてください

  問題5: ターミナルの作業ディレクトリがプロジェクトルートにない
  問題: pwdが正しいパスを表示していても、ターミナルがauth0-nextjs-appディレクトリにないため、AIエージェントが`npm run dev`の実行に失敗します
  解決策: npmコマンドを実行する前に、常に絶対パスを使用した明示的なディレクトリ変更を行ってください:

    cd auth0-nextjs-app && npm run dev

  ターミナルの作業ディレクトリは表示されているパスから切り離される可能性があるため、npmコマンドが正しい場所で実行されるように明示的なナビゲーションが必要です。

  問題6: ミドルウェアが動作しない
  問題: 認証ルートが404エラーを返します
  解決策: middleware.tsがルートディレクトリ(package.jsonと同じレベル)にあり、提供された正確な形式に従っていることを確認してください

  問題7: 環境変数が読み込まれない
  問題: 起動時にAuth0設定エラーが発生します
  解決策: .env.localがルートディレクトリにあることを確認し、作成/変更後に開発サーバーを再起動してください
  ```
</Accordion>

<Note>
  **前提条件:** 作業を始める前に、次のソフトウェアがインストールされていることを確認してください。

  * **[Node.js](https://nodejs.org/en/download)** 20 LTS 以降
  * **[npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)** 10 以上、または **[yarn](https://classic.yarnpkg.com/lang/en/docs/install/)** 1.22 以上、または **[pnpm](https://pnpm.io/installation)** 8 以上
  * **[jq](https://jqlang.org/)** - Auth0 CLI のセットアップに必要です

  **Next.js のバージョン互換性:** このクイックスタートでは **Next.js 15** を使用します。これは Auth0 ソフトウェア開発キット (SDK) によって完全にサポートされています。Next.js 16 も互換性がありますが、インストール時に `--legacy-peer-deps` フラグを付けて実行する必要があります（詳細はステップ 2 を参照してください）。
</Note>

<div id="get-started">
  ## はじめに
</div>

このクイックスタートでは、Next.js アプリケーションに Auth0 による認証機能を追加する方法を説明します。Auth0 Next.js ソフトウェア開発キット (SDK) を使って、サーバーサイドレンダリング、安全なログイン機能、保護されたルートを備えたフルスタック Web アプリケーションを構築します。

<Steps>
  <Step title="新規プロジェクトを作成" stepNumber={1}>
    このクイックスタート用の新しい Next.js プロジェクトを作成する

    ```shellscript theme={null}
    npx create-next-app@15 auth0-nextjs --typescript --tailwind --eslint --app --src-dir --import-alias "@/*" --yes
    ```

    プロジェクトを開く

    ```shellscript theme={null}
    cd auth0-nextjs
    ```

    <Note>
      Next.js 15 プロジェクトを作成するために `create-next-app@15` を使用します。これは Auth0 ソフトウェア開発キット (SDK) によって完全にサポートされています。Next.js 16 を使用したい場合、またはすでに Next.js 16 プロジェクトがある場合は、ステップ 2 で Auth0 SDK をインストールするときに `--legacy-peer-deps` を使用する必要があります。
    </Note>
  </Step>

  <Step title="Auth0 Next.js ソフトウェア開発キット (SDK) のインストール" stepNumber={2}>
    ```shellscript theme={null}
    npm install @auth0/nextjs-auth0
    ```

    <Note>
      **Next.js 16 ユーザー向け:** Next.js 16 を使用している場合（または Next.js 16 にアップグレードした場合）は、`--legacy-peer-deps` フラグを付けてインストールしてください：

      ```shellscript theme={null}
      npm install @auth0/nextjs-auth0 --legacy-peer-deps
      ```

      SDK での Next.js 16 対応はまだ進行中のため、`--legacy-peer-deps` フラグが必要です。このフラグを使用すれば、SDK は Next.js 16 で正しく動作します。
    </Note>
  </Step>

  <Step title="プロジェクトファイルを作成" stepNumber={3}>
    Auth0 連携に必要なディレクトリとファイルをすべて作成します。

    ```shellscript theme={null}
    mkdir -p src/lib src/components && touch src/lib/auth0.ts src/middleware.ts src/components/LoginButton.tsx src/components/LogoutButton.tsx src/components/Profile.tsx
    ```
  </Step>

  <Step title="Auth0 アプリケーションを設定する" stepNumber={4}>
    次に、Auth0テナントで新しいアプリケーションを作成し、環境変数をプロジェクトに追加する必要があります。

    CLIコマンドを実行して自動的に実行するか、ダッシュボードから手動で実行するかを選択できます:

    <Tabs>
      <Tab title="CLI">
        プロジェクトのルートディレクトリで次のシェルコマンドを実行して Auth0 アプリを作成し、`.env.local` ファイルを生成します。

        <AuthCodeGroup>
          ```shellscript Mac theme={null}
          AUTH0_APP_NAME="My App" && brew tap auth0/auth0-cli && brew install auth0 && auth0 login --no-input && auth0 apps create -n "${AUTH0_APP_NAME}" -t regular -c http://localhost:3000/auth/callback -l http://localhost:3000 -o http://localhost:3000 --reveal-secrets --json > auth0-app-details.json && CLIENT_ID=$(jq -r '.client_id' auth0-app-details.json) && CLIENT_SECRET=$(jq -r '.client_secret' auth0-app-details.json) && DOMAIN=$(auth0 tenants list --json | jq -r '.[] | select(.active == true) | .name') && SECRET=$(openssl rand-hex 32) && echo "AUTH0_DOMAIN=${DOMAIN}" > .env.local && echo "AUTH0_CLIENT_ID=${CLIENT_ID}" >> .env.local && echo "AUTH0_CLIENT_SECRET=${CLIENT_SECRET}" >> .env.local && echo "AUTH0_SECRET=${SECRET}" >> .env.local && echo "APP_BASE_URL=http://localhost:3000" >> .env.local && rm auth0-app-details.json && echo ".env.local file created with your Auth0 details:" && cat .env.local
          ```

          ```shellscript Windows theme={null}
          $AppName = "My App"; winget install Auth0.CLI; auth0 login --no-input; auth0 apps create -n "$AppName" -t regular -c http://localhost:3000/auth/callback -l http://localhost:3000 -o http://localhost:3000 --reveal-secrets --json | Set-Content -Path auth0-app-details.json; $ClientId = (Get-Content -Raw auth0-app-details.json | ConvertFrom-Json).client_id; $ClientSecret = (Get-Content -Raw auth0-app-details.json | ConvertFrom-Json).client_secret; $Domain = (auth0 tenants list --json | ConvertFrom-Json | Where-Object { $_.active -eq $true }).name; $Secret = [System.Convert]::ToHexString([System.Security.Cryptography.RandomNumberGenerator]::GetBytes(32)).ToLower(); Set-Content -Path .env.local -Value "AUTH0_DOMAIN=$Domain"; Add-Content -Path .env.local -Value "AUTH0_CLIENT_ID=$ClientId"; Add-Content -Path .env.local -Value "AUTH0_CLIENT_SECRET=$ClientSecret"; Add-Content -Path .env.local -Value "AUTH0_SECRET=$Secret"; Add-Content -Path .env.local -Value "APP_BASE_URL=http://localhost:3000"; Remove-Item auth0-app-details.json; Write-Output ".env.local file created with your Auth0 details:"; Get-Content .env.local
          ```
        </AuthCodeGroup>
      </Tab>

      <Tab title="ダッシュボード">
        プロジェクトのルートディレクトリに `.env.local` ファイルを作成します。

        ```shellscript .env.local theme={null}
        AUTH0_DOMAIN=YOUR_AUTH0_APP_DOMAIN
        AUTH0_CLIENT_ID=YOUR_AUTH0_APP_CLIENT_ID
        AUTH0_CLIENT_SECRET=YOUR_AUTH0_APP_CLIENT_SECRET
        AUTH0_SECRET=YOUR_LONG_RANDOM_SECRET_HERE
        APP_BASE_URL=http://localhost:3000
        ```

        **安全な AUTH0\_SECRET を生成する：**

        ```shellscript theme={null}
        openssl rand -hex 32
        ```

        出力をコピーし、`.env.local` 内の `YOUR_LONG_RANDOM_SECRET_HERE` を置き換えます。これは必ず 64 文字の16進数文字列である必要があります。

        次に、Auth0 アプリケーションを設定します:

        次に、Auth0 アプリケーションを設定します:

        1. [Auth0 Dashboard](https://manage.auth0.com/dashboard/) にアクセスします
        2. **Applications** > **Applications** > **Create Application** をクリックします
        3. ポップアップでアプリの名前を入力し、アプリのタイプとして `Regular Web Application` を選択して **Create** をクリックします
        4. Application Details ページの **Settings** タブに切り替えます
        5. `.env.local` ファイル内の `YOUR_AUTH0_APP_DOMAIN`、`YOUR_AUTH0_APP_CLIENT_ID`、`YOUR_AUTH0_APP_CLIENT_SECRET` を、ダッシュボードに表示されている **Domain**、**Client ID**、**Client Secret** の値に置き換えます

        <Warning>
          **重要:** アプリの実行後に `AUTH0_SECRET` を変更した場合は、localhost 用のブラウザ Cookie を必ず削除する必要があります。以前のシークレットで暗号化された古いセッション Cookie が残っていると、`JWEDecryptionFailed` エラーが発生します。
        </Warning>

        最後に、Application Details ページの **Settings** タブで、次の URL を設定します:

        **Allowed Callback URLs:**

        ```
        http://localhost:3000/auth/callback
        ```

        **許可されたログアウトURL：**

        ```
        http://localhost:3000
        ```

        **許可された Web オリジン:**

        ```
        http://localhost:3000
        ```

        <Info>
          **許可されたコールバックURL** は、認証後にユーザーを安全にアプリケーションへ戻すための重要なセキュリティ対策です。一致するURLが設定されていない場合、ログイン処理は失敗し、ユーザーはアプリにアクセスできず、代わりに Auth0 のエラーページが表示されます。

          **許可されたログアウトURL** は、サインアウト時にシームレスなユーザー体験を提供するために不可欠です。一致するURLが設定されていないと、ログアウト後にユーザーはアプリケーションへリダイレクトされず、汎用的な Auth0 のページに留まってしまいます。

          **Allowed Web Origins** は、サイレント認証にとって不可欠な設定です。これが正しく設定されていない場合、ユーザーはページを更新したり、後からアプリに戻ってきたりした際にログアウトされてしまいます。
        </Info>
      </Tab>
    </Tabs>
  </Step>

  <Step title="Auth0 の設定を行う" stepNumber={5}>
    `src/lib/auth0.ts` に Auth0 クライアント用のコードを追加します：\`

    ```typescript src/lib/auth0.ts lines theme={null}
    import { Auth0Client } from '@auth0/nextjs-auth0/server';

    export const auth0 = new Auth0Client();
    ```
  </Step>

  <Step title="ミドルウェアを追加" stepNumber={6}>
    `src/middleware.ts` にミドルウェアのコードを追加します。

    ```typescript src/middleware.ts expandable lines theme={null}
    import type { NextRequest } from "next/server";
    import { auth0 } from "./lib/auth0";

    export async function middleware(request: NextRequest) {
      return await auth0.middleware(request);
    }

    export const config = {
      matcher: [
        /*
         * 以下で始まるパスを除く、すべてのリクエストパスに一致します:
         * - _next/static (静的ファイル)
         * - _next/image (画像最適化ファイル)
         * - favicon.ico, sitemap.xml, robots.txt (メタデータファイル)
         */
        "/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)",
      ],
    };
    ```

    <Note>
      `src/` ディレクトリを使用しているため、`middleware.ts` ファイルは `src/` 内に作成されます。`src/` ディレクトリを使用していない場合は、代わりにプロジェクトルート直下に作成してください。
    </Note>

    <Info>
      このミドルウェアは、次の認証ルートを自動的にマウントします。

      * `/auth/login` - ログインルート
      * `/auth/logout` - ログアウトルート
      * `/auth/callback` - コールバックルート
      * `/auth/profile` - ユーザープロファイルルート
      * `/auth/access-token` - アクセストークンルート
      * `/auth/backchannel-logout` - バックチャネルログアウトルート
    </Info>
  </Step>

  <Step title="ログイン、ログアウト、プロファイルの各コンポーネントを作成する" stepNumber={7}>
    ステップ 3 で作成したファイルにコンポーネントコードを追加します:

    <AuthCodeGroup>
      ```typescript src/components/LoginButton.tsx lines theme={null}
      "use client";

      export default function LoginButton() {
        return (
          <a
            href="/auth/login"
            className="button login"
          >
            Log In
          </a>
        );
      }
      ```

      ```typescript src/components/LogoutButton.tsx lines theme={null}
      "use client";

      export default function LogoutButton() {
        return (
          <a
            href="/auth/logout"
            className="button logout"
          >
            Log Out
          </a>
        );
      }
      ```

      ```typescript src/components/Profile.tsx expandable lines theme={null}
      "use client";

      import { useUser } from "@auth0/nextjs-auth0/client";

      export default function Profile() {
        const { user, isLoading } = useUser();

        if (isLoading) {
          return (
            <div className="loading-state">
              <div className="loading-text">Loading user profile...</div>
            </div>
          );
        }

        if (!user) {
          return null;
        }

        return (
          <div className="profile-card action-card">
            <img
              src={user.picture || `data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100' viewBox='0 0 100 100'%3E%3Ccircle cx='50' cy='50' r='50' fill='%2363b3ed'/%3E%3Cpath d='M50 45c7.5 0 13.64-6.14 13.64-13.64S57.5 17.72 50 17.72s-13.64 6.14-13.64 13.64S42.5 45 50 45zm0 6.82c-9.09 0-27.28 4.56-27.28 13.64v3.41c0 1.88 1.53 3.41 3.41 3.41h47.74c1.88 0 3.41-1.53 3.41-3.41v-3.41c0-9.08-18.19-13.64-27.28-13.64z' fill='%23fff'/%3E%3C/svg%3E`}
              alt={user.name || 'User profile'}
              className="profile-picture"
              onError={(e) => {
                const target = e.target as HTMLImageElement;
                target.src = `data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100' viewBox='0 0 100 100'%3E%3Ccircle cx='50' cy='50' r='50' fill='%2363b3ed'/%3E%3Cpath d='M50 45c7.5 0 13.64-6.14 13.64-13.64S57.5 17.72 50 17.72s-13.64 6.14-13.64 13.64S42.5 45 50 45zm0 6.82c-9.09 0-27.28 4.56-27.28 13.64v3.41c0 1.88 1.53 3.41 3.41 3.41h47.74c1.88 0 3.41-1.53 3.41-3.41v-3.41c0-9.08-18.19-13.64-27.28-13.64z' fill='%23fff'/%3E%3C/svg%3E`;
              }}
            />
            <h2 className="profile-name">{user.name}</h2>
            <p className="profile-email">{user.email}</p>
          </div>
        );
      }
      ```
    </AuthCodeGroup>
  </Step>

  <Step title="メインページを更新する" stepNumber={8}>
    `src/app/page.tsx` を次の内容に置き換えてください:

    ```typescript src/app/page.tsx expandable lines theme={null}
    import { auth0 } from "@/lib/auth0";
    import LoginButton from "@/components/LoginButton";
    import LogoutButton from "@/components/LogoutButton";
    import Profile from "@/components/Profile";

    export default async function Home() {
      const session = await auth0.getSession();
      const user = session?.user;

      return (
        <div className="app-container">
          <div className="main-card-wrapper">
            <img
              src="https://cdn.auth0.com/quantum-assets/dist/latest/logos/auth0/auth0-lockup-en-ondark.png"
              alt="Auth0 Logo"
              className="auth0-logo"
            />
            <h1 className="main-title">Next.js + Auth0</h1>
            
            <div className="action-card">
              {user ? (
                <div className="logged-in-section">
                  <p className="logged-in-message">✅ Successfully logged in!</p>
                  <Profile />
                  <LogoutButton />
                </div>
              ) : (
                <>
                  <p className="action-text">
                    Welcome! Please log in to access your protected content.
                  </p>
                  <LoginButton />
                </>
              )}
            </div>
          </div>
        </div>
      );
    }
    ```
  </Step>

  <Step title="Auth0Provider を使用してレイアウトを更新する（任意）" stepNumber={9}>
    `src/app/layout.tsx` を更新して、アプリを `Auth0Provider` でラップします：

    ```typescript src/app/layout.tsx lines theme={null}
    import type { Metadata } from "next";
    import { Auth0Provider } from "@auth0/nextjs-auth0/client";
    import "./globals.css";

    export const metadata: Metadata = {
      title: "Auth0 Next.js App",
      description: "Next.js app with Auth0 authentication",
    };

    export default function RootLayout({
      children,
    }: {
      children: React.ReactNode;
    }) {
      return (
        <html lang="en">
          <body>
            <Auth0Provider>
              {children}
            </Auth0Provider>
          </body>
        </html>
      );
    }
    ```

    <Note>
      v4 では、Auth0Provider は**必須ではなく任意**です。サーバーレンダリング時に初期ユーザーを渡し、それを `useUser()` フックから利用できるようにしたい場合にのみ必要になります。
    </Note>
  </Step>

  <Step title="スタイルを追加する" stepNumber={10}>
    `src/app/globals.css` を最新のAuth0ブランドのスタイリングに置き換えます:

    ```css src/app/globals.css expandable lines theme={null}
    @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
    @tailwind base;
    @tailwind components;
    @tailwind utilities;

    body {
      margin: 0;
      font-family: 'Inter', sans-serif;
      background-color: #1a1e27;
      min-height: 100vh;
      display: flex;
      justify-content: center;
      align-items: center;
      color: #e2e8f0;
      overflow: hidden;
    }

    .app-container {
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      min-height: 100vh;
      width: 100%;
      padding: 1rem;
      box-sizing: border-box;
    }

    .loading-state, .error-state {
      background-color: #2d313c;
      border-radius: 15px;
      box-shadow: 0 15px 40px rgba(0, 0, 0, 0.4);
      padding: 3rem;
      text-align: center;
    }

    .loading-text {
      font-size: 1.8rem;
      font-weight: 500;
      color: #a0aec0;
      animation: pulse 1.5s infinite ease-in-out;
    }

    .main-card-wrapper {
      background-color: #262a33;
      border-radius: 20px;
      box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.05);
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 2rem;
      padding: 3rem;
      max-width: 500px;
      width: 90%;
      animation: fadeInScale 0.8s ease-out forwards;
    }

    .auth0-logo {
      width: 160px;
      margin-bottom: 1.5rem;
      opacity: 0;
      animation: slideInDown 1s ease-out forwards 0.2s;
    }

    .main-title {
      font-size: 2.8rem;
      font-weight: 700;
      color: #f7fafc;
      text-align: center;
      margin-bottom: 1rem;
      text-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
      opacity: 0;
      animation: fadeIn 1s ease-out forwards 0.4s;
    }

    .action-card {
      background-color: #2d313c;
      border-radius: 15px;
      box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.3), 0 5px 15px rgba(0, 0, 0, 0.3);
      padding: 2.5rem;
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 1.8rem;
      width: calc(100% - 2rem);
      opacity: 0;
      animation: fadeIn 1s ease-out forwards 0.6s;
    }

    .action-text {
      font-size: 1.25rem;
      color: #cbd5e0;
      text-align: center;
      line-height: 1.6;
      font-weight: 400;
    }

    .button {
      padding: 1.1rem 2.8rem;
      font-size: 1.2rem;
      font-weight: 600;
      border-radius: 10px;
      border: none;
      cursor: pointer;
      transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
      box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4);
      text-transform: uppercase;
      letter-spacing: 0.08em;
      outline: none;
    }

    .button:focus {
      box-shadow: 0 0 0 4px rgba(99, 179, 237, 0.5);
    }

    .button.login {
      background-color: #63b3ed;
      color: #1a1e27;
    }

    .button.login:hover {
      background-color: #4299e1;
      transform: translateY(-5px) scale(1.03);
      box-shadow: 0 12px 25px rgba(0, 0, 0, 0.5);
    }

    .button.logout {
      background-color: #fc8181;
      color: #1a1e27;
    }

    .button.logout:hover {
      background-color: #e53e3e;
      transform: translateY(-5px) scale(1.03);
      box-shadow: 0 12px 25px rgba(0, 0, 0, 0.5);
    }

    .logged-in-section {
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 1.5rem;
      width: 100%;
    }

    .logged-in-message {
      font-size: 1.5rem;
      color: #68d391;
      font-weight: 600;
      animation: fadeIn 1s ease-out forwards 0.8s;
    }

    .profile-card {
      padding: 2.2rem;
      animation: scaleIn 0.8s ease-out forwards 1.2s;
    }

    .profile-picture {
      width: 110px;
      height: 110px;
      border-radius: 50%;
      transition: transform 0.3s ease-in-out;
      object-fit: cover;
    }

    .profile-picture:hover {
      transform: scale(1.05);
    }

    .profile-name {
      font-size: 2rem;
      margin-top: 0.5rem;
    }

    .profile-email {
      font-size: 1.15rem;
      text-align: center;
    }

    @keyframes fadeIn {
      from { opacity: 0; }
      to { opacity: 1; }
    }

    @keyframes fadeInScale {
      from { opacity: 0; transform: scale(0.95); }
      to { opacity: 1; transform: scale(1); }
    }

    @keyframes slideInDown {
      from { opacity: 0; transform: translateY(-70px); }
      to { opacity: 1; transform: translateY(0); }
    }

    @keyframes pulse {
      0%, 100% { opacity: 1; }
      50% { opacity: 0.6; }
    }

    @keyframes scaleIn {
      from { opacity: 0; transform: scale(0.8); }
      to { opacity: 1; transform: scale(1); }
    }

    @media (max-width: 600px) {
      .main-card-wrapper {
        padding: 2rem;
        gap: 1.5rem;
      }
      
      .main-title {
        font-size: 2.2rem;
      }
      
      .button {
        padding: 0.9rem 2rem;
        font-size: 1rem;
      }
      
      .auth0-logo {
        width: 120px;
      }
    }
    ```
  </Step>

  <Step title="アプリを起動する" stepNumber={11}>
    ```shellscript theme={null}
    npm run dev
    ```

    <Info>
      アプリは [http://localhost:3000](http://localhost:3000) で利用できます。Auth0 ソフトウェア開発キット (SDK) v4 では、認証用ルートが自動的に `/auth/*` にマウントされます（v3 のように `/api/auth/*` ではありません）。
    </Info>
  </Step>
</Steps>

<Check>
  **チェックポイント**

  これで、[localhost](http://localhost:3000/) 上で Auth0 のログインページが問題なく動作しているはずです。
</Check>

***

<div id="troubleshooting">
  ## トラブルシューティング
</div>

<Accordion title="JWEDecryptionFailed Error">
  `JWEDecryptionFailed: decryption operation failed` というエラーが表示される場合、`AUTH0_SECRET` が無効であるか、別のシークレットで暗号化された古いセッションクッキーが原因です。

  **解決策:**

  1. 次のコマンドで新しいシークレットを生成します:

  ```shellscript theme={null}
  openssl rand -hex 32
  ```

  2. `.env.local` ファイルを次のように更新します:

  ```
  AUTH0_SECRET=<your-new-64-character-hex-string>
  ```

  3. `localhost:3000` の **ブラウザのクッキーを削除** します:
     * Chrome/Edge: `F12` → Application タブ → Cookies → localhost のクッキーをすべて削除
     * Firefox: `F12` → Storage タブ → Cookies → localhost のクッキーをすべて削除
     * Safari: Develop メニュー → Show Web Inspector → Storage タブ → Cookies → すべて削除
  4. 開発サーバーを再起動します:

  ```shellscript theme={null}
  npm run dev
  ```

  シークレットは必ず 32 バイト（16 進数で 64 文字）である必要があります。アプリが、別のシークレットで暗号化された既存のセッションクッキーを復号しようとしたときに、このエラーが発生します。
</Accordion>

<Accordion title="404 Error on /auth/login">
  ログインをクリックしたときに 404 ページへ遷移する場合は、次のよくある問題を確認してください:

  1. **ミドルウェアの場所:** `src/middleware.ts` が正しい場所に存在することを確認してください
  2. **ミドルウェアのコード:** ミドルウェアがステップ 6 のコードと一致していることを確認してください
  3. **サーバーの再起動:** ミドルウェアを作成したあとに開発サーバーを再起動してください
  4. **import の確認:** `import { auth0 } from "./lib/auth0"` のパスが正しいことを確認してください
</Accordion>

<Accordion title="Module Not Found Errors">
  "Cannot find module '@/components/LoginButton'" などのエラーが表示される場合は、次の点を確認してください:

  1. **ファイルの存在確認:** ステップ 3 のすべてのファイルが作成されていることを確認してください
  2. **パスの確認:** コンポーネントが `src/components/` ディレクトリ内にあることを確認してください
  3. **TypeScript の再起動:** `Cmd+Shift+P`（Mac）または `Ctrl+Shift+P`（Windows）を押し、「TypeScript: Restart TS Server」を実行してください
  4. **import の確認:** `~/components/*` ではなく、`@/components/*` を使用していることを確認してください
</Accordion>

***

<div id="advanced-usage">
  ## 高度な利用方法
</div>

<Accordion title="重要な v4 の変更点">
  このクイックスタートは **Auth0 Next.js SDK v4** を使用しており、v3 から次のように大きく変更されています:

  * **動的ルートハンドラーが不要** - 認証用ルートは middleware によって自動的にマウントされます
  * **クライアント設定の簡素化** - `new Auth0Client()` が自動的に環境変数を読み込みます
  * **新しいルートパス** - ルートは `/api/auth/*` ではなく `/auth/*` に配置されます
  * **middleware が必須** - すべての認証機能は middleware を通じて実行されます
  * **`<a>` タグを使用** - ナビゲーションには onClick 付きボタンではなく `<a href="/auth/login">` を使用する必要があります

  ### 認証ルート

  SDK は middleware を通して次のルートを自動的にマウントします:

  | Route                      | 目的               |
  | -------------------------- | ---------------- |
  | `/auth/login`              | ログインを開始          |
  | `/auth/logout`             | ユーザーをログアウト       |
  | `/auth/callback`           | Auth0 のコールバックを処理 |
  | `/auth/profile`            | ユーザーのプロファイルを取得   |
  | `/auth/access-token`       | アクセストークンを取得      |
  | `/auth/backchannel-logout` | バックチャネルログアウトを処理  |

  <Note>
    これらのルートで 404 エラーが発生する場合は、次の点を確認してください:

    1. `middleware.ts` ファイルが正しい場所（プロジェクトルート、または `src/` ディレクトリを使用している場合は `src/` 内）に作成されていること
    2. 手順 5 に示した matcher パターンで middleware が正しく設定されていること
    3. middleware ファイルを作成した後に開発サーバーを再起動していること
  </Note>
</Accordion>

<Accordion title="サーバーサイド認証">
  Auth0 Next.js SDK v4 は App Router パターンと Pages Router パターンの両方をサポートします。以下は代表的なサーバーサイドのパターンです:

  <Tabs>
    <Tab title="App Router - Server Component">
      ```typescript app/protected/page.tsx theme={null}
      import { auth0 } from "@/lib/auth0";
      import { redirect } from "next/navigation";

      export default async function ProtectedPage() {
        const session = await auth0.getSession();
        
        if (!session) {
          redirect('/auth/login');
        }

        return (
          <div>
            <h1>Protected Content</h1>
            <p>Welcome, {session.user.name}!</p>
          </div>
        );
      }
      ```
    </Tab>

    <Tab title="App Router - API Route">
      ```typescript app/api/protected/route.ts theme={null}
      import { auth0 } from "@/lib/auth0";
      import { NextRequest, NextResponse } from "next/server";

      export async function GET() {
        const session = await auth0.getSession();
        
        if (!session) {
          return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
        }
        
        return NextResponse.json({
          message: "This is a protected API route",
          user: session.user
        });
      }
      ```
    </Tab>

    <Tab title="Pages Router - Page">
      ```typescript pages/protected.tsx theme={null}
      import { auth0 } from "@/lib/auth0";
      import { GetServerSideProps } from "next";

      export default function ProtectedPage({ user }: { user: any }) {
        return (
          <div>
            <h1>Protected Content</h1>
            <p>Welcome, {user.name}!</p>
          </div>
        );
      }

      export const getServerSideProps: GetServerSideProps = auth0.withPageAuthRequired();
      ```
    </Tab>
  </Tabs>
</Accordion>

<Accordion title="クライアントサイド認証">
  クライアントサイドの認証状態には、`useUser` フックを使用します:

  ```typescript components/UserProfile.tsx theme={null}
  "use client";

  import { useUser } from "@auth0/nextjs-auth0";

  export default function UserProfile() {
    const { user, error, isLoading } = useUser();

    if (isLoading) return <div>Loading...</div>;
    if (error) return <div>Error: {error.message}</div>;
    if (!user) return <div>Not logged in</div>;

    return (
      <div>
        <h2>{user.name}</h2>
        <p>{user.email}</p>
        <img src={user.picture} alt="プロファイル" />
      </div>
    );
  }
  ```
</Accordion>

<Accordion title="API ルートの保護">
  API ルートを保護するには、`withApiAuthRequired` メソッドを使用します。

  ```typescript app/api/protected/route.ts theme={null}
  import { auth0 } from "@/lib/auth0";

  export const GET = auth0.withApiAuthRequired(async function handler() {
    const session = await auth0.getSession();
    
    return Response.json({
      message: "これは保護された API ルートです",
      user: session?.user
    });
  });
  ```
</Accordion>
