diff --git a/site/astro.config.mjs b/site/astro.config.mjs index fc94e64..25e65d9 100644 --- a/site/astro.config.mjs +++ b/site/astro.config.mjs @@ -67,10 +67,15 @@ const base = '/awesome-prometheus-alerts'; export default defineConfig({ site: 'https://samber.github.io', base, - redirects: buildRedirects(base), + redirects: { ...buildRedirects(base) }, output: 'static', integrations: [ sitemap({ + /** Exclude redirect source URLs from the sitemap. + * Astro generates static HTML redirect files for every entry in `redirects`, and the + * sitemap plugin naively picks them up. We must explicitly filter them out so that Google + * only indexes canonical destinations, not the redirect intermediaries. */ + filter: (page) => !page.includes('.html'), serialize(item) { const path = new URL(item.url).pathname; const segments = path.replace(/^\/|\/$/g, '').split('/').filter(Boolean); @@ -78,22 +83,22 @@ export default defineConfig({ if (segments.length <= 1) { // Homepage - return { ...item, changefreq: 'weekly', priority: 1.0, lastmod: new Date() }; + return { ...item, changefreq: 'weekly', priority: 1.0 }; } if (segments.length === 2 && segments[1] === 'rules') { // /rules/ index - return { ...item, changefreq: 'weekly', priority: 0.9, lastmod: new Date() }; + return { ...item, changefreq: 'weekly', priority: 0.9 }; } if (segments.length === 3 && segments[1] === 'rules') { // /rules/[group]/ index - return { ...item, changefreq: 'monthly', priority: 0.7, lastmod: new Date() }; + return { ...item, changefreq: 'monthly', priority: 0.7 }; } if (segments.length === 4 && segments[1] === 'rules') { // /rules/[group]/[service]/ — main content pages - return { ...item, changefreq: 'monthly', priority: 0.8, lastmod: new Date() }; + return { ...item, changefreq: 'monthly', priority: 0.8 }; } // Guide pages and others - return { ...item, changefreq: 'yearly', priority: 0.6, lastmod: new Date() }; + return { ...item, changefreq: 'yearly', priority: 0.6 }; }, }), icon(), diff --git a/site/src/pages/rules/[group]/[service].astro b/site/src/pages/rules/[group]/[service].astro index d73baea..9ecdb9c 100644 --- a/site/src/pages/rules/[group]/[service].astro +++ b/site/src/pages/rules/[group]/[service].astro @@ -22,12 +22,10 @@ const ruleCount = getRuleCount(service); const groupIndex = data.groups.findIndex((g) => getGroupSlug(g) === groupSlug) + 1; const serviceIndex = group.services.findIndex((s) => getServiceSlug(s) === serviceSlug) + 1; -// Build exporters summary for meta description +// Build exporters summary for keywords (kept for but removed from description) const exporterNames = service.exporters.map((e) => e.name).filter(Boolean).join(', '); -const metaDescBase = `${ruleCount} ready-to-use Prometheus alert rules for ${service.name}${exporterNames ? ` (${exporterNames})` : ''}. Copy-paste YAML for critical and warning alerts.`; -const metaDesc = metaDescBase.length > 160 - ? `${ruleCount} ready-to-use Prometheus alert rules for ${service.name}. Copy-paste YAML for critical and warning alerts.` - : metaDescBase; +// Description: lead with count + service + format signals. Exporter names go in keywords, not here. +const metaDesc = `${ruleCount} ready-to-use Prometheus alert rules for ${service.name}. Critical and warning YAML snippets — copy-paste into your Prometheus config or wget download.`; // FAQ JSON-LD for GEO (AI search engines) const faqItems = service.exporters.flatMap((exp) => @@ -55,7 +53,7 @@ const jsonLd = { { '@type': 'TechArticle', '@id': `${pageUrl}#article`, - headline: `${service.name} Prometheus Alert Rules`, + headline: `${service.name} Prometheus Alert Rules (${ruleCount})`, description: metaDesc, about: `Prometheus monitoring for ${service.name}`, url: pageUrl, @@ -76,7 +74,7 @@ const jsonLd = { ---