# Nextjs Status Page: 90-Tage-Uptime-Balken und Störungen

> Bau eine nextjs status page aus deinen Monitoring-Daten: ehrliche 90-Tage-Uptime-Balken, Störungen, Wartung, ISR per Webhook und Hosting, das online bleibt.

- Autor: [Serban Rusu](https://wingo-ui.com/blog/authors/serban), Founder of Wingo UI
- Veröffentlicht: 16. Okt. 2026
- Kategorie: [Praxis: Screens und Apps](https://wingo-ui.com/de/blog/category/build)
- Lesezeit: 12 Min.
- Kanonische URL: https://wingo-ui.com/de/blog/nextjs-status-page
- Englische Fassung: https://wingo-ui.com/blog/nextjs-status-page

## Kurz gesagt

Eine Next.js-Statusseite ist eine serverseitig gerenderte Route, die deine Monitoring-Checks zu einem Uptime-Wert pro Komponente und Tag zusammenfasst, die letzten 90 Tage als farbige Balken zeigt und offene Störungen, geplante Wartungen und vergangene Störungen auflistet. Render sie statisch, lass sie jede Minute und auf Abruf über den Webhook deines Monitors neu validieren und hoste sie getrennt von der App, über die sie berichtet. Die Vorlage Status Page von Wingo UI nimmt diese Daten als Props entgegen und kümmert sich um die Balken, die Störungs-Timeline, den Wartungs-Countdown und das Layout auf dem Smartphone.

Eine Statusseite klingt nach einem Wochenendprojekt, bis du aufschreibst, was sie alles leisten muss: jeden Dienst in einem Banner zusammenfassen, 90 Tage Uptime-Balken pro Komponente zeichnen, Updates zu Störungen in der richtigen Reihenfolge zeigen, bis zur Wartung herunterzählen, einen Verlauf führen und online bleiben, während deine App down ist. Dieses Tutorial baut eine nextjs status page im App Router, gespeist aus deinen eigenen Monitoring-Daten statt von einem gehosteten Anbieter. Die Oberfläche ist unsere [Vorlage Status Page](https://wingo-ui.com/templates/status-page), wir sind also nicht neutral. Das Datenmodell, die Uptime-Rechnung und das Caching funktionieren aber genauso, wenn du eine Statusseite erstellen willst und deine React Status Page komplett selbst baust.

## Was gehört auf eine öffentliche Statusseite?

Eine öffentliche Statusseite braucht sechs Teile, und die großen gehosteten Produkte haben Besucher darauf trainiert, nach allen zu suchen:

- **Ein Gesamt-Banner.** „All systems operational“ in Grün, Gelb für eingeschränkt oder teilweise gestört, Rot für einen schweren Ausfall, Blau für Wartung. Die schlechteste Komponente entscheidet.
- **Komponenten mit Uptime-Balken.** Eine Zeile für alles, was deine Kunden nutzen (API, Web-App, Webhooks), jede mit einem Balken aus Tagesblöcken. [Atlassian Statuspage zeigt in seiner Uptime-Ansicht](https://support.atlassian.com/statuspage/docs/display-historical-uptime-of-components) (Stand Oktober 2026) die letzten 90 Tage, färbt jeden Tag von Grün über Gelb und Orange bis Rot, je näher die Ausfallzeit an 60 Minuten kommt, und zeigt Tage ohne Daten grau. [OpenStatus](https://www.openstatus.dev/changelog/status-page-history-days-selector) geht kürzer: Seit dem 24. Juni 2026 wählt jede Seite 30 oder 45 Tage.
- **Offene Störungen mit ihren Updates.** Investigating, identified, monitoring, resolved, das neueste oben, jedes mit Uhrzeit.
- **Geplante Wartung.** Was, wann und welche Komponenten.
- **Eine Seite mit dem Störungsverlauf.** Vergangene Störungen nach Tag gruppiert, damit die Frage „Lag es letzten Dienstag an euch oder an uns?“ eine Antwort hat.
- **Eine Möglichkeit zum Abonnieren.** E-Mail, RSS, Webhooks, ein Kalender für Wartungen.

Die meisten Treffer für „status page template“, die wir gefunden haben, sind entweder komplette selbst gehostete Produkte (eine Datenbank, ein Admin-Bereich, ein Monitor) oder ein statisches Mockup mit fest eingetragenen Balken. Der schwierige Teil liegt dazwischen: rohe Checks in ehrliche Tageswerte verwandeln und sie auf eine Seite bringen, die schnell und aktuell bleibt. Darum geht es hier hauptsächlich.

## Wie installierst du die Vorlage für die Statusseite?

Ein CLI-Befehl kopiert die Vorlage und alles, was sie importiert. Die Vorlage gehört zu Pro, das Konto hinter der CLI braucht also Wingo UI Pro.

```bash
npx wingo-ui@latest add status-page
```

Die CLI kopiert `components/templates/status-page.tsx` und `status-page-data.ts` in dein Projekt, dazu alles, was die beiden nutzen: den [Tracker](https://wingo-ui.com/components/tracker) für die Uptime-Balken, die [Timeline](https://wingo-ui.com/components/timeline) für Updates zu Störungen, den [Countdown](https://wingo-ui.com/components/countdown) für Wartungen und das [Popover](https://wingo-ui.com/components/popover) für das Formular zum Abonnieren. Ohne Daten-Props rendert die Vorlage einen von drei Beispieldatensätzen, den du mit `simulate` auswählst (`operational`, `degraded` oder `outage`). Praktisch für einen ersten Blick.

> Live-Demo (Status Page): Stell simulate auf degraded oder outage und sieh zu, wie sich das Banner, die betroffenen Zeilen und die heutigen Blöcke ändern; fahr mit der Maus über einen Block oder tipp ihn an, um Uptime und Notiz des Tages zu sehen. Probier sie unter [Status Page](https://wingo-ui.com/templates/status-page) aus und installier sie mit `npx wingo-ui@latest add status-page`.

## Welche Daten braucht eine Next.js-Statusseite?

Sie braucht vier Daten-Props, alle in `status-page-data.ts` typisiert. Texte und Links kommen getrennt über `labels` und `hrefs`.

| Prop | Typ | Inhalt |
|---|---|---|
| `groups` | `StatusComponentGroup[]` | `{ id, name, components }`; jede Komponente hat `id`, `name`, `description`, `state` und eine tägliche `history`, die älteste zuerst |
| `incidents` | `StatusIncident[]` | `{ id, title, impact, components, updates }`, die Updates neueste zuerst |
| `maintenance` | `StatusMaintenance[]` | `{ id, title, description, startsAt, endsAt, components }` |
| `updatedAt` | `string` | ISO-Zeit der letzten Aktualisierung, im Banner angezeigt |

Ein Tag im Verlauf einer Komponente ist ein `StatusDay`: `{ date, status, uptime, note? }`. Dabei ist `status` einer der Werte `ok`, `degraded`, `down`, `maintenance` oder `none`, und `uptime` ist ein Prozentwert von 0 bis 100. Eine Störung bleibt offen, bis ihr neuestes Update die Phase `resolved` hat. Ein Wartungsfenster verschwindet, sobald `endsAt` vorbei ist.

Ein Detail erwischt dich gleich am ersten Tag: Lässt du `groups`, `incidents` oder `maintenance` weg, greift die Vorlage für dieses Prop auf ihre Beispieldaten zurück. Übergib also immer ein Array, auch ein leeres. Ein `updatedAt`, das sich nicht als Datum parsen lässt, fällt ebenfalls auf das Datum der Beispieldaten zurück.

## Wie werden aus Monitoring-Checks tägliche Uptime-Balken?

Dein Monitor (ein gehosteter Pinger, ein Cronjob, ein Health Check in deinem eigenen Worker) liefert Check-Ergebnisse. Die Statusseite will eine Zeile pro Komponente und Tag. Fass das einmal zusammen, in einem geplanten Job oder einer SQL-View, und speichere die Minuten:

```ts
// lib/status/rollup.ts
import type { StatusDay } from "@/components/templates/status-page-data"

// eine Zeile pro Komponente und UTC-Tag, geschrieben von deinem Rollup-Job
export type DayMinutes = {
  date: string // "2026-10-15"
  checked: number // Minuten mit einem Check-Ergebnis
  down: number
  degraded: number
  maintenance: number
  note?: string
}

export function toStatusDay(day: DayMinutes): StatusDay {
  if (day.checked === 0) return { date: day.date, status: "none", uptime: 100 }
  // geplante Wartung zählt nicht gegen die Uptime
  const measured = Math.max(1, day.checked - day.maintenance)
  const uptime = Math.floor(((measured - day.down) / measured) * 10_000) / 100
  const status =
    day.down > 0 ? "down" : day.degraded > 0 ? "degraded" : day.maintenance > 0 ? "maintenance" : "ok"
  return { date: day.date, status, uptime, note: day.note }
}

// die letzten 90 UTC-Tage, der älteste zuerst, Lücken als "keine Daten" gefüllt
export function lastDays(rows: DayMinutes[], today: string, count = 90): StatusDay[] {
  const byDate = new Map(rows.map((row) => [row.date, row]))
  return Array.from({ length: count }, (_, index): StatusDay => {
    const day = new Date(`${today}T00:00:00Z`)
    day.setUTCDate(day.getUTCDate() - (count - 1 - index))
    const date = day.toISOString().slice(0, 10)
    const row = byDate.get(date)
    return row ? toStatusDay(row) : { date, status: "none", uptime: 100 }
  })
}
```

Dahinter steckt eine Festlegung, und die solltest du bewusst treffen. Unsere: Ausfallminuten zählen voll, Minuten mit eingeschränkter Leistung färben den Block gelb, senken den Prozentwert aber nicht, und Wartung wird herausgerechnet. Atlassian entscheidet anders: Laut seiner Doku (geprüft im Oktober 2026) zählen Teilausfälle mit 30 % eines schweren Ausfalls, eingeschränkte Leistung und Wartung zählen gar nicht. Wenn du das willst, ergänz `DayMinutes` um eine Spalte `partial` mit Minuten und berechne die Uptime aus `measured - down - partial * 0.3`. Egal, wofür du dich entscheidest: Veröffentliche die Regel neben den Balken (das Label `componentsDescription` ist ein guter Ort), damit Kunden deine Rechnung nachprüfen können.

Zwei weitere Regeln halten die Balken ehrlich. Fass die Tage in UTC zusammen, denn die Vorlage rendert jede Zeit in ihrem Prop `timeZone`, und das steht standardmäßig auf UTC, damit Server und Browser dasselbe ausgeben. Und beachte, dass ein Tag mit `none` den Wert `uptime: 100` trägt: Der Durchschnitt einer Zeile zählt jeden Tag, den sie bekommt. Eine Komponente, die du letzte Woche angelegt hast, würde also einen perfekten 90-Tage-Wert zeigen. Kürz jeden Verlauf auf den Tag, an dem die Komponente live ging, so wie die Route unten mit `createdAt`. Atlassian löst dasselbe Problem mit einem Startdatum pro Komponente, das standardmäßig der Tag ist, an dem die Komponente angelegt wurde.

## Wie baust du die Status-Route im App Router?

Teil sie auf: eine Server Component, die die Daten lädt und umformt, und einen kleinen Client-Wrapper für alles, was die Servergrenze nicht überqueren kann. Die Vorlage ist eine Client Component, und `linkComponent` und `onSubscribe` sind Funktionen, gehören also in den Wrapper. Die Daten gehen als reines JSON hinüber.

```tsx
// app/status/status-view.tsx
"use client"

import Link from "next/link"
import { StatusPage, type StatusPageProps } from "@/components/templates/status-page"
import { subscribeToStatus } from "./actions" // eine Server Action: E-Mail speichern, Bestätigung senden

type StatusViewProps = Pick<StatusPageProps, "groups" | "incidents" | "maintenance" | "updatedAt">

export function StatusView(props: StatusViewProps) {
  return (
    <StatusPage
      {...props}
      linkComponent={Link}
      onSubscribe={subscribeToStatus}
      // in den Standardwerten steht Acme; jeder sichtbare Text steckt in labels
      labels={{ brand: "Northwind", visitSite: "Zu northwind.dev" }}
      hrefs={{ site: "https://northwind.dev" }}
    />
  )
}
```

```tsx
// app/status/page.tsx
import type { StatusComponentGroup } from "@/components/templates/status-page-data"
import { lastDays } from "@/lib/status/rollup"
import { getComponents, getDailyMinutes, getIncidents, getMaintenance } from "@/server/status" // deine Datenschicht
import { StatusView } from "./status-view"

export const revalidate = 60

export default async function StatusRoute() {
  const now = new Date()
  const today = now.toISOString().slice(0, 10)
  const [components, minutes, incidents, maintenance] = await Promise.all([
    getComponents(),
    getDailyMinutes({ days: 90 }),
    getIncidents({ days: 30 }),
    getMaintenance(),
  ])

  const groups: StatusComponentGroup[] = ["Core", "Integrations"].map((name) => ({
    id: name.toLowerCase(),
    name,
    components: components
      .filter((component) => component.group === name)
      .map((component) => ({
        id: component.id,
        name: component.name,
        description: component.description,
        state: component.state, // operational | degraded | partial | major | maintenance
        // keine Blöcke vor dem Start der Komponente, sonst beginnt ihr Durchschnitt mit falschen 100 %
        history: lastDays(minutes.filter((row) => row.componentId === component.id), today).filter(
          (day) => day.date >= component.createdAt, // "2026-09-01"
        ),
      })),
  }))

  return (
    <StatusView
      groups={groups}
      incidents={incidents}
      // beendete Fenster stünden im gecachten HTML sonst noch als "geplant" da
      maintenance={maintenance.filter((item) => Date.parse(item.endsAt) > now.getTime())}
      updatedAt={now.toISOString()}
    />
  )
}
```

`export const revalidate = 60` hält die Seite statisch und erzeugt sie höchstens einmal pro Minute neu. Das zählt genau in dem Moment, auf den es ankommt: Während eines Ausfalls hat deine Statusseite den meisten Traffic, und eine statische Seite aus dem Cache belastet die ohnehin angeschlagene Datenbank nicht zusätzlich. Der [ISR-Guide von Next.js](https://nextjs.org/docs/app/guides/incremental-static-regeneration) sagt außerdem, dass bei einem Fehler in der Revalidierung weiter die zuletzt erfolgreich erzeugten Daten ausgeliefert werden. Eine fehlschlagende Abfrage zeigt also leicht veraltete Daten statt einer Fehlerseite.

Wenn dein Projekt `cacheComponents` einschaltet, wird ein `revalidate`-Export zum Build-Fehler. Verschieb dann das ganze Laden in eine async-Funktion, die mit `"use cache"` beginnt und `cacheLife("minutes")` aufruft (dieses Profil revalidiert nach einer Minute), und berechne auch `today` und `updatedAt` darin: Cache Components lässt das Prerendering bei einem nackten `new Date()` außerhalb eines gecachten Bereichs scheitern.

Zwei Dinge solltest du vor dem Launch prüfen:

- **`onSubscribe` ist angeschlossen.** Ohne das Prop wartet das Formular 900 ms und meldet Erfolg. Für eine Demo ist das richtig, für Kunden falsch. Gibt `onSubscribe` ein Promise zurück, dreht sich der Button, bis es erfüllt ist. Wird es abgelehnt, erscheint der Fehler.
- **Die Standardlinks existieren.** `hrefs` zeigt auf `/status/history`, `/status/feed.rss`, `/status/maintenance.ics` und `/docs/webhooks`. Bau diese Routen oder überschreib die Links.

### Wie aktualisierst du die Seite, sobald sich eine Störung ändert?

Eine Minute reicht für die Balken. Für „Investigating“ bei einem frischen Ausfall ist sie zu langsam. Richte den Webhook deines Monitors oder Incident-Tools auf einen Route Handler, der die Seite neu validiert:

```ts
// app/api/status/revalidate/route.ts
import { revalidatePath } from "next/cache"

export async function POST(request: Request) {
  if (request.headers.get("authorization") !== `Bearer ${process.env.STATUS_WEBHOOK_SECRET}`) {
    return new Response("Unauthorized", { status: 401 })
  }
  revalidatePath("/status")
  return Response.json({ revalidated: true })
}
```

Aus einem Route Handler aufgerufen, markiert `revalidatePath` die Seite als veraltet, und der nächste Besuch rendert sie frisch. Validier `/status/history` genauso neu, wenn du eine Störung abschließt.

## Wie spielen Störungen, Wartung und Banner zusammen?

Das Banner setzt du nie von Hand. `overall` steht standardmäßig auf `"auto"` und ruft das exportierte `deriveOverall(groups)` auf: Der schlechteste Zustand einer Komponente gewinnt, in der Reihenfolge major, partial, degraded, maintenance, operational. Halte den `state` jeder Komponente aktuell, und das Banner folgt. Setz `overall` nur für den seltenen Fall explizit, den deine Daten nicht abbilden können, etwa ein geplantes Fenster für die ganze Plattform.

Eine offene Störung erscheint im Banner, ihre Updates als Timeline, das neueste oben. Speichere Updates als Zeilen mit `stage`, `message` und einer Zeit `at`, und leg ein neues an, sobald sich etwas ändert. `isIncidentOpen(incident)` liefert `true`, bis das neueste Update `resolved` sagt. Jede Störung führt die IDs der betroffenen Komponenten auf, so kann die Seite sie beim Namen nennen.

Wartungsfenster zählen bis `startsAt` herunter, während der Wartung dann bis `endsAt`, und verschwinden danach. Der Server rendert jedes Fenster als bevorstehend, und die Uhr wird erst nach der Hydration gelesen, danach alle 30 Sekunden. Eine statische Seite verursacht so nie einen Hydration Mismatch. Die Kehrseite: Ein Fenster, das nach der letzten Regenerierung zu Ende ging, steht im gecachten HTML noch als „Scheduled maintenance“, bis die Seite hydriert. Deshalb filtert die Route beendete Fenster heraus, bevor sie sie übergibt, und deshalb lohnt sich ein `revalidatePath`, wenn ein Fenster schließt.

Unter den Komponenten listet der Störungsverlauf die letzten `historyDays` Tage auf (standardmäßig 7), mit „No incidents reported“ an ruhigen Tagen. Das beantwortet die häufigste Frage. Verlinke `hrefs.history` auf eine vollständige Seite mit dem Störungsverlauf, die dieselbe Vorlage mit `historyDays={30}` rendert (und mit einem Label `historyDescription`, das „die letzten 30 Tage“ sagt), oder auf eine schlichte Liste aller Störungen nach Monat.

## Wie verhalten sich Uptime-Balken auf Smartphones und mit der Tastatur?

Hier fällt eine Statusseite aus lauter `div`s meistens auseinander. Neunzig Blöcke auf einem 390px breiten Bildschirm sind nach Abzug der Lücken jeweils schmaler als 3px: unmöglich anzutippen und schwer zu lesen. Die Vorlage rendert zwei Tracker pro Komponente und lässt CSS entscheiden: 90 Tage ab 768px, darunter die letzten 30, jeder mit eigenem Durchschnitt. Der Wechsel ist eine Media Query (`md:hidden` und `max-md:hidden`). Das Server-HTML stimmt also schon, und nach der Hydration springt nichts. Ein Check mit `useIsMobile` kann das nicht versprechen (warum, erklären wir in [unserem Artikel über den React Hook use mobile](https://wingo-ui.com/de/blog/react-use-mobile-hook-ssr)).

Bei Touch ist der ganze Balken die Zielfläche. Ein Tipp heftet eine Anzeige mit Datum, Uptime und Notiz an. Ziehst du seitwärts, wanderst du durch die Tage, während vertikales Ziehen weiter die Seite scrollt. Ein zweiter Tipp auf denselben Block löst `onBlockClick` aus, ein Tipp daneben blendet die Anzeige aus. Mit der Tastatur landet Tab auf dem neuesten Block, die Pfeiltasten gehen durch die Tage, Pos1 und Ende springen an die Enden, Bild auf und Bild ab bewegen sich um zehn, Enter oder Leertaste lösen `onBlockClick` aus, und eine Live-Region (`polite`) liest jeden Tag vor. Screenreader bekommen außerdem eine Zusammenfassung der Anzahl pro Status und eine Tabelle aller Blöcke.

Den [Tracker](https://wingo-ui.com/components/tracker) kannst du auch allein nutzen, und dort landen die meisten Suchen nach „uptime bars react“: eine Karte im internen Dashboard, eine Zeile für den Sync-Zustand, die letzten 30 Läufe einer Integration. Allein geht er anders mit schmalen Bildschirmen um: `fit="latest"` (der Standard) behält nur die neuesten Blöcke, die bei `minBlockWidth` (4px) passen, und verschiebt die Beschriftung am Anfang entsprechend. Die Vorlage zeigt stattdessen immer genau 90 und 30 Tage, damit der Durchschnitt über dem Balken immer einen bekannten Zeitraum abdeckt.

```tsx
// components/api-uptime.tsx
"use client"

import { useRouter } from "next/navigation"
import { Tracker, type TrackerDatum } from "@/components/ui/tracker"

export function ApiUptime({ days, average }: { days: TrackerDatum[]; average: string }) {
  const router = useRouter()
  return (
    <Tracker
      data={days}
      label="API"
      summary={average}
      locale="en-US"
      statuses={{
        // ein eigener Schlüssel neben den Standardwerten
        partial: { label: "Teilausfall", tone: "warning" },
        down: { label: "Schwerer Ausfall", tone: "danger" },
      }}
      onBlockClick={(day) => {
        if (day.date) router.push(`/status/history?date=${day.date}`)
      }}
    />
  )
}
```

Jeder Datenpunkt ist `{ status, id?, date?, label?, description? }`, und `statuses` wird über die Standardwerte gelegt (`ok`, `degraded`, `down`, `maintenance`, `none`). Ein selbst erfundener Schlüssel wie `partial` bekommt so sein eigenes Label und seinen eigenen `tone`. Ein Status ohne Eintrag wird als `none` gezeichnet und loggt in der Entwicklung eine Warnung.

> Live-Demo (Tracker): Fahr mit der Maus über einen Block oder tipp auf dem Smartphone einen an und zieh ihn seitwärts durch die Tage; mit der Tastatur springst du per Tab auf den Balken und gehst mit den Pfeiltasten weiter. Probier sie unter [Tracker](https://wingo-ui.com/components/tracker) aus und installier sie mit `npx wingo-ui@latest add tracker`.

## Wo solltest du eine Statusseite hosten?

Hoste sie auf einem anderen Deployment, bei einem anderen Anbieter und unter einer anderen Domain als die App, über die sie berichtet. Am 8. April 2021 lief die Statusseite von Facebook offenbar auf derselben Infrastruktur wie die Dienste, die ausfielen. [Statuspal empfiehlt in seiner Analyse dieses Ausfalls](https://statuspal.io/blog/2021-04-09-learning-from-facebook-keep-your-status-page-separately-from-your-infrastructure) für alles Selbstgehostete eine eigene Infrastruktur, ein eigenes Rechenzentrum, einen eigenen Hosting-Anbieter und eine eigene Domain. Statuspal verkauft Statusseiten, gewichte den Rat also entsprechend. Die Logik trägt aber auch für sich allein.

Für eine Next.js-Statusseite heißt das dreierlei:

- **Ein eigenes Deployment.** Ein eigenes Projekt, keine Route in deiner Haupt-App. Ein fehlerhaftes Deployment oder ein abgestürzter App-Server sollte sie nicht mitreißen.
- **Daten, die nicht von der Datenbank der App abhängen.** Lass den Monitor die Rollups und Störungen in einen kleinen Speicher schreiben, den das Status-Projekt liest, oder schick sie ihm direkt. Kann die Seite nur rendern, indem sie die Datenbank abfragt, die gerade ausgefallen ist, steht nur noch dein Cache zwischen dir und einer leeren Seite.
- **Monitoring von außen.** Checks, die in dem System laufen, das sie prüfen, verstummen mit ihm.

Wenn du den Status auch in deiner App zeigen willst (ein Banner im Dashboard während einer Störung), lies dieselben Daten aus dem JSON des Status-Projekts, statt eine zweite Quelle der Wahrheit zu pflegen. Für die App-Seite baut unser [Tutorial zum Next.js Admin Dashboard](https://wingo-ui.com/de/blog/nextjs-admin-dashboard-tutorial) die Shell, Tabellen und Einstellungen drumherum, und weitere Screens wie diesen findest du in [der Kategorie Build it](https://wingo-ui.com/de/blog/category/build).

## Was ist der nächste Schritt?

Installier die Vorlage, render sie mit Beispieldaten und tausch dann deine Rollups Prop für Prop ein: zuerst `groups`, dann `incidents`, dann `maintenance`.

```bash
npx wingo-ui@latest add status-page
```

Die Vorlage Status Page und der Tracker gehören zu Wingo UI Pro; mehr dazu unter [Pläne und Preise von Wingo UI Pro](https://wingo-ui.com/de/pricing). Wenn du mit Claude Code oder Cursor baust, lässt der [MCP-Server von Wingo UI](https://wingo-ui.com/docs/mcp) deinen Agenten die Props und das Nutzungsbeispiel der Vorlage direkt lesen. Das hilft, wenn er die Zuordnung aus deinem Monitoring-Schema schreibt.

## Komponenten in diesem Artikel

- [Status Page](https://wingo-ui.com/templates/status-page) (Pro): React status page template: an overall banner, components with 90-day uptime bars, live incidents, scheduled maintenance and history. Installation: `npx wingo-ui@latest add status-page`
- [Tracker](https://wingo-ui.com/components/tracker) (Pro): A React status tracker: a row of status blocks over time, one per day, hour or deploy, for uptime pages, sync health and habit streaks. Installation: `npx wingo-ui@latest add tracker`

## Häufige Fragen

### Wie baue ich eine Statusseite in Next.js?

Leg eine Route app/status an, deren Server Component deine Komponenten, ihre tägliche Uptime und deine Störungen lädt und dann rendert. Exportiere revalidate = 60, damit die Seite statisch bleibt und sich trotzdem jede Minute erneuert, und ruf revalidatePath('/status') aus einem Webhook auf, sobald sich eine Störung ändert.

### Wie wird der Uptime-Prozentsatz auf einer Statusseite berechnet?

Meist als Minuten, in denen eine Komponente erreichbar war, geteilt durch die gemessenen Minuten, pro Tag und dann über den Zeitraum gemittelt. Atlassian Statuspage zählt Stand Oktober 2026 Teilausfälle mit 30 % eines schweren Ausfalls und lässt eingeschränkte Leistung und Wartung außen vor. Leg deine eigene Regel fest und schreib sie auf.

### Sollte eine Statusseite auf demselben Server wie meine App laufen?

Nein. Eine Statusseite, die sich Server, DNS oder ein Deployment mit deiner App teilt, kann im selben Ausfall offline gehen, über den sie berichten soll. Deploye sie als eigenes Projekt und schick ihr die Daten von einem Monitor, der woanders läuft.

### Wie viele Tage Uptime-Verlauf sollte eine Statusseite zeigen?

Atlassian Statuspage zeigt 90 Tage; bei OpenStatus wählt laut Changelog vom 24. Juni 2026 jede Seite 30 oder 45 Tage (45 als Standard). Die Status Page von Wingo UI zeigt am Desktop 90 Tage und auf Smartphones die letzten 30, weil 90 Blöcke dort zu schmal zum Antippen wären.

### Ist die Vorlage Status Page von Wingo UI kostenlos?

Nein, die Vorlage Status Page und der Tracker, den sie nutzt, gehören zu Wingo UI Pro. Du installierst sie mit npx wingo-ui@latest add status-page, sobald dein Konto Pro hat.

---

Quelle: https://wingo-ui.com/de/blog/nextjs-status-page
