awesome-prometheus-alerts/site/src/components/ServiceCard.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

41 lines
1.4 KiB
Text

---
import type { Service, Group } from '../data/rules';
import { getRuleCount, getGroupSlug, getServiceSlug } from '../data/rules';
interface Props {
service: Service;
group: Group;
base: string;
}
const { service, group, base } = Astro.props;
const ruleCount = getRuleCount(service);
const groupSlug = getGroupSlug(group);
const serviceSlug = getServiceSlug(service);
const href = `${base}/rules/${groupSlug}/${serviceSlug}/`;
const exporterNames = service.exporters
.map((e) => e.name)
.filter(Boolean)
.slice(0, 3);
---
<a
href={href}
class="group block p-4 rounded-xl border border-slate-200 dark:border-slate-700/60 bg-white dark:bg-slate-900 hover:border-brand/40 dark:hover:border-brand-dark/40 hover:shadow-sm transition-all duration-150"
>
<div class="flex items-start justify-between gap-2 mb-2">
<h3 class="text-sm font-semibold text-slate-800 dark:text-slate-100 group-hover:text-brand dark:group-hover:text-brand-dark transition-colors leading-snug">
{service.name}
</h3>
<span class="flex-shrink-0 text-xs font-medium px-2 py-0.5 rounded-full bg-slate-100 dark:bg-slate-800 text-slate-500 dark:text-slate-400">
{ruleCount} rule{ruleCount !== 1 ? 's' : ''}
</span>
</div>
{exporterNames.length > 0 && (
<p class="text-xs text-slate-400 dark:text-slate-500 truncate">
{exporterNames.join(' · ')}{service.exporters.length > 3 ? ` +${service.exporters.length - 3}` : ''}
</p>
)}
</a>