Hi again @wsmetz72
I am sorry for my delayed response, I have been out of office and could not get back to you in time.
I see that you are having issues in building a Single Page Application (SPA) using Auth0’s quickstart guide. You have successfully created a login page and authenticated test users. Now you’re trying to integrate my custom HTML page into the Auth0 app so it displays as a members-only page on my organization’s website.
[ROOT CAUSE]**
The confusion stems from mixing two incompatible approaches:
- CDN-based approach (older): Uses
<script src="https://cdn.auth0.com/..."></script> and attaches auth0 to the global window object.
- Vite/NPM-based approach (newer): Uses ES Module imports and requires a build step.
The split-screen issue occurs because the example’s Universal Login component is still rendering on top of your custom content. This is a layout/CSS issue, not an Auth0 configuration issue.
The import error happens because you’re trying to use ES Module syntax (import) in a non-module context (likely PowerShell or a script that doesn’t support ES Modules).
[SOLUTION]
Step 1: Choose your approach — Vite/NPM (Recommended)
The newer Vite-based approach is recommended for modern SPAs. It provides better performance, security, and tooling.
Step 2: Install the Auth0 SDK via NPM
npm install @auth0/auth0-spa-js
Step 3: Remove the CDN link from index.html
Delete this line entirely:
<!-- REMOVE THIS -->
<script src="https://cdn.auth0.com/..."></script>
Replace it with a single module script tag:
<script type="module" src="/app.js"></script>
Step 4: Import the SDK correctly in app.js
At the very top of your app.js file, add the explicit import:
import { createAuth0Client } from '@auth0/auth0-spa-js';
let auth0Client;
window.onload = async () => {
auth0Client = await createAuth0Client({
domain: import.meta.env.VITE_AUTH0_DOMAIN,
clientId: import.meta.env.VITE_AUTH0_CLIENT_ID,
authorizationParams: {
redirect_uri: window.location.origin
}
});
// Check if user is logged in
const isAuthenticated = await auth0Client.isAuthenticated();
if (!isAuthenticated) {
// Show login or redirect
await auth0Client.loginWithRedirect();
} else {
// Show your custom member-only content
document.getElementById('app').innerHTML = '<h1>Welcome, member!</h1>';
}
};
Step 5: Fix the split-screen issue
The split-screen occurs because the Universal Login component is still being rendered. Instead of replacing content, conditionally show your page only after authentication:
// Hide Universal Login after successful authentication
const isAuthenticated = await auth0Client.isAuthenticated();
if (isAuthenticated) {
// Hide login UI, show your custom content
document.getElementById('auth0-login-container').style.display = 'none';
document.getElementById('member-content').style.display = 'block';
} else {
// Show login UI
document.getElementById('auth0-login-container').style.display = 'block';
document.getElementById('member-content').style.display = 'none';
}
Step 6: Build and deploy (without renaming files)
npm run build
Vite generates a dist folder with:
index.html (updated with correct file references)
assets/ folder (containing hashed files like app-rlbWHTKs.js)
Upload the entire dist folder to your hosting provider (e.g., GoDaddy). Do not rename any files.
When you run npm run build, Vite intentionally appends a random hash to file names (e.g., app-rlbWHTKs.js). This is called Cache Busting and serves two purposes:
- Browser caching: When you deploy updates, the new hash forces browsers to download the new file instead of using a cached version.
- Automatic linking: Vite automatically updates all references in
index.html to point to the hashed files.
If you manually rename app-rlbWHTKs.js back to app.js, you break the links that Vite created in index.html, resulting in a blank page or broken application.
COMMON MISTAKES TO AVOID
Kind Regards,
Nik