Skip to main content

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​

RouteSnap 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 TrpcClientProvider must wrap anything that uses tRPC hooks
  • The SessionProvider must wrap anything that checks authentication
  • The GMapsProvider must wrap any Google Maps components