From 136e15f68e88dd5d42df47982eb27192655e6385 Mon Sep 17 00:00:00 2001 From: Fabian Meyer <44942030+dinooo13@users.noreply.github.com> Date: Wed, 30 Sep 2026 21:32:16 +0200 Subject: [PATCH 1/2] Strengthen person entity signals and fix canonical URL redirects Search Console showed that every sitemap entry, canonical tag and internal link used slash-less URLs while the host serves directory indexes and 301-redirects /labs to /labs/. Google had indexed the slash form of three pages and never crawled six of the nine content pages. - Make the trailing-slash form canonical site-wide: site.trailingSlash, canonical normalisation in app.vue, path helpers, nav and back links, breadcrumbs, detail-page canonicals, error pages, llms.txt and rss.xml. - Extend the schema.org Person identity with name parts, handle, city, nationality, employer URL, topics, third-party profile pages and the speaker spotlight article, and show the city in the hero. - Return 410 for the whole legacy Hugo URL space (/p/, /page/, /categories/, /archives/, /search/, /about/) and stop the host's one-year cache on HTML, XML and TXT files. - Declare the portrait explicitly in the sitemap instead of the double-escaped ipx thumbnail that image discovery produced. Co-Authored-By: Claude Fable 5.1 --- AGENTS.md | 2 +- CLAUDE.md | 2 +- app/app.vue | 6 ++- app/components/AppHeader.vue | 3 +- app/components/HomeView.vue | 12 +++++ app/components/LabDetailView.vue | 4 +- app/components/TalkDetailView.vue | 4 +- app/pages/404.vue | 4 +- app/pages/410.vue | 4 +- app/pages/labs/[slug].vue | 4 +- app/pages/labs/index.vue | 2 +- app/pages/speaking/[slug].vue | 4 +- app/pages/speaking/index.vue | 2 +- app/utils/labs.ts | 2 +- app/utils/links.ts | 4 +- app/utils/speaking.ts | 2 +- build/generate-content-artifacts.ts | 16 +++--- content.config.ts | 1 + content/index.yml | 5 +- nuxt.config.ts | 79 ++++++++++++++++++++++++++--- public/.htaccess.tpl | 27 ++++++++-- 21 files changed, 147 insertions(+), 42 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index eb1e31c..9e93239 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -143,7 +143,7 @@ repoUrl: https://... # optional GitHub repo URL note: ... # optional note shown on detail page ``` -The slug used for the URL is derived from the filename (e.g., `my-project.yml` → `/labs/my-project`). +The slug used for the URL is derived from the filename (e.g., `my-project.yml` → `/labs/my-project/`). ### Adding a talk entry diff --git a/CLAUDE.md b/CLAUDE.md index 72884dc..dc18419 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -145,7 +145,7 @@ repoUrl: https://... # optional GitHub repo URL note: ... # optional note shown on detail page ``` -The slug used for the URL is derived from the filename (e.g., `my-project.yml` → `/labs/my-project`). +The slug used for the URL is derived from the filename (e.g., `my-project.yml` → `/labs/my-project/`). ### Adding a talk entry diff --git a/app/app.vue b/app/app.vue index ca58635..a4b5ab3 100644 --- a/app/app.vue +++ b/app/app.vue @@ -5,8 +5,12 @@ const baseURL = runtimeConfig.app.baseURL const basePrefix = baseURL.replace(/\/$/, '') +// Canonical URLs use the trailing-slash form (see `site.trailingSlash` in +// nuxt.config.ts); normalise here so a slash-less route never leaks through. const canonicalUrl = computed(() => { - return new URL(`${basePrefix}${route.path || '/'}`, runtimeConfig.public.siteUrl).toString() + const path = route.path || '/' + const normalised = path.endsWith('/') ? path : `${path}/` + return new URL(`${basePrefix}${normalised}`, runtimeConfig.public.siteUrl).toString() }) useHead({ diff --git a/app/components/AppHeader.vue b/app/components/AppHeader.vue index bfc5cbf..a58659d 100644 --- a/app/components/AppHeader.vue +++ b/app/components/AppHeader.vue @@ -7,7 +7,8 @@ const links = computed(() => navLinks.map(link => ({ }))) const isActive = (to: string) => { - return to === '/' ? route.path === '/' : route.path.startsWith(to) + const current = route.path.endsWith('/') ? route.path : `${route.path}/` + return to === '/' ? current === '/' : current.startsWith(to) } diff --git a/app/components/HomeView.vue b/app/components/HomeView.vue index 4437e6d..0753910 100644 --- a/app/components/HomeView.vue +++ b/app/components/HomeView.vue @@ -106,6 +106,18 @@ const reveal = { >>_ {{ current.title }}

+

+

+

{{ intro.lead }}

diff --git a/app/components/LabDetailView.vue b/app/components/LabDetailView.vue index 1fb3905..b5e6e64 100644 --- a/app/components/LabDetailView.vue +++ b/app/components/LabDetailView.vue @@ -59,7 +59,7 @@ const reveal = {
  • labs
  • @@ -375,7 +375,7 @@ const reveal = { eyebrow="Labs" heading-id="signal-related-labs" title="More from the lab" - :link="{ label: 'All labs', to: '/labs' }" + :link="{ label: 'All labs', to: '/labs/' }" />