Files
2026-07-12 10:17:17 -04:00

2.9 KiB

SPQ Page Architecture & Auth Flow

Page layout

/ (index.html) — login page (NO redirect — root lands here directly)
dashboard.html  — main dashboard (auth-guarded: no user → redirects to /)
appointments.html, customers.html, repair-orders.html — sub-pages (auth-guarded)

Why index.html = login page

When index.html was the dashboard and login.html was a separate page, stale/expired PocketBase tokens in localStorage caused an infinite redirect loop:

  1. User visits /index.html (dashboard) → onAuthStateChanged → SDK sees stale token as valid → stays
  2. First PocketBase API call fails (401) → SDK clears auth → onChange(null) fires → redirect to login.html
  3. login.html loads → SDK reads token from localStorage again (still there, client-side JWT expiry check says valid) → onAuthStateChanged(user) → redirect to index.html
  4. Loop!

Making index.html the login page eliminates the bounce: unauthorized users see the login form directly, authorized users get one clean redirect to dashboard.html.

Auth guard pattern (in every page JS)

onAuthStateChanged(auth, (user) => {
    if (user) {
        // initialize page
    } else {
        window.location.href = 'index.html';  // redirect to login
    }
});

login.js (login page):

onAuthStateChanged(auth, (user) => {
    if (user) {
        window.location.href = 'dashboard.html';  // already logged in → dashboard
    }
    // If no user, stay on login page
});

PocketBase auth flow

The pocketbase.js adapter:

  • Creates PocketBase client pointed at window.location.origin (same-origin, through nginx /api/ proxy)
  • onAuthStateChanged fires initial state synchronously via auth.currentUser getter (reads from pb.authStore)
  • Then registers pb.authStore.onChange for future changes
  • authStore reads from localStorage key pocketbase_auth

When renaming/moving pages

All references are relative (dashboard.html, not absolute paths). Files to update:

File What to change
login.js Login success redirect → dashboard.html
dashboard.js, main.js, appointments.js, customers.js, repair-orders.js Auth fail redirect → index.html
shared/header-functionality.js Logout redirect → index.html
index.html (login page body) Post-login redirects → dashboard.html?cb=...
appointments.html, repair-orders.html, customers.html Nav links → dashboard.html
dashboard.html Nav self-links → dashboard.html
customers.js Quote links → dashboard.html?quoteId=...

Total: ~28 references across 13 files.

nginx note

Home nginx server_name must include the domain the VPS sends in Host header. If the VPS proxies shopproquote.graj-media.com with Host: graj-media.com, add it as an alias:

server_name grajmedia.duckdns.org graj-media.com shopproquote.graj-media.com;