3.1 KiB
SPQ Auth Flow & Page Structure
File roles
| File | Role |
|---|---|
index.html |
Login/signup page — the root page. No auth redirect on load. |
dashboard.html |
Dashboard — the main app (was previously index.html). |
appointments.html, repair-orders.html, customers.html |
Sub-pages with shared header/nav pointing to dashboard.html. |
Auth redirects
Not logged in:
/ → index.html (login form, NO redirect)
/dashboard.html → auth guard → redirects to /index.html
Logged in:
/ → detects token in localStorage → redirects to /dashboard.html
/dashboard.html → stays
Logout → redirects to /index.html
Why index.html is the login page
Originally index.html was the dashboard and login.html was the login page. This caused a redirect loop: when PocketBase auth state was unstable (stale/expired token), onAuthStateChanged on the dashboard saw no user and redirected to login.html, whose own onAuthStateChanged saw the stored token and redirected back to index.html — creating a flip-flop between the two URLs.
Fix: Made index.html the login page and moved the dashboard to dashboard.html. Now visiting the root (/) shows the login form directly with zero redirects. The dashboard only redirects when it detects no user (→ /), and the login only redirects when it detects a user (→ /dashboard.html). No more reciprocal bounce.
Reference: all redirect targets
When renaming or restructuring pages, update these files:
Auth failure → index.html (login)
dashboard.js:122—window.location.href = 'index.html'main.js:44—window.location.href = 'index.html'appointments.js:50—window.location.href = 'index.html'customers.js:78—window.location.href = 'index.html'repair-orders.js:58—window.location.href = 'index.html'shared/header-functionality.js:318— logout handler →'index.html'
Login success → dashboard.html
login.js:33—window.location.href = 'dashboard.html'index.html:131— inline script:location.replace('dashboard.html?cb='+Date.now())index.html:577— login success handlerindex.html:1035— signup success handler
Nav links → dashboard.html
All href="dashboard.html" in: appointments.html, repair-orders.html, customers.html, dashboard.html
dashboard.htmlnav hasactive-pageclass on its own link
Quote deep-link → dashboard.html?quoteId=...
customers.js:676—href="dashboard.html?quoteId=${escapeHtml(quote.id)}"
Keyboard shortcut → dashboard.html
dashboard.js:2144— case 'q' keyboard shortcut
Dual-VPS config Host header note
The VPS has two ShopProQuote nginx configs:
shopproquote-duckdns(forgrajmedia.duckdns.org) —Host: grajmedia.duckdns.org✓ correctshopproquote(forshopproquote.graj-media.com) —Host: graj-media.com— may not match home nginx which only hasserver_name grajmedia.duckdns.org. Seevps-reverse-proxyskill's "Host header mismatch → SPA redirect loop" pitfall.