Status Page
Create public status pages for service availability communication
The Status Page resource creates public-facing status pages to communicate service health to customers.
Example Usage
Basic Status Page
import * as betteruptime from "@pulumi-contrib/better-uptime";
const statusPage = new betteruptime.StatusPage("service-status", {
companyName: "Example Inc",
companyUrl: "https://www.example.com",
subdomain: "status-example",
timezone: "America/New_York",
});
export const statusPageUrl = statusPage.url;Status Page with Custom Design
const brandedStatusPage = new betteruptime.StatusPage("branded-status", {
companyName: "Acme Corporation",
companyUrl: "https://acme.com",
subdomain: "status-acme",
timezone: "UTC",
design: "v2",
layout: "horizontal",
theme: "dark",
customCss: `
.header { background: #0066cc; }
.status-badge { border-radius: 4px; }
`,
});Status Page with Logo
const statusWithLogo = new betteruptime.StatusPage("company-status", {
companyName: "Tech Startup",
companyUrl: "https://techstartup.com",
subdomain: "status",
timezone: "America/Los_Angeles",
logoUrl: "https://techstartup.com/logo.png",
faviconUrl: "https://techstartup.com/favicon.ico",
});Multi-Language Status Page
const multiLangStatus = new betteruptime.StatusPage("global-status", {
companyName: "Global Services",
companyUrl: "https://global.example.com",
subdomain: "status-global",
timezone: "UTC",
subscribeBySms: true,
smsNotificationsEnabled: true,
supportedLanguages: ["en", "es", "fr", "de"],
automaticTranslation: true,
});Status Page with Announcement
const statusWithAnnouncement = new betteruptime.StatusPage("api-status", {
companyName: "API Platform",
companyUrl: "https://api.example.com",
subdomain: "apistatus",
timezone: "America/New_York",
announcement: "Scheduled maintenance on Saturday 2AM-4AM EST",
announcementType: "maintenance",
});Private Status Page
const privateStatus = new betteruptime.StatusPage("internal-status", {
companyName: "Internal Services",
companyUrl: "https://internal.example.com",
subdomain: "status-internal",
timezone: "UTC",
passwordEnabled: true,
password: "secure-password-123",
});Argument Reference
Required Arguments
companyName(String) - Company name displayed on status pagecompanyUrl(String) - Company website URLsubdomain(String) - Subdomain for status page (status-example.betteruptime.com)timezone(String) - Timezone for incident times
Optional Arguments
Branding
logoUrl(String) - URL to company logofaviconUrl(String) - URL to faviconcustomCss(String) - Custom CSS for stylingtheme(String) - Theme: "light" or "dark". Default: "light"layout(String) - Layout: "vertical" or "horizontal". Default: "vertical"design(String) - Design version: "v1" or "v2". Default: "v2"
Features
subscribeBySms(Boolean) - Enable SMS subscriptions. Default: falsesmsNotificationsEnabled(Boolean) - Enable SMS notifications. Default: falsehideFromSearchEngines(Boolean) - Hide from search engines. Default: falsepasswordEnabled(Boolean) - Enable password protection. Default: falsepassword(String) - Password for private status pageminIncidentLength(Number) - Minimum incident duration to display (seconds)announcementEmbedEnabled(Boolean) - Enable announcement embed. Default: falseannouncement(String) - Announcement textannouncementType(String) - Announcement type: "info", "maintenance", "warning"
Localization
supportedLanguages(List) - Supported language codes (e.g., ["en", "es", "fr"])automaticTranslation(Boolean) - Enable automatic translation. Default: false
Attribute Reference
id(String) - The status page IDurl(String) - Public status page URLcreatedAt(String) - Creation timestampupdatedAt(String) - Last update timestamp
Adding Monitors to Status Page
Status Page Resources
import * as betteruptime from "@pulumi-contrib/better-uptime";
const statusPage = new betteruptime.StatusPage("services", {
companyName: "Example Inc",
subdomain: "status",
timezone: "UTC",
});
const apiMonitor = new betteruptime.Monitor("api", {
url: "https://api.example.com",
monitorType: "status",
});
const webMonitor = new betteruptime.Monitor("website", {
url: "https://www.example.com",
monitorType: "status",
});
// Add monitors to status page
const apiResource = new betteruptime.StatusPageResource("api-resource", {
statusPageId: statusPage.id,
monitorId: apiMonitor.id,
publicName: "API",
position: 1,
});
const webResource = new betteruptime.StatusPageResource("web-resource", {
statusPageId: statusPage.id,
monitorId: webMonitor.id,
publicName: "Website",
position: 2,
});Status Page Sections
// Create sections for organization
const section = new betteruptime.StatusPageSection("core-services", {
statusPageId: statusPage.id,
name: "Core Services",
position: 1,
});
const sectionResource = new betteruptime.StatusPageResource("api-in-section", {
statusPageId: statusPage.id,
statusPageSectionId: section.id,
monitorId: apiMonitor.id,
publicName: "API Service",
position: 1,
});Best Practices
Subdomain Naming
// ✅ Good subdomain names
"status" // Simple and clear
"status-api" // Service-specific
"status-platform" // Platform-specific
// ❌ Avoid
"my-cool-status" // Too casual
"status123" // Meaningless numbers
"asdfstatus" // UnprofessionalTheme Selection
// Match your brand
const lightTheme = new betteruptime.StatusPage("light", {
companyName: "Bright Corp",
subdomain: "status-bright",
timezone: "UTC",
theme: "light",
customCss: ".header { background: #ffffff; }",
});
const darkTheme = new betteruptime.StatusPage("dark", {
companyName: "Dark Corp",
subdomain: "status-dark",
timezone: "UTC",
theme: "dark",
customCss: ".header { background: #1a1a1a; }",
});Privacy Settings
// Public status page
const publicStatus = new betteruptime.StatusPage("public", {
companyName: "Public Services",
subdomain: "status",
timezone: "UTC",
hideFromSearchEngines: false,
});
// Private internal status page
const privateStatus = new betteruptime.StatusPage("private", {
companyName: "Internal Services",
subdomain: "status-internal",
timezone: "UTC",
passwordEnabled: true,
password: process.env.STATUS_PAGE_PASSWORD,
hideFromSearchEngines: true,
});Announcement Management
// Planned maintenance announcement
const maintenanceStatus = new betteruptime.StatusPage("maintenance", {
companyName: "Services",
subdomain: "status",
timezone: "America/New_York",
announcement: "Scheduled maintenance: Saturday 2-4 AM EST",
announcementType: "maintenance",
});
// General information
const infoStatus = new betteruptime.StatusPage("info", {
companyName: "Services",
subdomain: "status",
timezone: "UTC",
announcement: "New features coming soon!",
announcementType: "info",
});Common Patterns
Complete Status Page Setup
import * as betteruptime from "@pulumi-contrib/better-uptime";
// Create status page
const statusPage = new betteruptime.StatusPage("company-status", {
companyName: "Acme Corp",
companyUrl: "https://acme.com",
subdomain: "status",
timezone: "America/New_York",
logoUrl: "https://acme.com/logo.png",
subscribeBySms: true,
smsNotificationsEnabled: true,
});
// Create sections
const coreSection = new betteruptime.StatusPageSection("core", {
statusPageId: statusPage.id,
name: "Core Services",
position: 1,
});
const apiSection = new betteruptime.StatusPageSection("apis", {
statusPageId: statusPage.id,
name: "APIs",
position: 2,
});
// Add monitors
const webMonitor = new betteruptime.Monitor("web", {
url: "https://www.acme.com",
monitorType: "status",
});
const apiMonitor = new betteruptime.Monitor("api", {
url: "https://api.acme.com",
monitorType: "status",
});
// Add to status page
const webResource = new betteruptime.StatusPageResource("web-resource", {
statusPageId: statusPage.id,
statusPageSectionId: coreSection.id,
monitorId: webMonitor.id,
publicName: "Website",
position: 1,
});
const apiResource = new betteruptime.StatusPageResource("api-resource", {
statusPageId: statusPage.id,
statusPageSectionId: apiSection.id,
monitorId: apiMonitor.id,
publicName: "REST API",
position: 1,
});
export const statusUrl = statusPage.url;Import
Status pages can be imported using their ID:
pulumi import better-uptime:index/statusPage:StatusPage example 123456Troubleshooting
Subdomain Already Taken
Error: "Subdomain is already in use"
Solution:
- Choose a different subdomain
- Add suffix like
-prodor-services - Use company/product name
Custom CSS Not Applied
Causes:
- Invalid CSS syntax
- Cache not cleared
- Design version incompatibility
Solution:
const statusPage = new betteruptime.StatusPage("fixed", {
companyName: "Company",
subdomain: "status",
timezone: "UTC",
design: "v2", // Ensure using v2
customCss: `
/* Valid CSS only */
.header {
background-color: #0066cc;
}
`,
});Password Protection Not Working
Cause: Password not enabled or incorrect
Solution:
const protectedStatus = new betteruptime.StatusPage("protected", {
companyName: "Private Services",
subdomain: "status-private",
timezone: "UTC",
passwordEnabled: true, // Must be true
password: "your-secure-password",
});