Performance
Instant navigation and zero splash screen delays.
What changed
Previously, navigating between pages showed a full-screen splash screen with a progress bar that could block the UI for up to 8 seconds. Now every page loads instantly with skeleton placeholders while data fetches in the background.
Route Progress Bar
A thin gradient bar at the top of the screen gives immediate visual feedback when you click a link. It starts animating instantly and completes when the new page renders — similar to YouTube and GitHub.
Skeleton Loading States
Every major page now has a dedicated loading.tsx file that renders a lightweight skeleton matching the page layout. This means:
- • Notable people directory — grid of placeholder cards
- • Home (
/home) — AppShell layout: sidebar, feed column (stories, profile card, widgets), docked Dayze Agent + mobile bottom nav - • Your People (
/[handle]/people) — desktop master–detail: shimmer grid + detail panel skeleton - • Calendar, Insights, Reels, Timeline — same AppShell chrome with route-specific main column placeholders
- • Movies — poster-ratio grid placeholders
- • Profile pages — avatar, name, and section blocks
- • Admin, Settings, Map, Saved, Explore, chat — all covered
- • Wallet, Inventory, Businesses, Analytics, Playbook — shared
ModulePageSkeleton
Intent prefetch
Hover, focus, or touch on sidebar and mobile bottom-nav links warms the route JS chunk and SWR data before you navigate — repeat clicks feel instant.
Load speed tracking (admin)
Superusers can open /admin → Performance to see per-route shell-ready times (ms until the route clears its loading gate), bounce-risk bands, and session aggregates. A summary strip also appears on the admin System Overview.
Bounce-risk bands: <400 ms low · <1 s OK · <2.5 s high · ≥2.5 s critical
Netlify Lighthouse (Best Practices)
Deploy badges on Netlify run Lighthouse on / after each production build. A Best Practices score of 0 in the UI often means the category failed to compute (null → 0), not a literal zero — open the deploy report for details.
- • Anonymous visitors no longer trigger
/api/user/onboarding401s from growth nudges. - • Landing search chips use first-party people JPEGs under
/assets/images/people/instead of Wikimedia CDN URLs. - • Production browser source maps are enabled for Lighthouse source-map coverage.
Minimal inline splash
Dayze uses a single inline HTML splash — colored crescent mark with a soft pulsing glow — that covers the pre-hydration gap. No wordmark or fake progress bar on first paint. It is dismissed as soon as React mounts — typically under 1 second. A JS timeout fallback auto-hides it even if hydration is slow. Route transitions may still show the legacy full loader for A/B (`lib/ui/page-loader-variant.ts`).
Pages with loading skeletons
Scalable client cache
Small bootstrap keys (user id, navbar profile) stay in localStorage for instant paint. Large lists—Your People, events—persist in IndexedDB (50MB+ quota) so power users with thousands of contacts do not hit storage limits.
Cache-first data (SWR persist)
On repeat visits, Home, Your People, and key lists hydrate from persisted SWR cache while auth and Supabase revalidate in the background. A lightweight session bootstrap (dayze_bootstrap_user) paints the shell immediately without waiting for getUser().
- •
usePeople/useEvents— loading skeleton only on first unresolved fetch - •
AppInitProvider— prefetches people, events, and profile after sign-in - • Admin console —
AdminPageSkeletoninstead of full splash; 1h superuser gate cache - •
useFastAuth— bootstrap shell on home, people, person profiles, wallet, share, analytics, settings, time, inventory, businesses, saved, playbook, calendar, insights, reels, timeline - •
fetchPeopleForUserGuarded— session memory + retry on false empty; merge mode freezes catalog snapshot - • IndexedDB → SWR rehydrate — non-empty people/events appear in hooks immediately; empty/missing lists fetch fresh data (avoids false RLS-empty cache)
- •
isProfilePending— onboarding modals wait for profile fetch; bootstrap stores birthday for repeat visits - • Idle prefetch — top nav route chunks warm during browser idle time after cache hydrate
- • Settings, finance, replies — unified
useFastAuth; replies use 5-minute session cache - • Inventory & business lists — 24h
localStoragepage-list cache for instant repeat visits
Maintainer reference: docs/PERFORMANCE.md in the repo.
- • Next.js App Router
loading.tsxconvention for Suspense boundaries - •
RouteProgressBar— CSS-only animation, no JS timers during transition - •
LoadingContext— dismisses the inline splash on hydration - • Inline HTML splash — minimal mark + glow; auto-dismissed on load + JS fallback
- •
LoadingSkeletons.tsx— Shimmer placeholders:AppShellPageSkeleton,HomePageSkeleton,UserPeoplePageSkeleton, route-specific content skeletons - • Client auth loading on Home, Calendar, Insights, Reels, Timeline reuses the same skeletons as each route's
loading.tsx - • Home console guardrails — supported Open-Meteo fields only, non-throwing referral stats, non-406 daily check-in reads, direct Supabase Storage avatar loading, and best-effort service-worker cache writes