Files
hermes-config/skills/software-development/web-ui-repair/references/cross-page-settings-desync.md
T
2026-07-12 10:17:17 -04:00

3.1 KiB

Cross-Page Settings Desync: Missing initializeSettings

Diagnostic Signal

User toggles a setting (desktop notifications, sound alerts, dark mode) on page A, saves — it sticks. Navigates to page B — the same toggle shows its default/off state. Toggling+saving on page B works on page B but page A reverts. Each page "remembers" only its own saves.

Root Cause

A shared settings module (settings.js) exports initializeSettings(), which:

  1. Calls loadSettings() — fetches saved settings from PocketBase/localStorage
  2. Calls populateSiteSettingsForm() — sets checkbox/select values from loaded settings
  3. Calls setupUnifiedSiteSettingsModalHandlers() — wires close/save/cancel buttons
  4. Calls subscribeToRealtimeSettings() — sets up change listeners

If any page in the app loads settings.js as a <script type="module"> but never calls initializeSettings(), that page runs with module defaults. The form controls show their raw HTML state (unchecked for input[type=checkbox] without a checked attribute).

Common Pattern

repair-orders.js:  import { initializeSettings } from './settings.js'
                   await initializeSettings(...);  // ✅ called

customers.js:      import { initializeSettings } from './settings.js'
                   await initializeSettings(...);  // ✅ called

main.js:           import { initializeSettings } from './settings.js'
                   initializeSettings(...);        // ✅ called

dashboard.js:      settingsModule.initializeSettings(...);  // ✅ called

appointments.js:   // ❌ imports settings.js? Yes (loaded as module)
                   // ❌ calls initializeSettings()? NO
                   // → settings desync on appointments page

Fix

Add the import and call to every page that has a site settings modal:

// At top of page's JS file:
import { initializeSettings } from './settings.js';

// Inside the page's init function (after auth check):
initializeSettings();

Verification

# Check every page's JS for the initializeSettings call
for js in repair-orders.js appointments.js customers.js main.js dashboard.js; do
  echo -n "$js: "
  grep -c 'initializeSettings' "$js"
done
# Every result should be ≥ 2 (import + call site). A result of 0 or 1 = bug.

PocketBase Pitfall: onSnapshot is One-Shot

The onSnapshot function in PocketBase adapter (pocketbase.js) is a one-shot fetch, not a realtime listener. It fires once when called, then never again:

function onSnapshot(queryOrDocRef, callback) {
    // Simple one-shot onSnapshot compatibility shim
    getDoc(queryOrDocRef).then(doc => callback(doc));
    return () => {};  // Unsubscribe is a no-op
}

This means subscribeToRealtimeSettings() does NOT provide realtime cross-page sync. Settings saved on page A are persisted to PocketBase, but page B won't see the change until it reloads (calling loadSettings() fresh). This is fine for navigation-based sync (each page loads settings on init), but means two open tabs won't stay in sync without a manual refresh.