From f387bcf12def501dae3b2b3da48315382e8f445b Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 25 Sep 2026 09:31:50 +0000 Subject: [PATCH 1/2] feat: update the description tags upon client-side navigation (vikejs/vike#3524) The +description setting (and useConfig({ description })) now also updates and upon client-side navigation, the same way +title updates document.title. Some tools read these tags from the DOM of the current page, e.g. browser extensions for bookmarking and social sharing. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_019AAZpDLjrcSr6BwQgpVs9a --- examples/full/.testRun.ts | 38 +++++++++++++++++++ examples/full/pages/images/+Page.tsx | 2 +- examples/full/pages/without-ssr/+config.ts | 1 + packages/vike-react/src/config.ts | 2 +- .../src/hooks/useConfig/configsClientSide.ts | 2 +- .../src/hooks/useConfig/useConfig-client.ts | 4 +- .../src/integration/applyHeadSettings.tsx | 21 +++++++++- .../src/integration/onRenderClient.tsx | 3 +- packages/vike-react/src/types/Config.ts | 2 +- 9 files changed, 67 insertions(+), 8 deletions(-) diff --git a/examples/full/.testRun.ts b/examples/full/.testRun.ts index b1cd5bd88..427cbea04 100644 --- a/examples/full/.testRun.ts +++ b/examples/full/.testRun.ts @@ -5,6 +5,8 @@ import assert from 'node:assert' let isProd: boolean const titleDefault = 'My Vike + React App' +// Set by inside the component of /images +const descriptionImages = 'Logo created by Romuald Brillout' const pages = { '/': { title: titleDefault, @@ -30,6 +32,7 @@ const pages = { }, '/without-ssr': { title: 'No SSR', + description: 'Page rendered only in the browser', text: 'This page is rendered only in the browser', counter: true, noSSR: true, @@ -48,6 +51,7 @@ function testRun(cmd: `pnpm run ${'dev' | 'preview'}`) { testPages() testPageNavigation_betweenWithSSRAndWithout() testPageNavigation_titleUpdate() + testPageNavigation_descriptionUpdate() testUseConfig() testReactSetting() testClientOnly() @@ -126,6 +130,38 @@ async function expectTitle(title: string) { }) } +// The description tags are updated upon client-side navigation. https://github.com/vikejs/vike/issues/3524 +function testPageNavigation_descriptionUpdate() { + test('description update client-side page navigation', async () => { + await page.goto(getServerUrl() + '/') + await testCounter() + await expectDescription(null) + // Set by +description + await page.click('a:has-text("Without SSR")') + await testCounter() + await expectDescription(pages['/without-ssr'].description) + // Set by useConfig() inside +data() + await page.click('a[href="/star-wars"]') + await expectDescription(pages['/star-wars'].description) + // Set by inside UI components + await page.click('a:has-text("useConfig()")') + await testCounter() + await expectDescription(descriptionImages) + await page.click('a:has-text("Without SSR")') + await testCounter() + await expectDescription(pages['/without-ssr'].description) + await ensureWasClientSideRouted('/pages/index') + }) +} +async function expectDescription(description: string | null) { + await autoRetry(async () => { + const getContent = (selector: string) => + page.evaluate((selector) => document.querySelector(selector)?.getAttribute('content') ?? null, selector) + expect(await getContent('meta[name="description"]')).toBe(description) + expect(await getContent('meta[property="og:description"]')).toBe(description) + }) +} + function testPages() { Object.entries(pages).forEach(([url, pageInfo]) => { testPage({ url, ...pageInfo }) @@ -202,6 +238,8 @@ function testUseConfig() { test('useConfig() HTML', async () => { const html = await fetchHtml('/images') expect(getTitle(html)).toBe(titleImages) + expect(html).toContain(``) + expect(html).toContain(``) expect(html).toMatch( partRegex`