Files
eryao/.trellis/tasks/archive/2026-05/05-10-audit-and-optimize-web-performance/request-audit.md
T

4.0 KiB

Web request audit

Initial request topology

App shell and auth

Area Request(s) Current behavior Waste / risk
AppShell refreshAccessToken(), getUserProfile() Runs on authenticated shell mount. Profile is stored in UserSettingsContext. This should be the primary profile/settings source for child pages.
LoginForm existing auth check refreshAccessToken(), getUserProfile() Valid existing session fetches profile to choose locale before redirect. Acceptable, but could reuse stored auth language if persisted in future.
LoginForm submit loginWithEmail(), getUserProfile() Login response lacks settings, so profile is fetched to choose locale. Acceptable until backend returns language/settings in auth response.

Duplicate profile/settings reads

Page Current request Better behavior
SettingsPage getUserProfile() + getPointsBalance() Reuse UserSettingsContext.userProfile; fetch only points.
GeneralSettingsPage getUserProfile() Seed from UserSettingsContext.userProfile; fetch only if context missing. Update context after updateUserSettings().
ProfileDetailPage getUserProfile() Seed from UserSettingsContext.userProfile; fetch only if context missing. Update context after updateUserProfile() / avatar upload.
ManualDivinationPage / AutoDivinationPage import getUserProfile but rely on context for profile; getUserProfile import appears unused Remove unused import and keep using context.

Points and store reads

Page Current request Better behavior
Dashboard getPointsBalance(), getUnreadNotificationCount(), getAgentHistory() Points has TTL cache, but should dedupe in-flight. History can be shared with history list via short TTL cache.
SettingsPage getPointsBalance() Keep cache, add in-flight dedupe and stale-while-revalidate option.
StorePage getPointsBalance(), getPackages() Cache packages for a longer TTL because packages are stable configuration. Keep explicit invalidation after purchase/payment flows.
ManualDivinationPage / AutoDivinationPage getPointsBalance() Reuse points cache/in-flight dedupe; consider prefetch when entering divination nav group.

History and notifications

Area Current request Better behavior
Dashboard getAgentHistory() for latest four Add short TTL/in-flight cache for history summary; history list can reuse if still fresh.
HistoryListPage getAgentHistory() full list Reuse cache populated by dashboard, then refresh in background.
NotificationPage getNotifications(locale) Cache list briefly per locale. Invalidate/update locally after mark-read actions.
Dashboard unread badge getUnreadNotificationCount() Cache briefly; invalidate/update after mark-read or mark-all-read.

Priority plan

  1. Add a small typed cache helper in web/src/lib/api.ts or adjacent web/src/lib/api-cache.ts for:
    • TTL cache
    • in-flight promise dedupe
    • explicit invalidation
    • optional stale return with background refresh where UI can support it
  2. Apply first to profile/settings, points, packages, history summary/list, notification list/count.
  3. Refactor pages to use UserSettingsContext for profile reads.
  4. Add prefetch hooks at AppShell/nav boundaries where it is cheap and safe.
  5. Browser-verify request count reductions on:
    • login -> dashboard
    • dashboard -> settings -> profile -> general
    • dashboard -> manual/auto divination
    • dashboard -> history
    • dashboard -> store

Open implementation questions

  • Whether to implement a minimal local cache helper or introduce a query library. Current repo has no query dependency, so default recommendation is a minimal helper first.
  • Whether auth login response should eventually include profile language/settings to avoid immediate post-login profile fetch. This would be a backend contract change and is out of scope for the first frontend-only optimization pass.