feat: add PostHog, move Plausible to v4, and drop Sentry session replay
Build and Deploy Spoon / quality (push) Successful in 1m40s
Build and Deploy Spoon / build-images (push) Successful in 12m23s

PostHog loads after the page is idle through a same-origin /ingest proxy and follows the signed-in Convex user. Plausible uses the per-site script through a /pa proxy. Sentry keeps errors and traces only. Pages load only the @spoon/ui modules they import, and client code reads public env from publicEnv.ts so zod stays out of the browser. Both analytics integrations stay off until their env is set in Infisical prod.
This commit is contained in:
Gabriel Brown committed 2026-10-01 17:17:21 -04:00
1 parent 587fa0fdcd
commit 348c2d3d62
22 files changed
+366 -106

No files matched your search

+28 -26
View File
@@ -7,8 +7,8 @@ import { Geist, Geist_Mono } from 'next/font/google';
import '@/app/styles.css';
import { useEffect } from 'react';
import { env } from '@/env';
import { generateMetadata } from '@/lib/metadata';
import { publicEnv } from '@/publicEnv';
import * as Sentry from '@sentry/nextjs';
import PlausibleProvider from 'next-plausible';
@@ -41,32 +41,34 @@ const GlobalError = ({ error, reset = undefined }: GlobalErrorProps) => {
useEffect(() => {
Sentry.captureException(error);
}, [error]);
return (
<PlausibleProvider
domain={env.NEXT_PUBLIC_SITE_URL.trim().replace(/^https?:\/\//, '')}
customDomain={env.NEXT_PUBLIC_PLAUSIBLE_URL}
const page = (
<ThemeProvider
attribute='class'
defaultTheme='system'
enableSystem
disableTransitionOnChange
>
<html lang='en' suppressHydrationWarning>
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
>
<ThemeProvider
attribute='class'
defaultTheme='system'
enableSystem
disableTransitionOnChange
>
<main className='flex min-h-screen flex-col items-center justify-center gap-4 p-6'>
<NextError statusCode={0} />
{reset !== undefined && (
<Button onClick={() => reset()}>Try Again</Button>
)}
<Toaster />
</main>
</ThemeProvider>
</body>
</html>
</PlausibleProvider>
<main className='flex min-h-screen flex-col items-center justify-center gap-4 p-6'>
<NextError statusCode={0} />
{reset !== undefined && (
<Button onClick={() => reset()}>Try Again</Button>
)}
<Toaster />
</main>
</ThemeProvider>
);
return (
<html lang='en' suppressHydrationWarning>
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
>
{publicEnv.NEXT_PUBLIC_PLAUSIBLE_SRC ? (
<PlausibleProvider>{page}</PlausibleProvider>
) : (
page
)}
</body>
</html>
);
};
export default GlobalError;