# 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)

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

**login.js** (login page):
```js
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;
```
