Docs/Use Probara
Public communication

Status pages

Publish branded, live public status pages with sections, incidents, maintenance, and versioned templates.

Status page model

VariablePurpose and validation
slugPublic URL identifier using lowercase letters, numbers, and hyphens
titleRequired public page title
descriptionOptional public summary
logo_urlOptional brand logo URL
primary_color / secondary_colorSix-digit colors in exact #RRGGBB form
monitor_idsMonitors exposed on the page when using the flat layout
display_namesPer-monitor public labels, each up to 80 characters
sectionsOrdered groups with titles up to 80 characters and ordered monitor entries

Each monitor can appear only once across a page's sections. A section entry can override its public display name and stores an explicit position so the presentation order is stable.

Presentation and disclosure settings

SettingCurrent built-in behavior
show_monitor_tagsPresent in the settings schema; not currently wired into the built-in template
show_monitor_urlPresent in the settings schema; not currently wired into the built-in template
show_monitor_uptimeControls per-monitor uptime in the built-in view
show_monitor_tlsPresent in the settings schema; not currently wired into the built-in template
show_latency_chartsPresent in the settings schema; not currently wired into the built-in template
show_agent_metricsPresent in the settings schema; not currently wired into the built-in template
show_global_uptimeControls the page-level uptime summary in the built-in view
show_footerControls the built-in footer region
footer_textBuilt-in custom footer text, up to 250 characters
default_themeInitial built-in theme: light or dark
allow_theme_toggleAllows the built-in visitor theme switch
enable_push_notificationsOffers visitors a browser-notification opt-in. Off by default, and inert unless the deployment also configures a VAPID keypair — see visitor notifications
custom_cssPage-scoped custom stylesheet, up to 128 KiB
custom_head_htmlTrusted custom head markup, up to 64 KiB. Injected after the built-in head, so a <link rel="icon"> here replaces the default monochrome favicon
custom_footer_htmlTrusted custom footer markup, up to 64 KiB

Settings are part of the page definition and can be supplied at creation or update. Several visibility fields are reserved in the schema but are not yet consumed by the active built-in renderer; storing them does not make those panels appear. Custom template authors must verify which data is present in the current template context.

Separately from these settings, the built-in template automatically shows a small "Certificate expires soon" note on a component whose monitor has an open `tls_expiry` alert — the certificate is inside its tls_min_days_valid window while the component itself remains operational, so the note never changes the component's status. Custom templates receive this as the boolean CertExpiresSoon field on each monitor entry.

Public routes and live updates

RouteResponse
GET /public/status/{slug}Rendered public status page
GET /public/status/{slug}/dataPublic JSON-shaped page data used by the renderer and clients
GET /public/status/{slug}/streamServer-sent event stream for live refresh notifications
GET /public/status/{slug}/preview/draftDraft-template preview, protected by a preview token when configured
GET /public/status/sw.jsPush service worker. Served from the parent path, not under a slug, so its scope covers the page URL; see visitor notifications
POST /public/status/{slug}/push/subscribeStores a browser push subscription. Returns 404 unless the page enables notifications and the deployment has VAPID keys
POST /public/status/{slug}/push/unsubscribeRemoves a browser push subscription. Always 204, so it cannot be used to probe which endpoints exist

The status-page service caches rendered data and subscribes to statuspage.updates on core NATS. Monitor, incident, maintenance, or page changes invalidate relevant cache entries and notify connected SSE clients. The rendered page also performs a periodic fallback refresh, currently about every 60 seconds.

Visitor browser notifications

A visitor can opt into browser push notifications for a status page. They are told when a component the page shows goes down, and again when it comes back up — including when the tab and the browser are closed. This is real Web Push (a service worker plus a VAPID keypair), not a notification raised by the open page.

Two things must both be true for the control to appear: the page sets enable_push_notifications, and the deployment configures STATUS_PAGE_VAPID_PUBLIC_KEY and STATUS_PAGE_VAPID_PRIVATE_KEY. Either alone renders nothing, because either alone would produce a button that cannot work.

TransitionNotification
A component enters downSent
A component returns to up from downSent
degraded, in either directionNot sent — some but not enough locations are failing, so the component is still up for most visitors
suspectNot sent — mid-confirmation, by design not yet an outage
unknown, or a paused monitorNot sent
Any monitor inside an active maintenance windowNot sent

Intermediate states are skipped rather than reported, so up → suspect → down is one notification, down → suspect → down is none, and down → degraded → up is a single recovery. A transition that reverses within about a minute never notifies at all.

  • Notifications require a secure context. Localhost counts, so development works, but a plain-HTTP deployment shows no control at all.
  • On iPhone and iPad, Web Push only works for a page added to the Home Screen. The control says so rather than failing silently in an ordinary Safari tab.
  • Turning the setting off stops new notifications but keeps existing subscriptions, so re-enabling does not force everyone to opt in again.
  • Rotating the VAPID keypair invalidates every stored subscription — push services bind an endpoint to the key that created it — and every visitor must opt in again.
  • A page rendered by a custom template gets no control unless the author adds one; .PushEnabled and .PushPublicKey are available in the template context.
  • Subscriptions store only the opaque browser endpoint and its public keys. No visitor identity, email address, or visit history is recorded.

Delivery is driven by the recorded state timeline rather than by live events, so a notification is not lost when a message is dropped or a replica restarts. Transitions older than about fifteen minutes are discarded instead of delivered late: a notification saying a service is down, arriving after it recovered, is worse than none.

Monitor data on a public page

The active built-in view shows current state and the configured monitor/global uptime summaries. It supports ordered sections, active/recent incidents, and maintenance. Group and passive monitors present derived or reported state rather than an active network-check result.

Monitor state uses the same unknown, up, suspect, down, and degraded model as the authenticated application. Template authors should preserve distinct labels rather than mapping every non-up state to a single outage color.

Visitors can switch among list, compact, and kiosk presentation modes, select uptime ranges, search monitors, filter by status, and use keyboard/URL preferences supported by the shared template. Those visitor controls are distinct from saved page settings. Kiosk mode auto-fits tile density to the screen so every monitor stays visible without scrolling on wall displays — tiles progressively shed detail (metrics, then meta line and uptime strip) as the count grows, with the hidden detail available on hover; only past the smallest tier (roughly 500+ monitors on a 1080p display) does the grid fall back to scrolling.

Publish incidents

  1. Create or open an incident in the authenticated application.
  2. Attach the affected monitors and relevant alerts.
  3. Add public timeline updates while keeping internal notes private.
  4. Publish the incident to one or more status pages.
  5. Continue status transitions and public updates through investigation, identification, monitoring, and resolution.
  6. Unpublish from an individual page when it is no longer relevant there.

Publication is monitor-aware: only incident content associated with monitors selected on that status page is eligible for that page's public context. Merely attaching an incident to a page does not make unrelated internal monitors public.

Show maintenance

Public page data includes applicable ongoing and recent maintenance windows. A window is applicable when it directly covers a selected monitor or covers a selected group and its members.

Maintenance changes alert behavior but does not stop checks. A page can continue showing observed state while also explaining the scheduled work, which helps visitors distinguish planned degradation from an unannounced incident.

Template lifecycle

Every page has a built-in default template and at most one editable draft. Publishing is versioned and previous published source is archived.

ActionEffect
Load defaultReturns the built-in template source
Save draftValidates and stores one unpublished template without affecting visitors
Preview draftRenders draft source against current page data
PublishArchives the current published template, promotes the draft, and increments the version
Discard draftDeletes only the draft
RevertCopies an archived version into a new current published version; history remains append-only
ResetArchives the current published template and restores the built-in source as a new version

Template source must be non-empty, parse as Go html/template, and remain within 512 KiB. Published versions can be listed and their source retrieved for review or rollback.

Author templates safely

Templates use Go html/template, which contextually escapes ordinary data values. Use the structures exposed by the default template as the compatibility reference and preview with real page data before publication.

Template functionPurpose
expandedStripCellsBuild the expanded monitor strip cells expected by the current renderer
globalStripCellsBuild the global summary strip cells
joinJoin string values for display
monitorStripCellsBuild standard monitor strip cells
typeIconReturn the display icon for a monitor type

Protect draft previews

When STATUS_PAGE_PREVIEW_SECRET is configured, draft preview URLs require a signed preview token. Without that secret, the development preview path is open to anyone who can reach it.

Reusable template library

Tenants can save validated template source as a named library entry. Names are limited to 100 characters. List responses expose metadata; source is retrieved from the dedicated source route.

Applying a library template copies its source into the target page's draft workflow. It does not create a live link: later edits to the library entry do not silently change already published pages.

Publication checklist

  • Verify the slug, public title, monitor selection, display names, and section order.
  • Review built-in visibility settings and treat the URL, tag, agent-metric, TLS, and latency flags as schema-reserved until the renderer explicitly supports them.
  • Preview light and dark themes at desktop and mobile widths.
  • Exercise unknown, suspect, degraded, down, maintenance, and incident states in a safe preview environment.
  • Check custom HTML/CSS for content security, accessibility, focus states, contrast, and responsive overflow.
  • Configure the preview secret and confirm the public status service has a reachable API/data path.
  • Publish, open the anonymous route in a clean browser session, and verify SSE/fallback refresh behavior.