awesome-prometheus-alerts/site/src/pages/rules/index.astro
Samuel Berthe 6ff7e74524
feat: migrate website from Jekyll to Astro
Rebuilds the site using Astro (SSG) with Tailwind CSS v4, replacing the
Jekyll/Cayman theme. Key changes:

- Splits the monolithic /rules page into 110 statically-generated pages
  (92 per-service + 13 group index + homepage + guide pages) for SEO
- URL structure: /rules/[group-slug]/[service-slug]/ with backward-
  compatibility redirect map for old anchor-based URLs (/rules#redis)
- Modern UI: Prometheus-orange accent, dark mode (system + toggle),
  sticky sidebar, responsive layout, copy-to-clipboard per rule/section
- SEO: per-page <title>, <meta description>, Open Graph, Twitter Card,
  canonical URLs, sitemap.xml via @astrojs/sitemap
- GEO: FAQPage JSON-LD schema on each service page (rules as Q&A pairs
  for AI search engines), TechArticle schema, BreadcrumbList
- Search: Pagefind (build-time index, lazy-loaded, ~200KB)
- Zero JS by default; copy buttons and theme toggle use inline scripts
- New CI: .github/workflows/deploy.yml builds Astro + Pagefind and
  deploys to GitHub Pages via actions/deploy-pages
- Existing dist.yml and test.yml workflows are untouched
- _data/rules.yml remains the single source of truth

Note: GitHub Pages source must be changed from "Build from branch"
(Jekyll) to "GitHub Actions" in repository settings.
2026-04-06 21:47:42 +02:00

84 lines
3.3 KiB
Text

---
import BaseLayout from '../../layouts/BaseLayout.astro';
import ServiceCard from '../../components/ServiceCard.astro';
import SearchWidget from '../../components/SearchWidget.astro';
import { data, getGroupSlug, getRuleCount, getTotalRuleCount, getTotalServiceCount, buildRedirectMap } from '../../data/rules';
const base = import.meta.env.BASE_URL;
const totalRules = getTotalRuleCount();
const totalServices = getTotalServiceCount();
const redirectMap = buildRedirectMap(base);
---
<BaseLayout
title="Prometheus Alerting Rules | Awesome Prometheus Alerts"
description={`Browse ${totalRules} Prometheus alerting rules across ${totalServices} services. Organized by category: databases, Kubernetes, cloud providers, message brokers, and more.`}
>
<!-- Old-anchor redirect handler -->
<script define:vars={{ redirectMap }}>
if (window.location.hash) {
const anchor = window.location.hash.slice(1);
const target = redirectMap[anchor];
if (target) {
window.location.replace(target);
}
}
</script>
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<!-- Header -->
<div class="mb-8">
<h1 class="text-2xl font-bold text-slate-900 dark:text-white mb-2">Alert Rules</h1>
<p class="text-slate-500 dark:text-slate-400">
{totalRules} alerting rules across {totalServices} services and {data.groups.length} categories.
</p>
</div>
<!-- Search -->
<div class="mb-8 max-w-xl">
<SearchWidget />
</div>
<!-- Caution banner -->
<div class="mb-8 p-4 rounded-xl border border-amber-200 dark:border-amber-800/50 bg-amber-50 dark:bg-amber-900/20">
<div class="flex gap-3">
<span class="text-amber-500 flex-shrink-0 mt-0.5">⚠️</span>
<div>
<h2 class="text-sm font-semibold text-amber-800 dark:text-amber-200 mb-1">Caution</h2>
<p class="text-sm text-amber-700 dark:text-amber-300">
Alert thresholds depend on the nature of your applications.
Some queries may have arbitrary tolerance thresholds.
Building an efficient monitoring platform takes time. 😉
</p>
</div>
</div>
</div>
<!-- Groups -->
<div class="space-y-10">
{data.groups.map((group) => {
const groupSlug = getGroupSlug(group);
const groupRuleCount = group.services.reduce((sum, svc) => sum + getRuleCount(svc), 0);
return (
<section>
<div class="flex items-center justify-between mb-4">
<h2 class="text-lg font-semibold text-slate-800 dark:text-slate-100">
<a href={`${base}/rules/${groupSlug}/`} class="hover:text-brand dark:hover:text-brand-dark transition-colors">
{group.name}
</a>
</h2>
<span class="text-sm text-slate-400 dark:text-slate-500">
{group.services.length} services · {groupRuleCount} rules
</span>
</div>
<div class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-3">
{group.services.map((service) => (
<ServiceCard service={service} group={group} base={base} />
))}
</div>
</section>
);
})}
</div>
</div>
</BaseLayout>