Implementation:Helicone Helicone App Component
| Knowledge Sources | |
|---|---|
| Domains | Application Shell, Provider Hierarchy |
| Last Updated | 2026-02-14 06:32 GMT |
Overview
Next.js custom App component that establishes the global provider hierarchy wrapping all pages, including analytics, authentication, state management, and theming.
Description
The MyApp component is the root of the Helicone web application, responsible for initializing and composing all global context providers. It implements a layered provider architecture in the following order (outermost to innermost):
- PHProvider - PostHog analytics provider (initialized conditionally based on
NEXT_PUBLIC_POSTHOG_API_KEYandNEXT_PUBLIC_ENDPOINT) - SupabaseProvider - Supabase session context (conditionally created if Supabase URL and anon key are available)
- QueryClientProvider - TanStack Query for server state management
- NotificationProvider - Toast notification system
- DndProvider - React DnD with HTML5 backend for drag-and-drop
- OrgContextProvider - Organization context for multi-tenant support
- FilterProvider - Filter AST context for request filtering
- ThemeProvider - Light/dark theme support with
classattribute strategy - TooltipProvider - Tooltip context for UI tooltips
The component also:
- Supports per-page layouts via the
getLayoutpattern onNextPageWithLayout - Captures attribution parameters (gclid, UTM) on mount via
captureAttributionParams - Conditionally renders Vercel Analytics, Koala, Pylon chat widget, and RB2B tracking scripts when
NEXT_PUBLIC_TRACKING_ENABLEDis set - Shows React Query Devtools in development mode
- Initializes PostHog with the application's ingest proxy endpoint
Usage
This component is automatically used by Next.js as the application wrapper. It should not be imported or used directly. Page components can define a getLayout function to customize their layout wrapper.
Code Reference
Source Location
- Repository: Helicone
- File: web/pages/_app.tsx
Signature
export type NextPageWithLayout<P = {}, IP = P> = NextPage<P, IP> & {
getLayout?: (page: ReactElement) => ReactNode;
};
export function PHProvider({ children }: { children: React.ReactNode }): JSX.Element;
export function SupabaseProvider({
children,
initialSession,
}: {
children: React.ReactNode;
initialSession?: Session | null;
}): JSX.Element;
export default function MyApp({ Component, pageProps }: AppPropsWithLayout): JSX.Element;Import
// This component is used automatically by Next.js
// For the layout type:
import type { NextPageWithLayout } from "@/pages/_app";
I/O Contract
Provider Hierarchy
| Layer | Provider | Purpose |
|---|---|---|
| 1 | PHProvider | PostHog analytics tracking |
| 2 | SupabaseProvider | Supabase authentication session |
| 3 | QueryClientProvider | TanStack Query client for data fetching |
| 4 | NotificationProvider | Toast notification system |
| 5 | DndProvider | React drag-and-drop support |
| 6 | OrgContextProvider | Organization/tenant context |
| 7 | FilterProvider | Filter AST context |
| 8 | ThemeProvider | Light/dark theme management |
| 9 | TooltipProvider | UI tooltip context |
Environment Variables
| Variable | Purpose |
|---|---|
| NEXT_PUBLIC_POSTHOG_API_KEY | PostHog analytics API key |
| NEXT_PUBLIC_ENDPOINT | PostHog endpoint check |
| NEXT_PUBLIC_DISABLE_POSTHOG | Disables PostHog when set |
| NEXT_PUBLIC_SUPABASE_URL | Supabase project URL |
| NEXT_PUBLIC_SUPABASE_ANON_KEY | Supabase anonymous key |
| NEXT_PUBLIC_TRACKING_ENABLED | Enables Vercel Analytics, Koala, Pylon, and RB2B scripts |
Conditional Third-Party Scripts
| Script | Condition | Purpose |
|---|---|---|
| Vercel Analytics | trackingEnabled | Page view and web vitals tracking |
| Koala | trackingEnabled | Visitor identification |
| Pylon | trackingEnabled | In-app chat widget |
| RB2B | trackingEnabled | B2B visitor identification |
Usage Examples
// Defining a page with a custom layout
import type { NextPageWithLayout } from "@/pages/_app";
import DashboardLayout from "@/components/layout/DashboardLayout";
const DashboardPage: NextPageWithLayout = () => {
return <div>Dashboard Content</div>;
};
DashboardPage.getLayout = (page) => (
<DashboardLayout>{page}</DashboardLayout>
);
export default DashboardPage;