Just login and show name

sharing an experiment.
created with Noel’s inspiration and Gemini 2.5 Pro.
deployed to Solid Login App (Working Pattern)
does nothing else than displaying foaf:name
hardcoded to https://teamid.live

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Solid Login App (Working Pattern)</title>
    <link rel="stylesheet" href="https://cdn.simplecss.org/simple.min.css">
</head>
<body>
    <main>
        <h1>Solid Login</h1>

        <!-- Shown while the session is being checked -->
        <div id="loading">
            <p>Initializing session...</p>
        </div>

        <!-- Shown only to logged-out users -->
        <div id="auth-guest" hidden>
            <p>You are not logged in. Please log in to continue.</p>
            <button id="login-button">Login with teamid.live</button>
        </div>

        <!-- Shown only to logged-in users -->
        <div id="auth-user" hidden>
            <p>Hello, <strong id="username"></strong>!</p>
            <button id="logout-button">Log out</button>
        </div>
    </main>

    <!--
      The necessary libraries, using the current versions from august 2025.
      The order is critical: Libraries first, then our application logic.
    -->
    <script src="https://cdn.jsdelivr.net/npm/@inrupt/solid-client-authn-browser@3.1.0/dist/solid-client-authn.bundle.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/n3@1.26.0/browser/n3.min.js"></script>
    <script src="app.js"></script>

</body>
</html>

app.js

// --- SECTION 1: CONFIGURATION ---
const SOLID_OIDC_ISSUER = "https://teamid.live";
const FOAF_NAME_PREDICATE = "http://xmlns.com/foaf/0.1/name";

// --- SECTION 2: UI ELEMENT REFERENCES ---
const loadingDiv = document.getElementById('loading');
const guestDiv = document.getElementById('auth-guest');
const userDiv = document.getElementById('auth-user');
const loginButton = document.getElementById('login-button');
const logoutButton = document.getElementById('logout-button');
const usernameSpan = document.getElementById('username');

// --- SECTION 3: CORE SOLID LOGIC ---

/**
 * Restores a previous session or handles the redirect from the login provider.
 * This is the main entry point of the application.
 */
async function restoreSession() {
    try {
        // Handle the redirect from the Solid Identity Provider.
        await solidClientAuthentication.handleIncomingRedirect({ restorePreviousSession: true });

        // Get the current session information.
        const session = solidClientAuthentication.getDefaultSession();

        // If not logged in, show the guest view and stop.
        if (!session.info.isLoggedIn) {
            updateUI(false);
            return;
        }

        // If logged in, fetch the user's name and update the UI.
        const user = await fetchUserProfile(session.info.webId);
        updateUI(true, user.name);

    } catch (error) {
        alert(error.message);
        updateUI(false); // If an error occurs, show the guest view.
    }
}

/**
 * Fetches the user's name from their Solid profile.
 * @param {string} webId - The WebID of the user.
 * @returns {Promise<object>} An object containing the user's name.
 */
async function fetchUserProfile(webId) {
    // This function uses the `readSolidDocument` helper below.
    const profileQuads = await readSolidDocument(webId);

    // Find the quad containing the foaf:name.
    const nameQuad = profileQuads.find(quad => quad.predicate.value === FOAF_NAME_PREDICATE);

    return {
        name: nameQuad?.object.value || 'Anonymous'
    };
}

/**
 * A low-level helper to fetch and parse a Solid document.
 * @param {string} url - The URL of the document to read.
 * @returns {Promise<Array>} An array of quads from the parsed document.
 */
async function readSolidDocument(url) {
    // Use the authenticated fetch from the library.
    const response = await solidClientAuthentication.fetch(url, { headers: { Accept: 'text/turtle' } });
    if (Math.floor(response.status / 100) !== 2) return []; // Return empty on error.
    
    const data = await response.text();
    // The n3.min.js bundle exposes the Parser directly on the global N3 object.
    const parser = new N3.Parser({ baseIRI: url }); 

    return parser.parse(data);
}

// --- SECTION 4: UI AND EVENT HANDLING ---

/**
 * Updates the user interface based on the login state.
 * @param {boolean} isLoggedIn - Whether the user is logged in.
 * @param {string} [name] - The user's name, if logged in.
 */
function updateUI(isLoggedIn, name) {
    loadingDiv.setAttribute('hidden', ''); // Hide loading message

    if (isLoggedIn) {
        guestDiv.setAttribute('hidden', '');
        userDiv.removeAttribute('hidden');
        usernameSpan.textContent = name;
    } else {
        userDiv.setAttribute('hidden', '');
        guestDiv.removeAttribute('hidden');
    }
}

// Attach event listeners to buttons.
loginButton.onclick = () => {
    solidClientAuthentication.login({
        oidcIssuer: SOLID_OIDC_ISSUER,
        redirectUrl: window.location.href,
        clientName: 'Hello World Solid App'
    });
};

logoutButton.onclick = async () => {
    logoutButton.setAttribute('disabled', '');
    await solidClientAuthentication.logout();
    logoutButton.removeAttribute('disabled');
    updateUI(false); // Reset to guest view.
};


// --- SECTION 5: START THE APPLICATION ---
restoreSession();
1 Like