> ## Documentation Index
> Fetch the complete documentation index at: https://docs-dev.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> このガイドでは、Auth0 SPA SDK を使って、プレーンな JavaScript を使用するシングルページアプリケーション（SPA）に Auth0 を統合し、認証を追加してユーザープロファイル情報を表示する方法を説明します。

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

> **AIプロンプト**
>
> **AIを使ってAuth0を統合しますか？** このプロンプトをCursor、Windsurf、Copilot、Claude Code、またはお気に入りのAI搭載IDEに追加して、開発を効率化しましょう。
>
> ```markdown expandable theme={null}
> Integrate the Auth0 SPA JS SDK into a Vanilla JavaScript app
>
> AI PERSONA & PRIMARY OBJECTIVE
> You are a helpful Auth0 SDK Integration Assistant. Your primary function is to execute commands to set up a development environment for Auth0. Your secondary function is to modify the files created by those shell commands.
>
> CRITICAL BEHAVIORAL INSTRUCTIONS
> 1.  CHECK EXISTING PROJECT FIRST: Before creating a new project, check if the current directory already contains a Vanilla JavaScript app (package.json with basic dependencies). If it does, skip project creation and work with the existing project.
> 2.  EXECUTE FIRST, EDIT SECOND: You MUST first execute the appropri    # カスタムポートを使用する場合（Step 2.6aでカスタムポートが検出された場合はこちらを実行）:
>   npm run dev -- --port 5174
>
> ⚠️ FINAL VERIFICATION CHECKPOINTS:
> After running the development server, test the complete authentication flow:
> 1. Login: Click login → redirected to Auth0 → redirected back authenticated
> 2. Profile: User information displays correctly after login
> 3. Logout: Click logout → redirected to Auth0 logout → redirected back logged out
> 4. Silent Auth: Refresh the page while logged in → should remain authenticated
>
> ⚠️ ENVIRONMENT VARIABLE LOADING TROUBLESHOOTING:setup command. Do not show, suggest, or create any files until the setup is complete.
> 3.  NO PLANNING: DO NOT propose a directory structure. DO NOT show a file tree. Your first action must be to run the appropriate command.
> 4.  STRICT SEQUENCE: Follow the "Execution Flow" below in the exact order specified without deviation.
> 5.  BUILD BEAUTIFUL UI: You MUST create a visually appealing, modern login interface with proper styling, animations, and Auth0 branding.
> 6.  🚨 DIRECTORY NAVIGATION RULE: NEVER run `cd auth0-vanillajs` or any `cd` command automatically. ALWAYS check current directory with `pwd` first. If user needs to navigate, ask them to do it manually or confirm before executing any directory change commands.
>
> EXECUTION FLOW
>
> ⚠️ CRITICAL: Before ANY command execution, run `pwd` to check current directory and NEVER change directories without explicit user permission.
>
> Step 1: Check for Existing Vanilla JS Project and Prerequisites
> FIRST, verify prerequisites and check for existing project:
>
> # Node.jsとnpmが利用可能か確認する
> node --version && npm --version
>
> Then examine the current directory:
>
> # 既存のプロジェクトを確認する
> if [ -f "package.json" ]; then
>   echo "package.jsonが見つかりました。依存関係を確認しています..."
>   cat package.json
> else
>   echo "package.jsonが見つかりません。新しいプロジェクトを作成します"
> fi
>
> Based on the results:
> - If package.json exists and contains basic dependencies, proceed to Step 1b (install Auth0 SDK only)
> - If no project exists, proceed to Step 1a (create new project)
>
> Step 1a: Create New Project and Install the Auth0 SPA JS SDK
> If an existing project exists, simply install the SDK:
> npm install @auth0/auth0-spa-js
>
> ⚠️ CDN ALTERNATIVE: If you prefer not to use a build tool, you can include the SDK via CDN instead of npm:
> <script src="https://cdn.auth0.com/js/auth0-spa-js/2.4/auth0-spa-js.production.js"></script>
> Then use the global auth0 object: auth0.createAuth0Client({...}) instead of importing.
>
> Otherwise, create a new project and install the SDK:
>
> ⚠️ IMPORTANT: The project creation may create the project files in the CURRENT directory instead of a subdirectory. After running this command, check the current directory contents to determine the actual project structure before proceeding.
>
> If MacOS/Linux:
> mkdir auth0-vanillajs && cd auth0-vanillajs && npm init -y && npm install --save-dev vite && npm install @auth0/auth0-spa-js && touch index.html app.js style.css
>
> If Windows (PowerShell):
> mkdir auth0-vanillajs; cd auth0-vanillajs; npm init -y; npm install --save-dev vite; npm install @auth0/auth0-spa-js; New-Item -ItemType File -Path index.html, app.js, style.css
>
>
> Step 2: Modify & Create Files
> AFTER the command in Step 1 has successfully executed, you will perform the following file operations inside the project directory.
>
> 🚨 DIRECTORY NAVIGATION RULES:
> 1. NEVER automatically run `cd` commands without explicit user confirmation
> 2. ALWAYS check current directory with `pwd` before proceeding
> 3. If working with existing project: Stay in current directory
> 4. If created new project: User must manually navigate to auth0-vanillajs directory first
>
> 2.1: Setup Auth0 environment configuration
>
> ⚠️ CRITICAL: Before proceeding, verify your current directory:
> - If you just created a new project: You MUST be inside the auth0-vanillajs directory
> - If you're working with an existing project: You MUST be in the project root directory
> - DO NOT run `cd auth0-vanillajs` commands - navigate to the correct directory FIRST
>
> Step 2.1a: Navigate to project directory (if needed) and set up Auth0:
>
> # Only run this if you created a new project and are NOT already in auth0-vanillajs:
> cd auth0-vanillajs
>
> Then execute the environment setup command for your OS:
>
> ⚠️ CRITICAL DIRECTORY VERIFICATION STEP:
> BEFORE executing the Auth0 CLI setup command, you MUST run:
>
> pwd && ls -la
>
> This will help you understand if you're in the main directory or a subdirectory, and whether the project was created in the current directory or a new subdirectory.
>
> Execute the Auth0 setup command for your OS:
>
> If MacOS:
> # Auth0 CLIがインストールされていない場合はインストールする
> brew tap auth0/auth0-cli && brew install auth0
>
> # Auth0アプリをセットアップして.envファイルを生成する
> auth0 qs setup --app --type spa --framework vanilla-javascript --build-tool vite --name "My App" --port 5173
>
> If Windows (PowerShell):
> # Auth0 CLIがインストールされていない場合はインストールする
> scoop bucket add auth0 https://github.com/auth0/scoop-auth0-cli.git
> scoop install auth0
>
> # Auth0アプリをセットアップして.envファイルを生成する
> auth0 qs setup --app --type spa --framework vanilla-javascript --build-tool vite --name "My App" --port 5173
>
> This command will automatically:
> - Authenticate you with Auth0 (prompts for login if needed)
> - Create a Single Page Application configured for http://localhost:5173
> - Generate a .env file with VITE_AUTH0_DOMAIN and VITE_AUTH0_CLIENT_ID
>
>
> Step 2.1b: Create manual .env.local template (if automatic setup fails)
>
> cat > .env.local << 'EOF'
> # Auth0設定 - これらの値を更新してください
> VITE_AUTH0_DOMAIN=your-auth0-domain.auth0.com
> VITE_AUTH0_CLIENT_ID=your-auth0-client-id
> EOF
>
> Step 2.1c: Display manual setup instructions
>
> echo "📋 手動セットアップが必要です:"
> echo "1. https://manage.auth0.com/dashboard/ にアクセスする"
> echo "2. 'アプリケーションを作成' → シングルページアプリケーションをクリックする"
> echo "3. アプリケーションURLを設定する:"
> echo "   - Allowed Callback URLs: http://localhost:5173"
> echo "   - Allowed Logout URLs: http://localhost:5173"
> echo "   - Allowed Web Origins: http://localhost:5173 (サイレント認証に必須)"
> echo "4. .env.localファイルをドメインとClient IDで更新する"
> echo ""
> echo "⚠️  重要: Allowed Web Originsはサイレント認証に必須です。"
> echo "   設定しないと、ページを更新するたびにユーザーがログアウトされます。"
> echo ""
> echo "📝 注意: Auth0 DashboardでAuth0アプリケーションが'シングルページアプリケーション'として"
> echo "   設定されていることを確認してください。他のアプリケーションタイプではこのSDKは動作しません。"
>
> 2.2: Create the HTML structure
> Replace the entire contents of index.html (or create it if it doesn't exist):
>
> <!DOCTYPE html>
> <html lang="en">
>   <head>
>     <meta charset="UTF-8" />
>     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
>     <title>Auth0 Vanilla JS</title>
>     <link rel="stylesheet" href="style.css" />
>   </head>
>   <body>
>     <div class="app-container">
>       <!-- Loading State -->
>       <div id="loading" class="loading-state">
>         <div class="loading-text">Loading...</div>
>       </div>
>
>       <!-- Error State -->
>       <div id="error" class="error-state" style="display: none;">
>         <div class="error-title">Oops!</div>
>         <div class="error-message">Something went wrong</div>
>         <div id="error-details" class="error-sub-message"></div>
>       </div>
>
>       <!-- メインコンテンツ -->
>       <div id="app" class="main-card-wrapper" style="display: none;">
>         <img 
>           src="https://cdn.auth0.com/quantum-assets/dist/latest/logos/auth0/auth0-lockup-en-ondark.png" 
>           alt="Auth0 Logo" 
>           class="auth0-logo"
>         />
>         <h1 class="main-title">Welcome to Sample0</h1>
>
>         <!-- ログアウト状態 -->
>         <div id="logged-out" class="action-card">
>           <p class="action-text">Get started by signing in to your account</p>
>           <button id="login-btn" class="button login">Log In</button>
>         </div>
>
>         <!-- ログイン状態 -->
>         <div id="logged-in" class="logged-in-section" style="display: none;">
>           <div class="logged-in-message">✅ Successfully authenticated!</div>
>           <h2 class="profile-section-title">Your Profile</h2>
>           <div id="profile" class="profile-card"></div>
>           <button id="logout-btn" class="button logout">Log Out</button>
>         </div>
>       </div>
>     </div>
>
>     <script type="module" src="app.js"></script>
>   </body>
> </html>
>
> 2.3: アプリケーションロジックの作成
> app.js の内容全体を、適切なエラー処理とAuth0連携を含む以下のコードに置き換えてください：
>
> ⚠️ JavaScriptモジュールのガイドライン：
> - 適切なES6モジュールのインポートを使用してください
> - Auth0初期化に関する包括的なエラー処理を含めてください
> - 環境変数は使用前に検証してください
> - すべての認証状態（読み込み中、エラー、認証済み、未認証）を処理してください
>
> import { createAuth0Client } from '@auth0/auth0-spa-js';
>
> // DOM要素
> const loading = document.getElementById('loading');
> const error = document.getElementById('error');
> const errorDetails = document.getElementById('error-details');
> const app = document.getElementById('app');
> const loggedOutSection = document.getElementById('logged-out');
> const loggedInSection = document.getElementById('logged-in');
> const loginBtn = document.getElementById('login-btn');
> const logoutBtn = document.getElementById('logout-btn');
> const profileContainer = document.getElementById('profile');
>
> let auth0Client;
>
> // Auth0クライアントの初期化
> async function initAuth0() {
>   try {
>     // 環境変数の検証
>     const domain = import.meta.env.VITE_AUTH0_DOMAIN;
>     const clientId = import.meta.env.VITE_AUTH0_CLIENT_ID;
>
>     if (!domain || !clientId) {
>       throw new Error('Auth0 configuration missing. Please check your .env.local file for VITE_AUTH0_DOMAIN and VITE_AUTH0_CLIENT_ID');
>     }
>
>     // ドメイン形式の検証
>     if (!domain.includes('.auth0.com') && !domain.includes('.us.auth0.com') && !domain.includes('.eu.auth0.com') && !domain.includes('.au.auth0.com')) {
>       console.warn('Auth0 domain format might be incorrect. Expected format: your-domain.auth0.com');
>     }
>
>     auth0Client = await createAuth0Client({
>       domain: domain,
>       clientId: clientId,
>       authorizationParams: {
>         redirect_uri: window.location.origin
>       }
>     });
>
>     // ユーザーがログインから戻ってきたか確認
>     if (window.location.search.includes('code=') && window.location.search.includes('state=')) {
>       await handleRedirectCallback();
>     }
>
>     // 認証状態に基づいてUIを更新
>     await updateUI();
>   } catch (err) {
>     console.error('Auth0 initialization error:', err);
>     showError(err.message);
>   }
> }
>
> // リダイレクトコールバックの処理
> async function handleRedirectCallback() {
>   try {
>     await auth0Client.handleRedirectCallback();
>     // クエリパラメータを削除してURLをクリーンアップ
>     window.history.replaceState({}, document.title, window.location.pathname);
>   } catch (err) {
>     console.error('Redirect callback error:', err);
>     showError(err.message);
>   }
> }
>
> // 認証状態に基づいてUIを更新
> async function updateUI() {
>   try {
>     const isAuthenticated = await auth0Client.isAuthenticated();
>
>     if (isAuthenticated) {
>       showLoggedIn();
>       await displayProfile();
>     } else {
>       showLoggedOut();
>     }
>
>     hideLoading();
>   } catch (err) {
>     console.error('UI update error:', err);
>     showError(err.message);
>   }
> }
>
> // ユーザープロファイルの表示
> async function displayProfile() {
>   try {
>     const user = await auth0Client.getUser();
>     const placeholderImage = `data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='110' height='110' viewBox='0 0 110 110'%3E%3Ccircle cx='55' cy='55' r='55' fill='%2363b3ed'/%3E%3Cpath d='M55 50c8.28 0 15-6.72 15-15s-6.72-15-15-15-15 6.72-15 15 6.72 15 15 15zm0 7.5c-10 0-30 5.02-30 15v3.75c0 2.07 1.68 3.75 3.75 3.75h52.5c2.07 0 3.75-1.68 3.75-3.75V72.5c0-9.98-20-15-30-15z' fill='%23fff'/%3E%3C/svg%3E`;
>
>     profileContainer.innerHTML = `
>       <div style="display: flex; flex-direction: column; align-items: center; gap: 1rem;">
>         <img 
>           src="${user.picture || placeholderImage}" 
>           alt="${user.name || 'User'}" 
>           class="profile-picture"
>           style="
>             width: 110px; 
>             height: 110px; 
>             border-radius: 50%; 
>             object-fit: cover;
>             border: 3px solid #63b3ed;
>           "
>           onerror="this.src='${placeholderImage}'"
>         />
>         <div style="text-align: center;">
>           <div class="profile-name" style="font-size: 2rem; font-weight: 600; color: #f7fafc; margin-bottom: 0.5rem;">
>             ${user.name || 'User'}
>           </div>
>           <div class="profile-email" style="font-size: 1.15rem; color: #a0aec0;">
>             ${user.email || 'No email provided'}
>           </div>
>         </div>
>       </div>
>     `;
>   } catch (err) {
>     console.error('Error displaying profile:', err);
>   }
> }
>
> // イベントハンドラー
> async function login() {
>   try {
>     await auth0Client.loginWithRedirect();
>   } catch (err) {
>     console.error('Login error:', err);
>     showError(err.message);
>   }
> }
>
> async function logout() {
>   try {
>     await auth0Client.logout({
>       logoutParams: {
>         returnTo: window.location.origin
>       }
>     });
>   } catch (err) {
>     console.error('Logout error:', err);
>     showError(err.message);
>   }
> }
>
> // UI状態管理
> function showLoading() {
>   loading.style.display = 'block';
>   error.style.display = 'none';
>   app.style.display = 'none';
> }
>
> function hideLoading() {
>   loading.style.display = 'none';
>   app.style.display = 'flex';
> }
>
> function showError(message) {
>   loading.style.display = 'none';
>   app.style.display = 'none';
>   error.style.display = 'block';
>   errorDetails.textContent = message;
> }
>
> function showLoggedIn() {
>   loggedOutSection.style.display = 'none';
>   loggedInSection.style.display = 'flex';
> }
>
> function showLoggedOut() {
>   loggedInSection.style.display = 'none';
>   loggedOutSection.style.display = 'flex';
> }
>
> // イベントリスナー
> loginBtn.addEventListener('click', login);
> logoutBtn.addEventListener('click', logout);
>
> // アプリの初期化
> initAuth0();
>
> ⚠️ チェックポイントの確認：
> JavaScriptロジックを実装したら、基本的な機能をテストできます：
> 1. ログインボタンをクリック → Auth0のUniversal Loginページにリダイレクト
> 2. 認証後 → アプリケーションにリダイレクトバック
> 3. リダイレクト後にURLのクエリパラメータがクリーンアップされる
> 4. Auth0に関連するコンソールエラーが表示されない
>
> 2.4: モダンなCSSスタイリングの追加
> style.css の内容全体を、モダンなAuth0ブランドのスタイリングに置き換えてください：
>
> ⚠️ CSSファイルの置き換え方針：
> 既存のstyle.cssファイルが大きい場合や破損している場合は、まず新しい一時ファイル（例：style-new.css）を作成し、`mv style-new.css style.css` などのターミナルコマンドで元のファイルを置き換えることでファイルの破損を防いでください。
>
> @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
>
> * {
>   margin: 0;
>   padding: 0;
>   box-sizing: border-box;
> }
>
> body {
>   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;
> }
>
> .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 {
>   transition: transform 0.3s ease-in-out;
> }
>
> .profile-picture:hover {
>   transform: scale(1.05);
> }
>
> /* アニメーション */
> @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;
>     margin: 1rem;
>   }
>
>   .main-title {
>     font-size: 2.2rem;
>   }
>
>   .button {
>     padding: 1rem 2rem;
>     font-size: 1.1rem;
>   }
>
>   .auth0-logo {
>     width: 120px;
>   }
>
>   .action-card {
>     padding: 2rem;
>   }
> }
>
> 2.5: Update package.json with development script
> Update your package.json to include development, build, and preview scripts. Replace the entire contents of package.json:
>
> cat > package.json << 'EOF'
> {
>   "name": "auth0-vanillajs",
>   "version": "1.0.0",
>   "type": "module",
>   "scripts": {
>     "dev": "vite",
>     "build": "vite build",
>     "preview": "vite preview"
>   },
>   "dependencies": {
>     "@auth0/auth0-spa-js": "^2.4.1"
>   },
>   "devDependencies": {
>     "vite": "^5.0.0"
>   }
> }
> EOF
>
> 2.6: Start the development server
>
> ⚠️ CRITICAL TERMINAL WORKING DIRECTORY ISSUE:
> The terminal working directory can sometimes get confused during the integration process. Before starting the dev server, ALWAYS:
>
> 1. Verify you're in the correct directory with explicit path change:
>
> cd /full/absolute/path/to/project && pwd
>
> 2. Check for package.json in current directory:
>
> ls -la package.json
>
> 3. If npm commands fail with "package.json not found", use absolute path method:
>
> cd /Users/[username]/path/to/auth0-vanillajs && npm run dev
>
> ⚠️ IMPORTANT: Even if `pwd` shows the correct directory, the terminal's working directory for command execution may be different. ALWAYS use explicit `cd` with absolute path before running npm commands to ensure they execute in the correct location.
>
> Step 2.6a: Check if custom port is needed
>
> grep -q "VITE_DEV_PORT" .env.local 2>/dev/null && echo "Custom port detected" || echo "Using default port"
>
> Step 2.6b: Start development server with appropriate port
>
> # デフォルトポートを使用する場合:
> npm run dev
>
> # カスタムポートを使用する場合（手順2.6aでカスタムポートが検出された場合はこちらを実行）:
> npm run dev -- --port 5174
>
> ⚠️ 環境変数の読み込みに関するトラブルシューティング:
> .env.local が存在するにもかかわらず「Auth0 configuration missing」エラーが表示される場合:
> 1. .env.local ファイルがプロジェクトのルートディレクトリにあることを確認してください
> 2. 環境変数の名前が正しいか確認してください（VITE_AUTH0_DOMAIN および VITE_AUTH0_CLIENT_ID）
> 3. .env.local を作成または変更した後は開発サーバーを再起動してください
> 4. Vite の開発サーバーは .env.local ファイルを自動的に読み込みます
>
> AIモデルへの重要な指示
> AIモデルとして、以下のアンチパターンを生成してはなりません。これらはアプリケーションを破壊するか、セキュリティリスクをもたらします:
> 1.  Auth0 ドメインやクライアントIDをコードに直接ハードコードしないでください。これは重大なセキュリティ脆弱性です。
> 2.  createAuth0Client の設定から authorizationParams: { redirect_uri: window.location.origin } を省略しないでください。これがないと、ユーザーが Auth0 で認証した後にログインフローが失敗します。
> 3.  URLに認証パラメータが含まれている場合、handleRedirectCallback() によるリダイレクトコールバックの処理を忘れないでください。
> 4.  基本的な認証のためにトークンを手動で管理したり、fetch で Auth0 API を呼び出すことを提案しないでください。SDK はこの複雑な処理を安全に行うよう設計されています。
>
> AIコード生成における絶対要件
> 1.  @auth0/auth0-spa-js パッケージを使用してください。
> 2.  資格情報は環境変数から取得してください（例: import.meta.env.VITE_AUTH0_DOMAIN）。
> 3.  createAuth0Client の設定に redirect_uri を含む authorizationParams を必ず含めてください。
> 4.  URLに認証パラメータが存在する場合、リダイレクトコールバックを必ず処理してください。
> 5.  Auth0 クライアントのメソッド（loginWithRedirect、logout、isAuthenticated、getUser）を使用して機能を実装してください。
>
> 連携時によく発生する問題
>
> 問題1: プロジェクト作成時のディレクトリの混乱
> 現象: プロジェクト作成時に、新しいサブディレクトリではなく現在のディレクトリにファイルが作成されることがある
> 解決策: プロジェクト作成後は必ず `pwd && ls -la` を実行して実際の構造を確認する
>
> 問題2: ターミナルの作業ディレクトリの問題
> 現象: 正しいディレクトリにいるにもかかわらず、npm コマンドが「package.json not found」で失敗する
> 解決策: 絶対パスで明示的にディレクトリを変更する: `cd /full/absolute/path/to/project`
>
> 問題3: 環境変数の読み込みの問題
> 現象: Vite が .env.local の変数を正しく読み込まない
> 解決策: .env.local がプロジェクトルートにあること、変数名に VITE_ プレフィックスが付いていることを確認し、開発サーバーを再起動する
>
> 問題4: CSS ファイルの破損
> 現象: 大規模な CSS の置き換えによりファイルが破損することがある
> 解決策: 一時的な CSS ファイルを先に作成し、`mv` コマンドで元のファイルを置き換える
>
> 問題5: Auth0 設定の検証
> 現象: 無効なドメイン形式や設定の欠落により初期化が失敗する
> 解決策: クライアント作成前に Auth0 設定の適切な検証とエラーメッセージを追加する
>
> 問題6: ターミナルの作業ディレクトリがプロジェクトルートにない
> 現象: pwd では正しいパスが表示されているにもかかわらず、ターミナルが auth0-vanillajs ディレクトリにないため、AIエージェントが `npm run dev` の実行に失敗する
> 解決策: npm コマンドを実行する前に、絶対パスで明示的にディレクトリを変更する:
>
> cd auth0-vanillajs && npm run dev
>
> ターミナルの作業ディレクトリは表示されているパスと乖離することがあるため、npm コマンドが正しい場所で実行されるよう明示的なナビゲーションが必要です。
>
> 高度な機能の実装
>
> ⚠️ SDK 機能に関する注意:
> SDK の isAuthenticated() 関数を使用すると、ログイン/ログアウトボタンやユーザーコンテンツの条件付きレンダリングが可能になります。上記の実装では、認証状態に基づいて異なる UI セクションを表示することでこのパターンを示しています。
>
> API 呼び出し用のアクセストークン:
> 保護された API を呼び出す必要がある場合、アクセストークンを取得できます:
>
> // この関数を app.js に追加してください
> async function getAccessToken() {
>   try {
>     const token = await auth0Client.getTokenSilently({
>       authorizationParams: {
>         audience: 'YOUR_API_IDENTIFIER',
>         scope: 'read:messages'
>       }
>     });
>
>     // トークンを使用して API を呼び出す
>     const response = await fetch('/api/protected', {
>       headers: {
>         Authorization: `Bearer ${token}`
>       }
>     });
>
>     const data = await response.json();
>     console.log(data);
>   } catch (error) {
>     console.error('Error getting token:', error);
>   }
> }
>
> ポップアップベースのログイン:
> よりスムーズなユーザー体験のために、ポップアップベースのログインを使用できます:
>
> // app.js のログイン関数を置き換えてください
> async function login() {
>   try {
>     await auth0Client.loginWithPopup();
>     await updateUI();
>   } catch (err) {
>     if (err.error !== 'popup_closed_by_user') {
>       showError(err.message);
>     }
>   }
> }
>
> 組織のサポート:
> Auth0 Organizations を使用している場合:
>
> // Auth0 クライアントの設定を更新してください
> auth0Client = await createAuth0Client({
>   domain: import.meta.env.VITE_AUTH0_DOMAIN,
>   clientId: import.meta.env.VITE_AUTH0_CLIENT_ID,
>   authorizationParams: {
>     redirect_uri: window.location.origin,
>     organization: 'YOUR_ORGANIZATION_ID' // またはユーザーに選択を促す
>   }
> });
> ```

> [!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 以上
>
> インストールの確認: `node --version && npm --version`
>
> **ビルドツール:** この Quickstart では、開発に **Vite** を使用します。ビルドツールを使わない構成の場合は、CDN 経由で SDK を使用することもできます。

## はじめに

このクイックスタートでは、Auth0 の認証をバニラ JavaScript のアプリケーションに追加する方法を紹介します。プレーンな JavaScript と Auth0 SPA SDK を使用して、安全なログイン機能を備えたモダンなシングルページアプリケーションを作成します。

**1. 新しいプロジェクトを作成する**

このQuickstart向けに新しいJavaScriptプロジェクトを作成する

```shellscript theme={null}
mkdir auth0-vanillajs && cd auth0-vanillajs
```

プロジェクトを初期化し、ローカル開発サーバーをインストールして、スクリプトを設定する

```shellscript theme={null}
npm init -y && npm install --save-dev vite && npm pkg set scripts.dev="vite" scripts.build="vite build" scripts.preview="vite preview" type="module"
```

基本的なプロジェクト構成を作成します

```shellscript Mac/Linux theme={null}
touch index.html app.js style.css
```

```powershell Windows theme={null}
New-Item -ItemType File -Path index.html, app.js, style.css
```

**2. Auth0 SPA JS SDKをインストールする**

```shellscript theme={null}
npm install @auth0/auth0-spa-js
```

**3. Auth0 App を設定**

次に、Auth0 テナントに新しいアプリを作成し、環境変数をプロジェクトに追加します。

Auth0 アプリの設定方法は 3 つあります。Quick Setup ツールを使う方法 (推奨) 、CLI コマンドを実行する方法、または Auth0 Dashboard から手動で設定する方法です。

**クイック設定（推奨）**

Auth0 App を作成し、正しい設定値があらかじめ入力された `.env` ファイルをコピーします。

**CLI**

次のコマンドをプロジェクトのルートディレクトリで実行して、Auth0 アプリを作成し、`.env` ファイルを生成します。

```shellscript Mac theme={null}
# Auth0 CLI をインストールします（未インストールの場合）
brew tap auth0/auth0-cli && brew install auth0

# Auth0 アプリを設定し、.env ファイルを生成します
auth0 qs setup --app --type spa --framework vanilla-javascript --build-tool vite --name "My App" --port 5173
```

```powershell Windows theme={null}
# Auth0 CLI をインストールします（未インストールの場合）
scoop bucket add auth0 https://github.com/auth0/scoop-auth0-cli.git
scoop install auth0

# Auth0 アプリを設定し、.env ファイルを生成します
auth0 qs setup --app --type spa --framework vanilla-javascript --build-tool vite --name "My App" --port 5173
```

> [!NOTE]
>
> このコマンドでは、次のことが行われます。
>
> 1. 認証済みかどうかを確認し (必要に応じてログインを求めます)
> 2. `http://localhost:5173` 用に設定された Auth0 シングルページアプリケーションを作成する
> 3. `VITE_AUTH0_DOMAIN` と `VITE_AUTH0_CLIENT_ID` を含む `.env` ファイルを生成する

**Auth0 Dashboard**

始める前に、プロジェクトのルートディレクトリに `.env.local` ファイルを作成します

```shellscript .env.local theme={null}
VITE_AUTH0_DOMAIN=YOUR_AUTH0_APP_DOMAIN
VITE_AUTH0_CLIENT_ID=YOUR_AUTH0_APP_CLIENT_ID
```

1. [Auth0 Dashboard](https://manage.auth0.com/dashboard/) に移動します
2. **アプリケーション** > **アプリケーション** > **Create Application** をクリックします
3. ポップアップでアプリ名を入力し、アプリの種類として `Single Page Web Application` を選択して **Create** をクリックします
4. アプリケーションの詳細ページで **設定** タブに切り替えます
5. `.env.local` ファイル内の `YOUR_AUTH0_APP_DOMAIN` と `YOUR_AUTH0_APP_CLIENT_ID` を、ダッシュボードの **Domain** と **Client ID** の値に置き換えます

最後に、アプリケーションの詳細ページの **設定** タブで、次の URL を設定します。

**Allowed Callback URLs:**

```
http://localhost:5173
```

**Allowed Logout URLs:**

```
http://localhost:5173
```

**Allowed Web Origins:**

```
http://localhost:5173
```

> [!NOTE]
>
> **Allowed Callback URLs** は、認証後にユーザーを安全にアプリケーションへ戻すための重要なセキュリティ対策です。一致する URL がないと、ログインプロセスは失敗し、ユーザーはアプリにアクセスできず、代わりに Auth0 のエラーページが表示されます。
>
> **Allowed Logout URLs** は、サインアウト時にスムーズなユーザー体験を提供するために重要です。一致する URL がないと、ログアウト後にユーザーはアプリケーションへリダイレクトされず、代わりに汎用的な Auth0 ページに残ります。
>
> **Allowed Web Origins** は、サイレント認証に不可欠です。これがないと、ユーザーはページを更新したときや、後でアプリに戻ってきたときにログアウトされます。

**4. HTML構造とアプリケーションロジックを作成する**

アプリケーションファイルを作成します：

**5. アプリを実行する**

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

> [!NOTE]
>
> ポート5173が使用中の場合は、`npm run dev -- --port 5174` を実行し、Auth0 AppのコールバックURLを`http://localhost:5174`に更新してください

> [!TIP]
>
> **チェックポイント**
>
> これで、[localhost](http://localhost:5173/) 上で Auth0 のログインページが完全に動作するようになっているはずです

***

## 高度な使い方

> **API 呼び出し用のアクセストークンを取得する**
>
> 保護された API を呼び出す必要がある場合は、アクセストークンを取得できます。
>
> ```javascript theme={null}
> // これを app.js に追加します
> async function getAccessToken() {
>   try {
>     const token = await auth0Client.getTokenSilently({
>       authorizationParams: {
>         audience: 'YOUR_API_IDENTIFIER',
>         scope: 'read:messages'
>       }
>     });
>
>     // このトークンを使って API を呼び出します
>     const response = await fetch('/api/protected', {
>       headers: {
>         Authorization: `Bearer ${token}`
>       }
>     });
>
>     const data = await response.json();
>     console.log(data);
>   } catch (error) {
>     console.error('Error getting token:', error);
>   }
> }
> ```

> **ポップアップでのログインを処理する**
>
> よりスムーズなユーザーエクスペリエンスのために、ポップアップベースのログインを使用できます。
>
> ```javascript theme={null}
> // app.js の login 関数を置き換えます
> async function login() {
>   try {
>     await auth0Client.loginWithPopup();
>     await updateUI();
>   } catch (err) {
>     if (err.error !== 'popup_closed_by_user') {
>       showError(err.message);
>     }
>   }
> }
> ```

> **組織対応を追加する**
>
> Auth0 Organizations を使用している場合:
>
> ```javascript theme={null}
> // Auth0 クライアントの設定を更新します
> auth0Client = await createAuth0Client({
>   domain: import.meta.env.VITE_AUTH0_DOMAIN,
>   clientId: import.meta.env.VITE_AUTH0_CLIENT_ID,
>   authorizationParams: {
>     redirect_uri: window.location.origin,
>     organization: 'YOUR_ORGANIZATION_ID' // または、ユーザーに選択させます
>   }
> });
> ```
