feat(landing): live server card backed by self-hosted mc-status

Add a featured live ServerCard to the landing (replaces the static
ServerListPanel in hero + status sections): server favicon, color MOTD,
online/offline pill, players online/max with fill bar, and a player-head
row rendered by our own NMSR from Drasl skins. Progressive enhancement —
SSG skeleton degrades gracefully when JS or the API is unavailable.

Back it with a self-hosted pinger instead of the public api.mcstatus.io:
mcstatus.io's API service is closed-source (only the mcutil library is
open), so docker/mc-status wraps mcutil and re-emits its v2 JSON shape,
keeping the frontend unchanged. The service ignores the path address and
only pings MC_STATUS_TARGET (no SSRF relay), with a 30s TTL cache.

Exposed same-origin via caddy at the apex /api/mcstatus/* path (no new DNS
subdomain or LE cert change, no CORS). Uptime Kuma stays the uptime
history + alerting backend; see plan/15-mc-status.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
oierandClaude Opus 4.8 committed 2026-06-09 22:08:30 +02:00
1 parent df8ffca53e
commit d21a7f0e92
11 files changed
+581 -7

No files matched your search

+3 -3
View File
@@ -4,7 +4,7 @@ import { ui, LANGS, LANG_LABEL, LANG_PATH, type Lang } from "../i18n/ui";
import Creeper from "../components/Creeper.astro";
import PixelIcon from "../components/PixelIcon.astro";
import CopyChip from "../components/CopyChip.astro";
import ServerListPanel from "../components/ServerListPanel.astro";
import ServerCard from "../components/ServerCard.astro";
import "../styles/main.css";
// One static page per locale: en at "/", es at "/es/", eu at "/eu/".
@@ -108,7 +108,7 @@ const dustBits = Array.from({ length: 16 }, (_, i) => {
</div>
</div>
<div class="hero-status">
<ServerListPanel
<ServerCard
modded={t.status.modded}
motd={t.status.motd}
upTo={t.status.upTo}
@@ -126,7 +126,7 @@ const dustBits = Array.from({ length: 16 }, (_, i) => {
<p class="lead">{t.status.lead}</p>
</div>
<div class="reveal">
<ServerListPanel
<ServerCard
modded={t.status.modded}
motd={t.status.motd}
upTo={t.status.upTo}