From 220fe660708f10305bcabbb9ed65998906bbd036 Mon Sep 17 00:00:00 2001 From: Bissbert <43237892+Bissbert@users.noreply.github.com> Date: Mon, 4 May 2026 18:13:37 +0700 Subject: [PATCH 1/8] fix(seo): exclude /admin/ from sitemap, robots, and indexing The /admin/ route was leaking into the public sitemap-0.xml and was indexable. This: - Adds a sitemap filter so /admin/* URLs are excluded - Adds Disallow: /admin/ to robots.txt - Adds a noindex prop to BaseLayout and uses it on the admin page Resolves P0-5 from the 2026-05-04 UX review. --- astro.config.mjs | 4 +++- public/robots.txt | 3 +++ src/layouts/BaseLayout.astro | 6 ++++-- src/pages/admin/index.astro | 1 + 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/astro.config.mjs b/astro.config.mjs index e6a9c19..7991a0b 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -21,7 +21,9 @@ export default defineConfig({ }), react(), tailwind(), - sitemap(), + sitemap({ + filter: (page) => !page.includes('/admin'), + }), ], vite: { optimizeDeps: { diff --git a/public/robots.txt b/public/robots.txt index 5261405..a859c94 100644 --- a/public/robots.txt +++ b/public/robots.txt @@ -10,6 +10,9 @@ Sitemap: https://gemmology.dev/sitemap-index.xml # Disallow API endpoints (served by separate worker) Disallow: /api/ +# Disallow admin surface +Disallow: /admin/ + # Allow all crawlers to access static assets Allow: /crystals/ Allow: /og-images/ diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro index 0aa0fe8..e12a0ca 100644 --- a/src/layouts/BaseLayout.astro +++ b/src/layouts/BaseLayout.astro @@ -11,6 +11,7 @@ interface Props { type?: 'website' | 'article'; noHeader?: boolean; noFooter?: boolean; + noindex?: boolean; } const { @@ -20,7 +21,8 @@ const { canonical, type = 'website', noHeader = false, - noFooter = false + noFooter = false, + noindex = false } = Astro.props; // Generate canonical URL @@ -71,7 +73,7 @@ const fullTitle = `${title} | gemmology.dev`; - + diff --git a/src/pages/admin/index.astro b/src/pages/admin/index.astro index 58a3684..e2b123f 100644 --- a/src/pages/admin/index.astro +++ b/src/pages/admin/index.astro @@ -6,6 +6,7 @@ import { AdminPanel } from '../../components/admin/AdminPanel'; From cebc1490f9113c5f47a1618172f296ec0ef935ea Mon Sep 17 00:00:00 2001 From: Bissbert <43237892+Bissbert@users.noreply.github.com> Date: Mon, 4 May 2026 18:15:36 +0700 Subject: [PATCH 2/8] fix(a11y): promote learn property/comparison headings from h4 to h3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sections in /learn/* skipped h3 entirely — h2 (e.g. "Symmetry Elements") went straight to h4 children rendered by PropertyList and ComparisonBlock. That violates WCAG 1.3.1 and breaks screen-reader/LLM passage attribution. Both components now accept a headingLevel prop (default 3). SectionRenderer passes headingLevel=4 only when the components are nested inside a subsection (which already uses h3), preserving correct structure at every depth. Resolves P0-6 from the 2026-05-04 UX review. --- src/components/learn/ComparisonBlock.astro | 6 ++++-- src/components/learn/PropertyList.astro | 6 ++++-- src/components/learn/SectionRenderer.astro | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/components/learn/ComparisonBlock.astro b/src/components/learn/ComparisonBlock.astro index 7909583..0f2a9d0 100644 --- a/src/components/learn/ComparisonBlock.astro +++ b/src/components/learn/ComparisonBlock.astro @@ -13,9 +13,11 @@ interface ComparisonItem { interface Props { items: ComparisonItem[]; + headingLevel?: 3 | 4; } -const { items } = Astro.props; +const { items, headingLevel = 3 } = Astro.props; +const HeadingTag = `h${headingLevel}` as 'h3' | 'h4'; const variantClasses = { default: 'bg-slate-50 border-slate-200', @@ -50,7 +52,7 @@ const gridCols = items.length === 2 const variant = item.variant || 'default'; return ( -

{item.title}

+ {item.title}