From 3e9a3b41e1ac805d75953a1bc88ddc006bedd63f Mon Sep 17 00:00:00 2001 From: Peter White Date: Tue, 6 Oct 2026 14:27:08 +0200 Subject: [PATCH] Clarify not-found copy for login-protected pages --- .../components/SitePage/SitePageNotFound.tsx | 31 ++++++++++++------- packages/gitbook/src/intl/translations/ar.ts | 8 +++-- packages/gitbook/src/intl/translations/bg.ts | 8 +++-- packages/gitbook/src/intl/translations/cs.ts | 8 +++-- packages/gitbook/src/intl/translations/da.ts | 8 +++-- packages/gitbook/src/intl/translations/de.ts | 8 +++-- packages/gitbook/src/intl/translations/el.ts | 8 +++-- packages/gitbook/src/intl/translations/en.ts | 9 ++++-- packages/gitbook/src/intl/translations/es.ts | 8 +++-- packages/gitbook/src/intl/translations/et.ts | 9 ++++-- packages/gitbook/src/intl/translations/fi.ts | 8 +++-- packages/gitbook/src/intl/translations/fr.ts | 8 +++-- packages/gitbook/src/intl/translations/he.ts | 8 +++-- packages/gitbook/src/intl/translations/hi.ts | 9 ++++-- packages/gitbook/src/intl/translations/hr.ts | 8 +++-- packages/gitbook/src/intl/translations/hu.ts | 9 ++++-- packages/gitbook/src/intl/translations/id.ts | 8 +++-- packages/gitbook/src/intl/translations/it.ts | 8 +++-- packages/gitbook/src/intl/translations/ja.ts | 8 +++-- packages/gitbook/src/intl/translations/ko.ts | 9 ++++-- packages/gitbook/src/intl/translations/lt.ts | 8 +++-- packages/gitbook/src/intl/translations/lv.ts | 9 ++++-- packages/gitbook/src/intl/translations/ms.ts | 8 +++-- packages/gitbook/src/intl/translations/nl.ts | 8 +++-- packages/gitbook/src/intl/translations/no.ts | 9 ++++-- packages/gitbook/src/intl/translations/pl.ts | 9 ++++-- .../gitbook/src/intl/translations/pt-br.ts | 8 +++-- packages/gitbook/src/intl/translations/pt.ts | 8 +++-- packages/gitbook/src/intl/translations/ro.ts | 8 +++-- packages/gitbook/src/intl/translations/ru.ts | 8 +++-- packages/gitbook/src/intl/translations/sk.ts | 8 +++-- packages/gitbook/src/intl/translations/sl.ts | 9 ++++-- packages/gitbook/src/intl/translations/sv.ts | 9 ++++-- packages/gitbook/src/intl/translations/th.ts | 8 +++-- packages/gitbook/src/intl/translations/tr.ts | 9 ++++-- packages/gitbook/src/intl/translations/uk.ts | 9 ++++-- packages/gitbook/src/intl/translations/vi.ts | 9 ++++-- packages/gitbook/src/intl/translations/yue.ts | 8 +++-- .../gitbook/src/intl/translations/zh-tw.ts | 8 +++-- packages/gitbook/src/intl/translations/zh.ts | 8 +++-- packages/gitbook/src/lib/adaptive.test.ts | 17 ++++++++++ packages/gitbook/src/lib/adaptive.ts | 7 +++++ 42 files changed, 290 insertions(+), 90 deletions(-) create mode 100644 packages/gitbook/src/lib/adaptive.test.ts diff --git a/packages/gitbook/src/components/SitePage/SitePageNotFound.tsx b/packages/gitbook/src/components/SitePage/SitePageNotFound.tsx index 94e394fc6..d6796c36e 100644 --- a/packages/gitbook/src/components/SitePage/SitePageNotFound.tsx +++ b/packages/gitbook/src/components/SitePage/SitePageNotFound.tsx @@ -22,6 +22,7 @@ import { } from '../SpaceLayout/SpaceLayoutContext'; import { TrackPageViewEvent } from '@/components/Insights'; import { t, tString, useLanguage } from '@/intl/client'; +import { isVisitorAuthenticated } from '@/lib/adaptive'; import { tcls } from '@/lib/tailwind'; const RELATED_PAGES_COUNT = 5; @@ -36,7 +37,7 @@ export function SitePageNotFound() { const basePath = useSpaceBasePath(); const adaptiveAuthLoginHref = useSiteAdaptiveAuthLoginHref(); const siteIndexURL = useSiteIndexURL(); - const { siteSpaceId } = useCurrentContent(); + const { siteSpaceId, visitorAuthClaims } = useCurrentContent(); const language = useLanguage(); const router = useRouter(); const searchParams = useSearchParams(); @@ -44,6 +45,13 @@ export function SitePageNotFound() { const setSearchState = useSetSearchState(); const { assistants } = useAI(); + const isAuthenticated = isVisitorAuthenticated(visitorAuthClaims); + const [titleKey, messageKey] = !adaptiveAuthLoginHref + ? (['notfound_title', 'notfound'] as const) + : isAuthenticated + ? (['notfound_adaptive_no_access_title', 'notfound_adaptive_no_access'] as const) + : (['notfound_adaptive_title', 'notfound_adaptive'] as const); + // Show the assistant input when a non-search assistant is available (i.e. not just ask-AI). const assistant = assistants.find((candidate) => candidate.mode !== 'search') ?? null; const inputLabel = tString(language, assistant ? 'search_or_ask' : 'search'); @@ -124,21 +132,20 @@ export function SitePageNotFound() { 'text-tint-strong' )} > - {t( - language, - adaptiveAuthLoginHref - ? 'notfound_adaptive_title' - : 'notfound_title' - )} + {t(language, titleKey)}

- {t( - language, - adaptiveAuthLoginHref ? 'notfound_adaptive' : 'notfound' - )} + {t(language, messageKey)}

- {adaptiveAuthLoginHref ? ( + {adaptiveAuthLoginHref && isAuthenticated ? ( + // Re-running login refreshes the visitor's claims, e.g. after a role change. + + ) : adaptiveAuthLoginHref ? (
{ + it('is false without claims', () => { + expect(isVisitorAuthenticated({})).toBe(false); + }); + + it('is false with only unsigned claims', () => { + expect(isVisitorAuthenticated({ unsigned: { plan: 'free' } })).toBe(false); + }); + + it('is true with signed claims', () => { + expect(isVisitorAuthenticated({ role: 'admin', unsigned: {} })).toBe(true); + }); +}); diff --git a/packages/gitbook/src/lib/adaptive.ts b/packages/gitbook/src/lib/adaptive.ts index 5152d58a7..5be4613c0 100644 --- a/packages/gitbook/src/lib/adaptive.ts +++ b/packages/gitbook/src/lib/adaptive.ts @@ -24,3 +24,10 @@ export function getVisitorAuthClaims(siteData: SiteURLData): VisitorAuthClaims { export function getVisitorAuthClaimsFromToken(token: SiteAPIToken): VisitorAuthClaims { return token.claims ?? {}; } + +/** + * Whether the visitor is authenticated, i.e. has claims beyond the unsigned ones anyone can set. + */ +export function isVisitorAuthenticated(claims: VisitorAuthClaims): boolean { + return Object.keys(claims).some((key) => key !== 'unsigned'); +}