From fc8a58557ab965768f96e8a8787a4e2beb1c565e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Fri, 15 May 2026 18:56:49 +0200 Subject: [PATCH] fix(auth): unblock the about page for unauthenticated visitors The /about page (GeoLite2 attribution) was listed in proxy.ts PUBLIC_PATHS but missed in AuthShell's client-side PUBLIC_PATHS, so unauthenticated visitors bounced through /auth/login. Add /about to the AuthShell list and treat it as a standalone public page (same edge-to-edge render as /privacy). Apply safe-area-inset-top on the privacy and about sticky headers so iOS notch / Dynamic Island viewports don't overlap the brand row. Add a default-closed Contents
TOC at the top of the privacy policy and wrap every HealthKit identifier with break-all so long camelCase strings (heartRateVariabilitySDNN, environmentalAudioExposure) wrap inside narrow viewports. --- src/app/about/page.tsx | 2 +- src/app/privacy/page.tsx | 136 +++++++++++++++++++++++---- src/components/layout/auth-shell.tsx | 18 +++- 3 files changed, 133 insertions(+), 23 deletions(-) diff --git a/src/app/about/page.tsx b/src/app/about/page.tsx index 0fda9a5ff..e9020ebb0 100644 --- a/src/app/about/page.tsx +++ b/src/app/about/page.tsx @@ -56,7 +56,7 @@ function Section({ export default function AboutPage() { return (
-
+
+

HealthLog is an open-source, self-hostable personal-health-tracking @@ -288,64 +384,64 @@ export default function PrivacyPage() { data-slot="privacy-hk-quantity" >

  • - bodyMass + bodyMass
  • - bodyFatPercentage + bodyFatPercentage
  • - bodyTemperature + bodyTemperature
  • - bloodPressureSystolic + bloodPressureSystolic
  • - bloodPressureDiastolic + bloodPressureDiastolic
  • - bloodGlucose + bloodGlucose
  • - oxygenSaturation + oxygenSaturation
  • - heartRate + heartRate
  • - restingHeartRate + restingHeartRate
  • - heartRateVariabilitySDNN + heartRateVariabilitySDNN
  • - vo2Max + vo2Max
  • - stepCount + stepCount
  • - activeEnergyBurned + activeEnergyBurned
  • - flightsClimbed + flightsClimbed
  • - distanceWalkingRunning + distanceWalkingRunning
  • - environmentalAudioExposure + environmentalAudioExposure
  • - headphoneAudioExposure + headphoneAudioExposure
  • - timeInDaylight (iOS 17 and later) + timeInDaylight (iOS 17 and later)
  • HKCategoryTypeIdentifier:

    • - sleepAnalysis — read with full + sleepAnalysis — read with full per-stage granularity (Awake, REM, Core, Deep). Stages are stored server-side as separate rows so the chart can stack them.
    • diff --git a/src/components/layout/auth-shell.tsx b/src/components/layout/auth-shell.tsx index 87b504585..17f4aa547 100644 --- a/src/components/layout/auth-shell.tsx +++ b/src/components/layout/auth-shell.tsx @@ -11,7 +11,18 @@ import { BottomNav } from "./bottom-nav"; import { SidebarNav } from "./sidebar-nav"; import { TopBar } from "./top-bar"; -const PUBLIC_PATHS = ["/auth/login", "/auth/register", "/privacy"]; +// v1.4.27 MB6 — `/about` joins the public-path list so the GeoLite2 +// CC BY-SA 4.0 attribution stays reachable for unauthenticated +// visitors. The `/about` route is already registered in `proxy.ts` +// PUBLIC_PATHS; this constant gates the client-side auth shell, and +// both lists must agree or the route round-trips through the +// sign-in redirect. +const PUBLIC_PATHS = [ + "/auth/login", + "/auth/register", + "/privacy", + "/about", +]; export function AuthShell({ children }: { children: React.ReactNode }) { const { user, isAuthenticated, isLoading } = useAuth(); @@ -25,7 +36,10 @@ export function AuthShell({ children }: { children: React.ReactNode }) { // squash a 3000-word policy into a "login card" layout, so we let it // render edge-to-edge while still resolving as a public page for the // auth gate above. - const isStandalonePublicPage = pathname.startsWith("/privacy"); + // v1.4.27 MB6 — `/about` follows the same shape (own header, own + // footer, full-width body), so it joins the standalone list. + const isStandalonePublicPage = + pathname.startsWith("/privacy") || pathname.startsWith("/about"); const isAdminPage = pathname.startsWith("/admin"); const isOnboardingPage = pathname === "/onboarding"; const showUnlockNotifier = isAuthenticated && !isPublicPage && !!user?.id;