From 95b23770db3312d0dc12654c47b76aa595038d68 Mon Sep 17 00:00:00 2001 From: Gabriel Vieira Date: Tue, 2 Jun 2026 19:24:36 -0300 Subject: [PATCH] fix(navbar): /me/ai-usage showed the visitor navbar while authenticated (#71) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit /me/* is authenticated but lives outside /[tenant], so it never got the tenant layout. ConditionalNavbar treated /me/ as a public prefix, so the root layout rendered the visitor navbar (Entrar/Começar) on a logged-in page even though the body still showed personal metrics. - Add src/app/me/layout.tsx: authenticated chrome (session guard + TenantProvider + TenantNavbar) scoped to the user's primary org. - Drop /me/ from ConditionalNavbar PUBLIC_PREFIXES so the visitor navbar no longer renders there. - Move page padding into the layout (p-4 sm:p-6), matching how [tenant]/layout.tsx owns padding; drop the floating-navbar offset. Co-Authored-By: Claude Opus 4.8 (1M context) --- platform/src/app/me/ai-usage/page.tsx | 2 +- platform/src/app/me/layout.tsx | 46 +++++++++++++++++++ platform/src/components/ConditionalNavbar.tsx | 5 +- 3 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 platform/src/app/me/layout.tsx diff --git a/platform/src/app/me/ai-usage/page.tsx b/platform/src/app/me/ai-usage/page.tsx index 0cccd06..6b4d606 100644 --- a/platform/src/app/me/ai-usage/page.tsx +++ b/platform/src/app/me/ai-usage/page.tsx @@ -54,7 +54,7 @@ export default async function PersonalAIUsagePage({ }); return ( -
+

{t("meAiUsage.title")}

diff --git a/platform/src/app/me/layout.tsx b/platform/src/app/me/layout.tsx new file mode 100644 index 0000000..ac0f263 --- /dev/null +++ b/platform/src/app/me/layout.tsx @@ -0,0 +1,46 @@ +import type { ReactNode } from "react"; + +import { redirect } from "next/navigation"; + +import { getServerSession } from "next-auth/next"; + +import { TenantNavbar } from "@/components/tenant/TenantNavbar"; +import { TenantProvider } from "@/components/tenant/TenantProvider"; +import { authOptions } from "@/lib/auth"; + +type SessionOrganization = { + slug: string; + role?: string | null; +}; + +type SessionUser = { + organizations?: SessionOrganization[]; +}; + +// Routes under /me are authenticated but cross-organization (self-only), so +// they live outside /[tenant] and never get the tenant layout. Without this +// layout the root ConditionalNavbar fell back to the public/visitor navbar, +// making an authenticated page look logged out (issue #71). Render the +// authenticated TenantNavbar here, scoped to the user's primary org for its +// links and org switcher. +export default async function MeLayout({ children }: { children: ReactNode }) { + const session = await getServerSession(authOptions); + if (!session) { + redirect("/auth/signin?callbackUrl=/me/ai-usage"); + } + + const sessionUser = session.user as SessionUser | undefined; + const primaryOrg = sessionUser?.organizations?.[0]; + + return ( + +

+ +
{children}
+
+ + ); +} diff --git a/platform/src/components/ConditionalNavbar.tsx b/platform/src/components/ConditionalNavbar.tsx index 9a12a92..a19fddc 100644 --- a/platform/src/components/ConditionalNavbar.tsx +++ b/platform/src/components/ConditionalNavbar.tsx @@ -13,7 +13,10 @@ const PUBLIC_ROUTES = new Set([ '/deck', ]); -const PUBLIC_PREFIXES = ['/cli/', '/me/']; +// Note: /me/* is authenticated (self-only) and renders its own TenantNavbar +// via src/app/me/layout.tsx — it must NOT be treated as public here, otherwise +// the visitor navbar shows on a logged-in page (issue #71). +const PUBLIC_PREFIXES = ['/cli/']; const HIDDEN_PREFIXES = [ '/auth',