From 234da6f7d79142bf63d51410453a8863229f2aad Mon Sep 17 00:00:00 2001 From: Matthias Meister Date: Fri, 3 Apr 2026 19:01:48 +0200 Subject: [PATCH] refactor(app): scope heavy providers to authenticated route layouts --- app/(app)/layout.tsx | 31 ++++++++++++++ app/auth/[path]/page.tsx | 6 ++- app/dashboard/layout.tsx | 31 ++++++++++++++ app/layout.tsx | 26 ++---------- components/providers.tsx | 87 +++++++++++++++++++++++++--------------- 5 files changed, 125 insertions(+), 56 deletions(-) create mode 100644 app/(app)/layout.tsx create mode 100644 app/dashboard/layout.tsx diff --git a/app/(app)/layout.tsx b/app/(app)/layout.tsx new file mode 100644 index 0000000..829ea09 --- /dev/null +++ b/app/(app)/layout.tsx @@ -0,0 +1,31 @@ +import * as Sentry from "@sentry/nextjs"; + +import { InitUser } from "@/components/init-user"; +import { AppProviders } from "@/components/providers"; +import { getAuthUser, getToken } from "@/lib/auth-server"; + +export default async function AuthenticatedAppLayout({ + children, +}: { + children: React.ReactNode; +}) { + const initialToken = await getToken(); + const user = await getAuthUser(); + + if (user) { + const id = user.userId ?? String(user._id); + Sentry.setUser({ + id, + email: user.email ?? undefined, + }); + } else { + Sentry.setUser(null); + } + + return ( + + + {children} + + ); +} diff --git a/app/auth/[path]/page.tsx b/app/auth/[path]/page.tsx index 4d7d0d6..5d54469 100644 --- a/app/auth/[path]/page.tsx +++ b/app/auth/[path]/page.tsx @@ -1,6 +1,8 @@ import { AuthView } from "@daveyplate/better-auth-ui"; import { authViewPaths } from "@daveyplate/better-auth-ui/server"; +import { AuthViewProviders } from "@/components/providers"; + export const dynamicParams = false; export function generateStaticParams() { @@ -16,7 +18,9 @@ export default async function AuthPage({ return (
- + + +
); } diff --git a/app/dashboard/layout.tsx b/app/dashboard/layout.tsx new file mode 100644 index 0000000..1f68fe0 --- /dev/null +++ b/app/dashboard/layout.tsx @@ -0,0 +1,31 @@ +import * as Sentry from "@sentry/nextjs"; + +import { InitUser } from "@/components/init-user"; +import { AppProviders } from "@/components/providers"; +import { getAuthUser, getToken } from "@/lib/auth-server"; + +export default async function DashboardLayout({ + children, +}: { + children: React.ReactNode; +}) { + const initialToken = await getToken(); + const user = await getAuthUser(); + + if (user) { + const id = user.userId ?? String(user._id); + Sentry.setUser({ + id, + email: user.email ?? undefined, + }); + } else { + Sentry.setUser(null); + } + + return ( + + + {children} + + ); +} diff --git a/app/layout.tsx b/app/layout.tsx index 9282acb..95340cf 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,12 +1,9 @@ import type { Metadata } from "next"; import Script from "next/script"; import { Manrope } from "next/font/google"; -import * as Sentry from "@sentry/nextjs"; import "./globals.css"; import { cn } from "@/lib/utils"; -import { Providers } from "@/components/providers"; -import { InitUser } from "@/components/init-user"; -import { getAuthUser, getToken } from "@/lib/auth-server"; +import { RootProviders } from "@/components/providers"; import { getLocale, getMessages, getTimeZone } from "next-intl/server"; const manrope = Manrope({ subsets: ["latin"], variable: "--font-sans" }); @@ -47,20 +44,9 @@ export default async function RootLayout({ }: Readonly<{ children: React.ReactNode; }>) { - const initialToken = await getToken(); const locale = await getLocale(); const messages = await getMessages(); const timeZone = await getTimeZone(); - const user = await getAuthUser(); - if (user) { - const id = user.userId ?? String(user._id); - Sentry.setUser({ - id, - email: user.email ?? undefined, - }); - } else { - Sentry.setUser(null); - } return ( - - + {children} - + ); diff --git a/components/providers.tsx b/components/providers.tsx index 166e69f..342aa54 100644 --- a/components/providers.tsx +++ b/components/providers.tsx @@ -34,21 +34,40 @@ function SentryAuthUserSync() { return null; } -export function Providers({ - children, - initialToken, - locale, - messages, - timeZone, -}: { +type RootProvidersProps = { children: ReactNode; - initialToken?: string | null; locale?: string; messages?: AbstractIntlMessages; timeZone?: string; -}) { +}; + +type AppProvidersProps = { + children: ReactNode; + initialToken?: string | null; +}; + +function AuthUiShell({ children }: { children: ReactNode }) { const router = useRouter(); + return ( + router.refresh()} + Link={Link} + > + {children} + + ); +} + +export function RootProviders({ + children, + locale, + messages, + timeZone, +}: RootProvidersProps) { return ( - - - router.refresh()} - Link={Link} - > - {children} - - - + {children} ); } + +export function AppProviders({ children, initialToken }: AppProvidersProps) { + return ( + + + + {children} + + + + ); +} + +export function AuthViewProviders({ children }: { children: ReactNode }) { + return {children}; +}