Provider Nesting
The app uses deeply nested React context providers. Understanding the nesting order is important when adding new providers or consuming contexts.
Root Layout
The root layout (src/app/layout.tsx) wraps children in MaintenanceProvider.
App Layout
The (app) layout (src/app/(app)/layout.tsx) nests providers in this exact order:
LayoutProvider → lockScroll / unlockScroll (document.body overflow control)
└─ PHProvider → PostHog init (capture_pageview: false, person_profiles: identified_only)
└─ SessionProvider → NextAuth session
└─ TrpcClientProvider → tRPC client + React Query QueryClientProvider
└─ UserLocationProvider → IP geolocation via tRPC (staleTime: Infinity)
└─ GMapsProvider → @vis.gl/react-google-maps APIProvider
└─ MapPlacesProvider → places dict, selectedPlace, markersLoaded, reloadPlaces
└─ SearchProvider → location, acsAttrs, categories; syncs URL ↔ state
└─ LoadingOverlayProvider → showOverlay(msg) / hideOverlay, z-100 modal
Map Layout
The map layout (src/app/(app)/map/layout.tsx) adds additional providers inside the app layout:
MobileProvider → isMobile (≤1024px), activeSnapPoint, snapPoints
└─ PlacesQueryProvider → bounds-based tRPC search, 500ms debounce, PAGE_SIZE=20, pagination
Snap Points by Route
| Route | Snap Points |
|---|---|
/map (default) | [0.14, 0.5, 1] |
/map/place/[id] | [0.14, 0.6, 1] |
/map/results | ['100px', 0.6, 1] |
Important Notes
- Any new provider must be inserted at the correct level based on its dependencies
- Providers lower in the tree can access contexts from providers above them
- The
TrpcClientProvidermust wrap anything that uses tRPC hooks - The
SessionProvidermust wrap anything that checks authentication - The
GMapsProvidermust wrap any Google Maps components