From a66e08fe16c2ce7f04eae36dc1b2177fba0ddec9 Mon Sep 17 00:00:00 2001 From: Alaeddin <15094821+BSalaeddin@users.noreply.github.com> Date: Sat, 12 Sep 2026 08:38:38 +0100 Subject: [PATCH] feat(seo): A-Z store directory and neighbour links so no store page is orphaned --- apps/caramel-app/e2e/seo-a11y.spec.ts | 88 +++++ .../app/(marketing)/coupons/[store]/page.tsx | 5 + .../src/app/(marketing)/coupons/page.tsx | 4 + .../coupons/stores/[letter]/page.tsx | 222 +++++++++++++ .../app/(marketing)/coupons/stores/page.tsx | 123 +++++++ .../app/(marketing)/supported-stores/page.tsx | 7 + apps/caramel-app/src/app/llms.txt/route.ts | 1 + apps/caramel-app/src/app/sitemap.ts | 38 ++- .../components/coupons/store-letter-strip.tsx | 51 +++ .../components/coupons/store-neighbours.tsx | 83 +++++ .../caramel-app/src/layouts/Footer/Footer.tsx | 1 + apps/caramel-app/src/lib/couponsRepo.ts | 68 ++++ apps/caramel-app/src/lib/seo/sitemapStores.ts | 9 + .../caramel-app/src/lib/seo/storeDirectory.ts | 204 ++++++++++++ .../src/lib/seo/storeDirectoryCache.ts | 79 +++++ .../tests/integration/coupons-read.itest.ts | 36 +++ .../unit/coupons-store-directory.test.ts | 304 ++++++++++++++++++ .../tests/unit/couponsRepo.test.ts | 64 ++++ apps/caramel-app/tests/unit/sitemap.test.ts | 86 ++++- .../tests/unit/storeDirectory.test.ts | 272 ++++++++++++++++ .../tests/unit/storeDirectoryCache.test.ts | 86 +++++ 21 files changed, 1818 insertions(+), 13 deletions(-) create mode 100644 apps/caramel-app/src/app/(marketing)/coupons/stores/[letter]/page.tsx create mode 100644 apps/caramel-app/src/app/(marketing)/coupons/stores/page.tsx create mode 100644 apps/caramel-app/src/components/coupons/store-letter-strip.tsx create mode 100644 apps/caramel-app/src/components/coupons/store-neighbours.tsx create mode 100644 apps/caramel-app/src/lib/seo/storeDirectory.ts create mode 100644 apps/caramel-app/src/lib/seo/storeDirectoryCache.ts create mode 100644 apps/caramel-app/tests/unit/coupons-store-directory.test.ts create mode 100644 apps/caramel-app/tests/unit/storeDirectory.test.ts create mode 100644 apps/caramel-app/tests/unit/storeDirectoryCache.test.ts diff --git a/apps/caramel-app/e2e/seo-a11y.spec.ts b/apps/caramel-app/e2e/seo-a11y.spec.ts index 8470f171..dc5bc395 100644 --- a/apps/caramel-app/e2e/seo-a11y.spec.ts +++ b/apps/caramel-app/e2e/seo-a11y.spec.ts @@ -58,6 +58,11 @@ test.describe('SEO & Accessibility Basics', () => { // seeded app (e2e-pr/local) and the deployed dev site (e2e-push). Only the // codecademy.com assertion depends on a specific catalog row, so only it is // DATABASE_URL-gated; everything else holds on any non-empty catalog. +// Distinct hrefs matching `re` (group 1) in raw HTML, in document order. +function hrefsOf(html: string, re: RegExp): string[] { + return Array.from(new Set(Array.from(html.matchAll(re)).map(m => m[1]!))) +} + function extractJsonLd(html: string): Array> { const scriptRe = /