5039 lines
331 KiB
HTML
5039 lines
331 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en" id="home">
|
|
|
|
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
|
|
|
|
<head>
|
|
<title>
|
|
What are Error Budgets? A Guide to Managing Reliability
|
|
</title>
|
|
<meta name="description" content=" Error budgets are a fundamental concept in Site Reliability Engineering that help teams balance innovation with reliability.">
|
|
|
|
<!-- Critical meta tags MUST be first (within first 1024 bytes) -->
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, viewport-fit=cover" />
|
|
<meta name="theme-color" content="#000000" />
|
|
<meta name="theme-color" media="(prefers-color-scheme: light)" content="#000000" />
|
|
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="#1E293B" />
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
|
|
|
<!-- Resource hints - start fetching critical resources early -->
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<!-- Preconnect to external image/avatar domains to reduce layout shift & latency -->
|
|
<link rel="preconnect" href="https://avatars.githubusercontent.com" crossorigin>
|
|
<link rel="dns-prefetch" href="//avatars.githubusercontent.com">
|
|
<!-- DNS prefetch for deferred analytics -->
|
|
<link rel="dns-prefetch" href="//eu.posthog.com">
|
|
<!-- Preload Tailwind to reduce FOUC/CLS -->
|
|
<link rel="preload" href="/oneuptime-assets/tailwind/tailwind-3.4.5.js" as="script">
|
|
<link rel="preload" href="https://fonts.googleapis.com/css2?family=Geist:ital,wght@0,400..800;1,400..800&display=swap" as="style">
|
|
|
|
<!-- Google Fonts - Geist (Vercel's typeface), roman + italic, weights 400-800 -->
|
|
<link href="https://fonts.googleapis.com/css2?family=Geist:ital,wght@0,400..800;1,400..800&display=swap"
|
|
rel="stylesheet">
|
|
|
|
<!-- Font and form element styles -->
|
|
<style>
|
|
* {
|
|
font-family: Geist, Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
}
|
|
|
|
input[type="datetime-local"]::-webkit-calendar-picker-indicator {
|
|
background: transparent;
|
|
bottom: 0;
|
|
color: transparent;
|
|
cursor: pointer;
|
|
height: auto;
|
|
left: 0;
|
|
position: absolute;
|
|
right: 0;
|
|
top: 0;
|
|
width: auto;
|
|
appearance: none; /* standard */
|
|
-webkit-appearance: none; /* vendor */
|
|
}
|
|
|
|
input[type="date"]::-webkit-calendar-picker-indicator {
|
|
background: transparent;
|
|
bottom: 0;
|
|
color: transparent;
|
|
cursor: pointer;
|
|
height: auto;
|
|
left: 0;
|
|
position: absolute;
|
|
right: 0;
|
|
top: 0;
|
|
width: auto;
|
|
appearance: none;
|
|
-webkit-appearance: none;
|
|
}
|
|
|
|
/*Chrome*/
|
|
@media screen and (-webkit-min-device-pixel-ratio:0) {
|
|
input[type='range']::-webkit-slider-thumb {
|
|
width: 20px;
|
|
-webkit-appearance: none;
|
|
border-radius: 50%;
|
|
height: 20px;
|
|
cursor: pointer;
|
|
background: #4b5563;
|
|
}
|
|
}
|
|
|
|
/*Firefox*/
|
|
input[type='range']::-moz-range-thumb {
|
|
width: 16px;
|
|
-webkit-appearance: none;
|
|
border-radius: 50%;
|
|
height: 16px;
|
|
cursor: pointer;
|
|
background: #4b5563;
|
|
border-color: #4b5563;
|
|
}
|
|
</style>
|
|
<!-- Critical CSS to prevent layout shift before Tailwind loads -->
|
|
<style>
|
|
/* Critical layout styles to prevent CLS - these match Tailwind utility classes */
|
|
.bg-white { background-color: #fff; }
|
|
.relative { position: relative; }
|
|
.flex { display: flex; }
|
|
.hidden { display: none; }
|
|
.items-center { align-items: center; }
|
|
.justify-between { justify-content: space-between; }
|
|
.justify-start { justify-content: flex-start; }
|
|
.justify-center { justify-content: center; }
|
|
.text-center { text-align: center; }
|
|
.mx-auto { margin-left: auto; margin-right: auto; }
|
|
.max-w-7xl { max-width: 80rem; }
|
|
.max-w-3xl { max-width: 48rem; }
|
|
.px-6 { padding-left: 1.5rem; padding-right: 1.5rem; }
|
|
.py-6 { padding-top: 1.5rem; padding-bottom: 1.5rem; }
|
|
.py-12 { padding-top: 3rem; padding-bottom: 3rem; }
|
|
.py-24 { padding-top: 6rem; padding-bottom: 6rem; }
|
|
.border-b-2 { border-bottom-width: 2px; border-bottom-style: solid; }
|
|
.border-gray-100 { border-color: #f3f4f6; }
|
|
.overflow-hidden { overflow: hidden; }
|
|
.w-auto { width: auto; }
|
|
.h-8 { height: 2rem; }
|
|
.h-10 { height: 2.5rem; }
|
|
.space-x-10 > :not([hidden]) ~ :not([hidden]) { margin-left: 2.5rem; }
|
|
.inline-flex { display: inline-flex; }
|
|
.grid { display: grid; }
|
|
.gap-4 { gap: 1rem; }
|
|
.gap-5 { gap: 1.25rem; }
|
|
.isolate { isolation: isolate; }
|
|
.fixed { position: fixed; }
|
|
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border-width: 0; }
|
|
@media (min-width: 640px) {
|
|
.sm\:h-10 { height: 2.5rem; }
|
|
.sm\:py-16 { padding-top: 4rem; padding-bottom: 4rem; }
|
|
.sm\:grid-cols-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
|
|
.sm\:gap-5 { gap: 1.25rem; }
|
|
}
|
|
@media (min-width: 768px) {
|
|
.md\:hidden { display: none; }
|
|
.md\:flex { display: flex; }
|
|
.md\:justify-start { justify-content: flex-start; }
|
|
.md\:space-x-10 > :not([hidden]) ~ :not([hidden]) { margin-left: 2.5rem; }
|
|
}
|
|
@media (min-width: 1024px) {
|
|
.lg\:w-0 { width: 0; }
|
|
.lg\:flex-1 { flex: 1 1 0%; }
|
|
.lg\:px-8 { padding-left: 2rem; padding-right: 2rem; }
|
|
.lg\:py-40 { padding-top: 10rem; padding-bottom: 10rem; }
|
|
}
|
|
.grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
.auto-rows-fr { grid-auto-rows: minmax(0, 1fr); }
|
|
/* Reserve space for logo-roll section to prevent CLS */
|
|
.marquee-container { overflow: hidden; min-height: 60px; }
|
|
.logo-item { min-width: 160px; height: 60px; }
|
|
.logo-item img { max-height: 36px; max-width: 140px; }
|
|
</style>
|
|
|
|
<!-- Tailwind CSS (render-critical), served from this install rather than cdn.tailwindcss.com -->
|
|
<script src="/oneuptime-assets/tailwind/tailwind-3.4.5.js"></script>
|
|
|
|
<!--
|
|
Home's own reporting on a captured touch. The shared partial captures the
|
|
attribution and calls this; the event name is the marketing site's, which
|
|
is exactly why it is not in the partial.
|
|
-->
|
|
<script>
|
|
window.oneUptimeOnAttributionCaptured = function (eventProps) {
|
|
if (typeof posthog !== 'undefined' && posthog && posthog.capture) {
|
|
posthog.capture('home/utm_event', eventProps);
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<!--
|
|
Consent.
|
|
|
|
This block runs BEFORE Google Tag Manager, because Consent Mode's defaults
|
|
have to be on the dataLayer before the container reads it.
|
|
|
|
MEASUREMENT IS NO LONGER GATED ON THE BANNER. Consent Mode defaults to
|
|
granted, attribution is captured and stored on every visit, and PostHog
|
|
loads on every visit. The `cookiesAccepted` key is still written and
|
|
`oneUptimeConsent` still reports it, because the banner and the footer's
|
|
cookie-settings link still read and write it — but nothing downstream
|
|
branches on the answer any more.
|
|
|
|
Stated plainly so nobody has to infer it from the code: pressing "Reject
|
|
all" does not stop measurement, does not stop attribution being stored, and
|
|
does not clear what an earlier visit stored. This was a deliberate product
|
|
decision (the booking receiver needs every booking attributed, and a
|
|
booking is itself a deliberate act by the visitor); it is not an oversight,
|
|
and it is not the behaviour the banner's own copy describes. If that copy
|
|
or the banner UI is meant to keep promising a choice, this is the file that
|
|
has to change back.
|
|
-->
|
|
|
|
<!--
|
|
The dataLayer and the gtag shim, defined before both the consent signals
|
|
below and the container itself.
|
|
|
|
Deliberately inside the enableGoogleTagManager gate. A self-hosted install
|
|
loads no Google tag at all, and every OneUptime event guards on
|
|
`typeof dataLayer !== 'undefined'` — so creating the array there would turn
|
|
those no-ops into an array that grows for the life of the page and that
|
|
nothing will ever read.
|
|
-->
|
|
<script>
|
|
window.dataLayer = window.dataLayer || [];
|
|
function gtag() { dataLayer.push(arguments); }
|
|
</script>
|
|
|
|
|
|
<script>
|
|
window.oneUptimeConsent = (function () {
|
|
var STORAGE_KEY = 'cookiesAccepted';
|
|
|
|
function readRaw() {
|
|
try {
|
|
return window.localStorage.getItem(STORAGE_KEY);
|
|
} catch (e) {
|
|
/*
|
|
* Private mode, disabled storage, or a cross-origin sandbox.
|
|
* Unreadable storage is not consent.
|
|
*/
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function state() {
|
|
var raw = readRaw();
|
|
if (raw === 'true') { return 'granted'; }
|
|
if (raw === 'false') { return 'denied'; }
|
|
return 'unset';
|
|
}
|
|
|
|
function isGranted() {
|
|
return state() === 'granted';
|
|
}
|
|
|
|
/*
|
|
* Consent Mode v2, defaulting to granted across the board.
|
|
*
|
|
* wait_for_update is kept at 500ms so the container's own timing is
|
|
* unchanged, even though nothing arrives later to change the answer.
|
|
*/
|
|
function pushConsentSignal(mode, granted) {
|
|
/*
|
|
* No tag, nothing to tell. On a self-hosted install gtag is never
|
|
* defined; the banner's answer is still recorded either way.
|
|
*/
|
|
if (typeof window.gtag !== 'function') {
|
|
return;
|
|
}
|
|
|
|
window.gtag('consent', mode, {
|
|
ad_storage: granted ? 'granted' : 'denied',
|
|
ad_user_data: granted ? 'granted' : 'denied',
|
|
ad_personalization: granted ? 'granted' : 'denied',
|
|
analytics_storage: granted ? 'granted' : 'denied',
|
|
functionality_storage: granted ? 'granted' : 'denied',
|
|
personalization_storage: granted ? 'granted' : 'denied',
|
|
security_storage: 'granted',
|
|
wait_for_update: 500
|
|
});
|
|
}
|
|
|
|
pushConsentSignal('default', true);
|
|
|
|
function set(granted) {
|
|
try {
|
|
window.localStorage.setItem(STORAGE_KEY, granted ? 'true' : 'false');
|
|
} catch (e) {
|
|
// Nothing to persist to. The in-page decision still applies.
|
|
}
|
|
|
|
/*
|
|
* Deliberately NOT pushing a Consent Mode update here. The default
|
|
* is granted and stays granted; pushing 'denied' on a refusal would
|
|
* re-gate the Google tag and make the banner functional again,
|
|
* which is exactly what this file no longer does.
|
|
*
|
|
* There is no observer list either. Nothing downstream reacts to
|
|
* the answer any more, and an onChange() that could never fire is
|
|
* an API that reads as working code — re-add it alongside the
|
|
* consumer that needs it, not before.
|
|
*/
|
|
}
|
|
|
|
return {
|
|
state: state,
|
|
isGranted: isGranted,
|
|
grant: function () { set(true); },
|
|
deny: function () { set(false); }
|
|
};
|
|
})();
|
|
</script>
|
|
|
|
<!--
|
|
Attribution capture (UTM parameters + ad platform click IDs), and the
|
|
reader that hands it on to the signup form (through localStorage, same
|
|
origin).
|
|
|
|
STORAGE MODEL
|
|
|
|
- Last-touch UTM values live in the individual utm* localStorage keys, read
|
|
by the signup page and stored on the User record.
|
|
- Last-touch click IDs live as a JSON object under 'clickIds'.
|
|
- The visitor's first attributed visit is preserved as JSON under
|
|
'firstTouch' and never overwritten.
|
|
|
|
A visit counts as a new "touch" if it carries ANY utm parameter or ad click
|
|
ID — Google Ads auto-tagging sends only gclid, no UTMs.
|
|
|
|
CONSENT
|
|
|
|
None. Every touch is stored on sight, whatever the banner says and whether
|
|
or not it has been answered. See the block at the top of this file for why.
|
|
|
|
CAL.COM BOOKINGS
|
|
|
|
window.oneUptimeCalAttributionMetadata(bookingKind) flattens the same
|
|
attribution into the scalar string map Cal.com accepts as booking metadata.
|
|
Cal hands it back on its BOOKING_CREATED webhook, which is delivered to the
|
|
CRM — not to OneUptime, which receives no booking webhook at all
|
|
(Docs/analytics/enterprise-conversion-tracking.md).
|
|
-->
|
|
<script>
|
|
(function () {
|
|
/*
|
|
* Must stay in step with UtmWireKeyToPropertyKey in
|
|
* Common/Types/Marketing/Attribution.ts — the signup door whitelists on
|
|
* that map, so a key written here that is missing there is silently
|
|
* dropped on arrival. AttributionCapture.test.ts asserts the two are
|
|
* identical.
|
|
*/
|
|
var UTM_KEY_MAP = {
|
|
'utm_source': 'utmSource',
|
|
'utm_medium': 'utmMedium',
|
|
'utm_campaign': 'utmCampaign',
|
|
'utm_term': 'utmTerm',
|
|
'utm_content': 'utmContent',
|
|
'utm_id': 'utmId',
|
|
'utm_source_platform': 'utmSourcePlatform',
|
|
'utm_creative_format': 'utmCreativeFormat',
|
|
'utm_marketing_tactic': 'utmMarketingTactic'
|
|
};
|
|
|
|
/*
|
|
* Must stay in step with AdClickIdKeys in
|
|
* Common/Types/Marketing/Attribution.ts — the server whitelists on that
|
|
* list, so a key sent from here that is missing there is silently
|
|
* dropped on arrival.
|
|
*/
|
|
var CLICK_ID_PARAMS = ['gclid', 'wbraid', 'gbraid', 'fbclid', 'msclkid', 'li_fat_id', 'twclid', 'rdt_cid'];
|
|
|
|
// Mirrors MaxAttributionValueLength on the server.
|
|
var MAX_VALUE_LENGTH = 500;
|
|
|
|
/*
|
|
* The first touch travels to Cal as one JSON string, so it gets a JSON
|
|
* bound rather than the 500-char per-value one. Truncating JSON
|
|
* produces a string the receiver's JSON.parse rejects, which would drop
|
|
* the whole first touch silently.
|
|
*/
|
|
var MAX_FIRST_TOUCH_LENGTH = 4000;
|
|
|
|
/*
|
|
* This page's touch, kept in memory as well as written.
|
|
*
|
|
* Not a consent buffer — storeTouch runs unconditionally now. This is
|
|
* for the browser that refuses localStorage outright: private modes,
|
|
* "block all site data", a sandboxed iframe, enterprise storage policy.
|
|
* There, every setItem throws and is swallowed as best-effort, so a
|
|
* reader that trusted storage alone would hand Cal an empty bag for a
|
|
* visitor who arrived on a paid click seconds earlier — the exact
|
|
* failure this whole path exists to prevent.
|
|
*/
|
|
var currentTouch = null;
|
|
|
|
function setItem(key, value) {
|
|
try {
|
|
window.localStorage.setItem(key, value);
|
|
} catch (e) {
|
|
// Storage unavailable; attribution is best-effort.
|
|
}
|
|
}
|
|
|
|
function removeItem(key) {
|
|
try {
|
|
window.localStorage.removeItem(key);
|
|
} catch (e) {
|
|
// Nothing to remove from.
|
|
}
|
|
}
|
|
|
|
function getItem(key) {
|
|
try {
|
|
return window.localStorage.getItem(key);
|
|
} catch (e) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function bound(value) {
|
|
return String(value).slice(0, MAX_VALUE_LENGTH);
|
|
}
|
|
|
|
function readTouchFromUrl() {
|
|
var urlParams = new URLSearchParams(window.location.search);
|
|
|
|
var utmValues = {};
|
|
var hasUtm = false;
|
|
Object.keys(UTM_KEY_MAP).forEach(function (param) {
|
|
var value = urlParams.get(param);
|
|
if (value) {
|
|
utmValues[UTM_KEY_MAP[param]] = bound(value);
|
|
hasUtm = true;
|
|
}
|
|
});
|
|
|
|
var clickIds = {};
|
|
var hasClickId = false;
|
|
CLICK_ID_PARAMS.forEach(function (param) {
|
|
var value = urlParams.get(param);
|
|
if (value) {
|
|
clickIds[param] = bound(value);
|
|
hasClickId = true;
|
|
}
|
|
});
|
|
|
|
if (!hasUtm && !hasClickId) {
|
|
return null;
|
|
}
|
|
|
|
return {
|
|
utmValues: utmValues,
|
|
clickIds: clickIds,
|
|
hasClickId: hasClickId,
|
|
url: window.location.href,
|
|
referrer: document.referrer || '',
|
|
timestamp: new Date().toISOString()
|
|
};
|
|
}
|
|
|
|
function storeTouch(touch) {
|
|
// New touch: clear previous last-touch values, then store this visit's.
|
|
Object.keys(UTM_KEY_MAP).forEach(function (param) {
|
|
removeItem(UTM_KEY_MAP[param]);
|
|
});
|
|
Object.keys(touch.utmValues).forEach(function (key) {
|
|
setItem(key, touch.utmValues[key]);
|
|
});
|
|
setItem('utmUrl', touch.url);
|
|
|
|
if (touch.hasClickId) {
|
|
setItem('clickIds', JSON.stringify(touch.clickIds));
|
|
} else {
|
|
removeItem('clickIds');
|
|
}
|
|
|
|
// Preserve the first attributed touch forever.
|
|
if (!getItem('firstTouch')) {
|
|
var firstTouch = {};
|
|
Object.keys(touch.utmValues).forEach(function (key) {
|
|
firstTouch[key] = touch.utmValues[key];
|
|
});
|
|
if (touch.hasClickId) {
|
|
firstTouch.clickIds = touch.clickIds;
|
|
}
|
|
firstTouch.landingUrl = touch.url;
|
|
firstTouch.referrer = touch.referrer;
|
|
firstTouch.timestamp = touch.timestamp;
|
|
setItem('firstTouch', JSON.stringify(firstTouch));
|
|
}
|
|
}
|
|
|
|
function parseStoredJson(key) {
|
|
var raw = getItem(key);
|
|
if (!raw) { return null; }
|
|
try {
|
|
var parsed = JSON.parse(raw);
|
|
return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : null;
|
|
} catch (e) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Everything known about where this visitor came from, whether it
|
|
* reached storage or is only in memory.
|
|
*
|
|
* This page's touch wins: it is this page load, and the stored copy is
|
|
* at best the same thing and at worst an older visit.
|
|
*/
|
|
window.oneUptimeGetAttribution = function () {
|
|
var utm = {};
|
|
Object.keys(UTM_KEY_MAP).forEach(function (param) {
|
|
var key = UTM_KEY_MAP[param];
|
|
var value = (currentTouch && currentTouch.utmValues[key]) || getItem(key);
|
|
if (value && value !== 'null' && value !== 'undefined') {
|
|
utm[key] = value;
|
|
}
|
|
});
|
|
|
|
var utmUrl = (currentTouch && currentTouch.url) || getItem('utmUrl');
|
|
if (utmUrl) {
|
|
utm.utmUrl = utmUrl;
|
|
}
|
|
|
|
var clickIds = (currentTouch && currentTouch.hasClickId ? currentTouch.clickIds : null)
|
|
|| parseStoredJson('clickIds')
|
|
|| {};
|
|
|
|
var firstTouch = parseStoredJson('firstTouch');
|
|
|
|
/*
|
|
* Storage refused the write, so there is no stored first touch to
|
|
* read back. This visit is the only one we will ever know about,
|
|
* which makes it the first one.
|
|
*/
|
|
if (!firstTouch && currentTouch) {
|
|
firstTouch = {};
|
|
Object.keys(currentTouch.utmValues).forEach(function (key) {
|
|
firstTouch[key] = currentTouch.utmValues[key];
|
|
});
|
|
if (currentTouch.hasClickId) {
|
|
firstTouch.clickIds = currentTouch.clickIds;
|
|
}
|
|
firstTouch.landingUrl = currentTouch.url;
|
|
firstTouch.referrer = currentTouch.referrer;
|
|
firstTouch.timestamp = currentTouch.timestamp;
|
|
}
|
|
|
|
return {
|
|
utm: utm,
|
|
clickIds: clickIds,
|
|
firstTouch: firstTouch
|
|
};
|
|
};
|
|
|
|
/*
|
|
* The same attribution, flattened into the scalar string map Cal.com
|
|
* accepts as booking metadata.
|
|
*
|
|
* Cal takes booking metadata as FLAT, BRACKETED keys on the embed
|
|
* config — `metadata[utm_source]` — and hands them back on the webhook
|
|
* as payload.metadata.utm_source. NOT as a nested `metadata: {...}`
|
|
* object: Cal serialises each config value into a query parameter, so a
|
|
* nested object becomes the string "[object Object]" and every key
|
|
* inside it is lost. Nothing errors; bookings keep succeeding, they
|
|
* just arrive attributable to nothing — indistinguishable from not
|
|
* having done this at all.
|
|
*
|
|
* https://cal.com/help/embedding/prefill-booking-form-embed
|
|
*
|
|
* Keys are the snake_case wire spelling, which is what the CRM's Cal
|
|
* webhook receiver parses. Returns {} when there is nothing to
|
|
* attribute and no booking kind, so a caller can spread it
|
|
* unconditionally without sending an empty metadata bag.
|
|
*/
|
|
window.oneUptimeCalAttributionMetadata = function (bookingKind) {
|
|
var attribution = window.oneUptimeGetAttribution();
|
|
var config = {};
|
|
|
|
function put(key, value, maxLength) {
|
|
if (value) {
|
|
config['metadata[' + key + ']'] =
|
|
String(value).slice(0, maxLength || MAX_VALUE_LENGTH);
|
|
}
|
|
}
|
|
|
|
Object.keys(UTM_KEY_MAP).forEach(function (param) {
|
|
put(param, attribution.utm[UTM_KEY_MAP[param]]);
|
|
});
|
|
|
|
put('utm_url', attribution.utm.utmUrl);
|
|
|
|
Object.keys(attribution.clickIds).forEach(function (param) {
|
|
put(param, attribution.clickIds[param]);
|
|
});
|
|
|
|
if (attribution.firstTouch) {
|
|
var serialized = JSON.stringify(attribution.firstTouch);
|
|
if (serialized.length <= MAX_FIRST_TOUCH_LENGTH) {
|
|
put('ou_first_touch', serialized, MAX_FIRST_TOUCH_LENGTH);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Unconditional, unlike everything above it. All three embeds book
|
|
* the same Cal event type (oneuptimehq/demo), so without this the
|
|
* receiver cannot tell a support call from an enterprise demo from
|
|
* a self-hosted architecture assessment — they arrive identical.
|
|
*/
|
|
if (bookingKind) {
|
|
config['metadata[ou_booking_kind]'] = String(bookingKind).slice(0, MAX_VALUE_LENGTH);
|
|
}
|
|
|
|
return config;
|
|
};
|
|
|
|
var touch = readTouchFromUrl();
|
|
|
|
if (touch) {
|
|
currentTouch = touch;
|
|
storeTouch(touch);
|
|
}
|
|
|
|
/*
|
|
* Reporting is the including page's business, not this partial's.
|
|
*
|
|
* The marketing site emits a `home/`-prefixed PostHog event from here;
|
|
* the product origins emit nothing, and must not start emitting under
|
|
* a `home/` name just because they now share the capture code. So the
|
|
* touch is handed out and the page decides what, if anything, to do
|
|
* with it.
|
|
*
|
|
* Wire keys (utm_source), not property keys (utmSource): this is what
|
|
* arrived on the URL.
|
|
*/
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
if (!touch || typeof window.oneUptimeOnAttributionCaptured !== 'function') {
|
|
return;
|
|
}
|
|
|
|
var eventProps = { utm_url: touch.url };
|
|
Object.keys(UTM_KEY_MAP).forEach(function (param) {
|
|
if (touch.utmValues[UTM_KEY_MAP[param]]) {
|
|
eventProps[param] = touch.utmValues[UTM_KEY_MAP[param]];
|
|
}
|
|
});
|
|
Object.keys(touch.clickIds).forEach(function (param) {
|
|
eventProps[param] = touch.clickIds[param];
|
|
});
|
|
|
|
window.oneUptimeOnAttributionCaptured(eventProps);
|
|
});
|
|
})();
|
|
</script>
|
|
|
|
|
|
<!-- Google Tag Manager -->
|
|
<script>(function (w, d, s, l, i) {
|
|
w[l] = w[l] || []; w[l].push({
|
|
'gtm.start':
|
|
new Date().getTime(), event: 'gtm.js'
|
|
}); var f = d.getElementsByTagName(s)[0],
|
|
j = d.createElement(s), dl = l != 'dataLayer' ? '&l=' + l : ''; j.async = true; j.src =
|
|
'https://www.googletagmanager.com/gtm.js?id=' + i + dl; f.parentNode.insertBefore(j, f);
|
|
})(window, document, 'script', 'dataLayer', 'GTM-PKQD5WH');</script>
|
|
<!-- End Google Tag Manager -->
|
|
|
|
|
|
<!--
|
|
Deferred analytics - PostHog loads after page render to improve LCP. Until
|
|
it lands the stub queues capture calls, so nothing in the product has to
|
|
know whether the library is there. Loading is not gated on the cookie
|
|
banner (Common/Server/Views/Partials/AnalyticsConsent.ejs).
|
|
-->
|
|
<script>
|
|
// PostHog stub - capture calls are queued until the library loads
|
|
window.posthog = window.posthog || [];
|
|
window.posthog._i = [];
|
|
window.posthog.init = window.posthog.init || function(){};
|
|
window.posthog.capture = window.posthog.capture || function(){window.posthog.push(['capture'].concat(Array.prototype.slice.call(arguments, 0)));};
|
|
|
|
// Defer PostHog initialization until after page render
|
|
(function() {
|
|
var started = false;
|
|
|
|
function initPostHog() {
|
|
if (started) { return; }
|
|
started = true;
|
|
|
|
!function (t, e) { var o, n, p, r; e.__SV || (window.posthog = e, e._i = [], e.init = function (i, s, a) { function g(t, e) { var o = e.split("."); 2 == o.length && (t = t[o[0]], e = o[1]), t[e] = function () { t.push([e].concat(Array.prototype.slice.call(arguments, 0))) } } (p = t.createElement("script")).type = "text/javascript", p.async = !0, p.src = s.api_host + "/static/array.js", (r = t.getElementsByTagName("script")[0]).parentNode.insertBefore(p, r); var u = e; for (void 0 !== a ? u = e[a] = [] : a = "posthog", u.people = u.people || [], u.toString = function (t) { var e = "posthog"; return "posthog" !== a && (e += "." + a), t || (e += " (stub)"), e }, u.people.toString = function () { return u.toString(1) + ".people (stub)" }, o = "capture identify alias people.set people.set_once set_config register register_once unregister opt_out_capturing has_opted_out_capturing opt_in_capturing reset isFeatureEnabled onFeatureFlags getFeatureFlag getFeatureFlagPayload reloadFeatureFlags group updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures getActiveMatchingSurveys getSurveys".split(" "), n = 0; n < o.length; n++)g(u, o[n]); e._i.push([i, s, a]) }, e.__SV = 1) }(document, window.posthog || []);
|
|
posthog.init('phc_lrbfSHsDc1YOhfbabPI8ncLCKz8eqeGdmu0O6IRKaz1', { api_host: 'https://eu.posthog.com', autocapture: false });
|
|
}
|
|
|
|
function initWhenIdle() {
|
|
// Use requestIdleCallback to defer PostHog until browser is idle
|
|
if ('requestIdleCallback' in window) {
|
|
requestIdleCallback(initPostHog);
|
|
} else {
|
|
setTimeout(initPostHog, 1);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Unconditional. PostHog used to wait for the banner; it no longer
|
|
* does — see the top of
|
|
* Common/Server/Views/Partials/AnalyticsConsent.ejs for the decision
|
|
* and its consequences. The stub above still queues capture calls
|
|
* until the library is in, so nothing is lost in the meantime.
|
|
*/
|
|
initWhenIdle();
|
|
})();
|
|
</script>
|
|
|
|
<!--
|
|
Canonical browser record of a booked meeting
|
|
(Docs/analytics/enterprise-conversion-tracking.md). It carries no attendee
|
|
details: Cal's bookingSuccessful detail includes the attendee's name and
|
|
email, and none of it is passed through. The legacy per-page PostHog event
|
|
is emitted alongside so existing dashboards keep their history.
|
|
-->
|
|
<script>
|
|
/*
|
|
* Cal fires the booking event under more than one action name: the older
|
|
* 'bookingSuccessful' and the newer 'bookingSuccessfulV2'. embed.js is
|
|
* loaded unpinned from app.cal.com, so which name arrives is Cal's
|
|
* decision on any given day - and a booking that fires only the name we
|
|
* are not subscribed to reports no conversion at all, silently, while the
|
|
* booking itself still succeeds. Subscribing to one name makes the
|
|
* enterprise lead conversion depend on a third party not renaming it.
|
|
*
|
|
* Subscribe to both and latch: whichever arrives first reports the
|
|
* booking, and a second name for the same booking is ignored, so one
|
|
* booking stays one meeting_booked.
|
|
*/
|
|
window.oneUptimeOnCalBookingSuccess = function (handler) {
|
|
if (typeof Cal !== 'function') {
|
|
return;
|
|
}
|
|
|
|
var reported = false;
|
|
|
|
var once = function (e) {
|
|
if (reported) {
|
|
return;
|
|
}
|
|
reported = true;
|
|
handler(e && e.detail ? e.detail : {});
|
|
};
|
|
|
|
['bookingSuccessful', 'bookingSuccessfulV2'].forEach(function (action) {
|
|
Cal('on', { action: action, callback: once });
|
|
});
|
|
};
|
|
|
|
window.oneUptimeTrackMeetingBooked = function (options) {
|
|
options = options || {};
|
|
|
|
var properties = {
|
|
event_schema_version: 1,
|
|
booking_source: 'cal.com',
|
|
booking_kind: options.bookingKind || 'unknown',
|
|
page_path: window.location.pathname,
|
|
cal_event_type: typeof options.calEventType === 'string' ? options.calEventType : 'bookingSuccessful',
|
|
cal_namespace: typeof options.calNamespace === 'string' ? options.calNamespace : 'default'
|
|
};
|
|
|
|
if (typeof posthog !== 'undefined' && posthog && posthog.capture) {
|
|
posthog.capture('meeting_booked', properties);
|
|
|
|
// Legacy event name, kept so existing PostHog dashboards do not break.
|
|
if (options.legacyEventName) {
|
|
posthog.capture(options.legacyEventName, properties);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* One booking, one GA4 event. The dataLayer push below is the only
|
|
* path to Google; the GTM container forwards it with a Custom Event
|
|
* trigger (see Docs/analytics/gtm-key-events.json).
|
|
*
|
|
* There used to be a `gtag('event', 'meeting_booked', ...)` mirror
|
|
* here as well. Once the Google tag is on the page, gtag interop is
|
|
* live and that call reaches GA4 *directly*, bypassing GTM - so with
|
|
* the forwarding tag in place the same booking was counted twice,
|
|
* under one name, from two mechanisms. Keep every OneUptime event on
|
|
* the dataLayer path so the container stays the single control point.
|
|
*/
|
|
if (typeof dataLayer !== 'undefined') {
|
|
dataLayer.push(Object.assign({ event: 'meeting_booked' }, properties));
|
|
}
|
|
};
|
|
</script>
|
|
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
// Track page view
|
|
if (typeof posthog !== 'undefined' && posthog && posthog.capture) {
|
|
posthog.capture('home/page_view', {
|
|
'page': {
|
|
'path': window.location.pathname,
|
|
'referrer': document.referrer,
|
|
'search': window.location.search,
|
|
'url': window.location.href,
|
|
'title': document.title,
|
|
}
|
|
});
|
|
}
|
|
|
|
/*
|
|
* CTA clicks, for conversion funnel analysis.
|
|
*
|
|
* `data-ou-cta` names the event explicitly and is the path to prefer.
|
|
* The href patterns below are the fallback that covers the register
|
|
* and demo links scattered across the site without tagging each one.
|
|
*
|
|
* A[href*="demo"] used to be in that fallback and was wrong in both
|
|
* directions at once: it matched in-page scroll anchors like
|
|
* #book-demo on the demo page itself - a visitor moving down a page
|
|
* they had already reached, counted as a fresh demo request - while
|
|
* matching nothing at all on the self-hosted page, whose enterprise
|
|
* CTAs point at #architecture-assessment. The one CTA that mattered
|
|
* most to a sales-led funnel was the one that fired nothing.
|
|
*/
|
|
document.querySelectorAll('a[data-ou-cta], a[href="/accounts/register"], a[href*="register"], a[href="/enterprise/demo"]').forEach(function(link) {
|
|
link.addEventListener('click', function(e) {
|
|
var href = this.getAttribute('href');
|
|
var eventName = this.getAttribute('data-ou-cta')
|
|
|| (href.indexOf('register') !== -1 ? 'cta_get_started' : 'cta_request_demo');
|
|
|
|
// PostHog
|
|
if (typeof posthog !== 'undefined' && posthog && posthog.capture) {
|
|
posthog.capture('home/' + eventName, {
|
|
'page': window.location.pathname,
|
|
'href': href,
|
|
'text': this.innerText.trim()
|
|
});
|
|
}
|
|
|
|
// GA4 via dataLayer
|
|
if (typeof dataLayer !== 'undefined') {
|
|
dataLayer.push({
|
|
'event': eventName,
|
|
'eventCategory': 'cta_click',
|
|
'eventAction': eventName,
|
|
'eventLabel': window.location.pathname
|
|
});
|
|
}
|
|
});
|
|
});
|
|
});
|
|
</script>
|
|
|
|
<!-- PWA Meta Tags -->
|
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
<meta name="apple-mobile-web-app-status-bar-style" content="default">
|
|
<meta name="apple-mobile-web-app-title" content="OneUptime">
|
|
<meta name="mobile-web-app-capable" content="yes">
|
|
<meta name="application-name" content="OneUptime">
|
|
|
|
<!-- Icons -->
|
|
<link rel="shortcut icon" href="/img/favicons/favicon.ico">
|
|
<link rel="apple-touch-icon" sizes="180x180" href="/img/favicons/apple-touch-icon.png">
|
|
<link rel="icon" type="image/png" sizes="32x32" href="/img/favicons/favicon-32x32.png">
|
|
<link rel="icon" type="image/png" sizes="16x16" href="/img/favicons/favicon-16x16.png">
|
|
<link rel="mask-icon" href="/img/favicons/safari-pinned-tab.svg" color="#000000">
|
|
|
|
<!-- Microsoft Tiles -->
|
|
<meta name="msapplication-TileColor" content="#000000">
|
|
<meta name="msapplication-TileImage" content="/img/favicons/mstile-144x144.png">
|
|
|
|
<!-- Legacy and compatibility -->
|
|
<link rel="apple-touch-icon-precomposed" href="/img/ou-wb.svg">
|
|
<link rel="icon" href="/img/ou-wb.svg">
|
|
<link rel="image_src" type="image/png" href="/img/hou-wb.svg">
|
|
|
|
<!-- Canonical URL -->
|
|
|
|
<link rel="canonical" href="https://oneuptime.com">
|
|
|
|
<!-- Feed autodiscovery -->
|
|
|
|
<link rel="alternate" type="application/rss+xml" title="OneUptime Blog RSS Feed" href="https://oneuptime.com/blog/rss.xml"> <link rel="alternate" type="text/markdown" title="Markdown version of this post" href="/blog/post/2025-09-03-what-are-error-budgets/markdown">
|
|
<meta property="og:site_name" content="OneUptime | One Complete Observability platform.">
|
|
<meta property="og:type" content="article">
|
|
<meta property="og:title" content=" What are Error Budgets? A Guide to Managing Reliability">
|
|
<meta property="og:description" content=" Error budgets are a fundamental concept in Site Reliability Engineering that help teams balance innovation with reliability.">
|
|
<meta property="og:url" content="https://oneuptime.com/blog/post/2025-09-03-what-are-error-budgets/view">
|
|
<meta property="og:image" content="https://oneuptime.com/blog/post/2025-09-03-what-are-error-budgets/social-media.png">
|
|
<meta property="article:published_time" content="2025-09-03T00:00:00.000Z">
|
|
<meta property="article:modified_time" content="2025-09-03T00:00:00.000Z">
|
|
<meta property="article:publisher" content="https://www.facebook.com/OneUptime">
|
|
<meta name="twitter:card" content="summary_large_image">
|
|
<meta name="twitter:title" content=" What are Error Budgets? A Guide to Managing Reliability">
|
|
<meta name="twitter:description" content=" Error budgets are a fundamental concept in Site Reliability Engineering that help teams balance innovation with reliability.">
|
|
<meta name="twitter:url" content="https://oneuptime.com/blog/post/2025-09-03-what-are-error-budgets/view">
|
|
<meta name="twitter:image" content="https://oneuptime.com/blog/post/2025-09-03-what-are-error-budgets/social-media.png">
|
|
<meta name="twitter:label1" content="Written by">
|
|
<meta name="twitter:data1" content="Nawaz Dhandala">
|
|
<meta name="twitter:site" content="@OneUptimeHQ">
|
|
<meta property="og:image:width" content="1280">
|
|
<meta property="og:image:height" content="720">
|
|
<script type="application/ld+json">
|
|
{
|
|
"@context": "https://schema.org",
|
|
"@type": "BlogPosting",
|
|
"keywords": "Site Reliability Engineering, SRE, Observability, SLO, Error Budget, Reliability",
|
|
"publisher": {
|
|
"@type": "Organization",
|
|
"name": "OneUptime",
|
|
"url": "https://oneuptime.com/",
|
|
"logo": {
|
|
"@type": "ImageObject",
|
|
"url": "https://oneuptime.com/img/OneUptimePNG/1.png",
|
|
"width": 60,
|
|
"height": 60
|
|
}
|
|
},
|
|
"author": {
|
|
"@type": "Person",
|
|
"name": "Nawaz Dhandala",
|
|
"url": "https://github.com/nawazdhandala",
|
|
"sameAs": []
|
|
},
|
|
"headline": " What are Error Budgets? A Guide to Managing Reliability",
|
|
"url": "https://oneuptime.com/blog/post/2025-09-03-what-are-error-budgets/view",
|
|
"datePublished": "2025-09-03T00:00:00.000Z",
|
|
"dateModified": "2025-09-03T00:00:00.000Z",
|
|
"description": " Error budgets are a fundamental concept in Site Reliability Engineering that help teams balance innovation with reliability.",
|
|
"mainEntityOfPage": "https://oneuptime.com/blog/post/2025-09-03-what-are-error-budgets/view"
|
|
}
|
|
</script>
|
|
|
|
<!-- Breadcrumb schema -->
|
|
<script type="application/ld+json">
|
|
{
|
|
"@context": "https://schema.org",
|
|
"@type": "BreadcrumbList",
|
|
"itemListElement": [
|
|
{ "@type": "ListItem", "position": 1, "name": "Home", "item": "https://oneuptime.com/" },
|
|
{ "@type": "ListItem", "position": 2, "name": "Blog", "item": "https://oneuptime.com/blog" },
|
|
{ "@type": "ListItem", "position": 3, "name": " What are Error Budgets? A Guide to Managing Reliability" }
|
|
]
|
|
}
|
|
</script>
|
|
|
|
<!-- Syntax highlighting with highlight.js - using VS Code dark theme -->
|
|
<link rel="stylesheet" href="/oneuptime-assets/highlight/styles/vs2015.min.css">
|
|
<script src="/oneuptime-assets/highlight/highlight.min.js"></script>
|
|
<script>
|
|
// Lazy-load only the language packs actually used on this page
|
|
document.addEventListener('DOMContentLoaded', function(){
|
|
var langMap = {
|
|
'dockerfile':'dockerfile','yaml':'yaml','yml':'yaml','bash':'bash','shell':'bash','sh':'bash',
|
|
'typescript':'typescript','ts':'typescript','go':'go','python':'python','py':'python',
|
|
'json':'json','ruby':'ruby','rb':'ruby','java':'java','css':'css','sql':'sql',
|
|
'rust':'rust','graphql':'graphql','javascript':'javascript','js':'javascript',
|
|
'xml':'xml','html':'xml','markup':'xml','cpp':'cpp','csharp':'csharp','php':'php',
|
|
'bind':'dns','dns':'dns','zone':'dns',
|
|
'conf':'apache','apache':'apache','nginx':'nginx',
|
|
'ini':'ini','toml':'ini',
|
|
'diff':'diff','http':'http','makefile':'makefile',
|
|
'c':'c','swift':'swift','kotlin':'kotlin','scala':'scala','lua':'lua',
|
|
'perl':'perl','r':'r','powershell':'powershell','ps':'powershell'
|
|
};
|
|
var needed = {};
|
|
document.querySelectorAll('pre code[class*="language-"]').forEach(function(el){
|
|
var m = el.className.match(/language-(\w+)/);
|
|
if(m && langMap[m[1]]){ needed[langMap[m[1]]] = true; }
|
|
else if(m && m[1]){ el.className = el.className.replace(/language-\w+/, ''); }
|
|
});
|
|
var langs = Object.keys(needed);
|
|
var loaded = 0;
|
|
if(langs.length === 0){ hljs.highlightAll(); return; }
|
|
langs.forEach(function(lang){
|
|
var s = document.createElement('script');
|
|
s.src = '/oneuptime-assets/highlight/languages/' + lang + '.min.js';
|
|
s.async = false;
|
|
s.onload = s.onerror = function(){
|
|
loaded++;
|
|
if(loaded >= langs.length){ hljs.highlightAll(); }
|
|
};
|
|
document.head.appendChild(s);
|
|
});
|
|
});
|
|
</script>
|
|
|
|
<style>
|
|
body {
|
|
background: #ffffff;
|
|
color: #111827;
|
|
}
|
|
|
|
.reading-progress {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
width: 0;
|
|
height: 3px;
|
|
z-index: 60;
|
|
background: linear-gradient(90deg, #3b82f6, #06b6d4, #10b981);
|
|
transition: width 120ms ease-out;
|
|
box-shadow: 0 0 10px rgba(59, 130, 246, 0.4), 0 0 20px rgba(6, 182, 212, 0.3);
|
|
}
|
|
|
|
.floating-share {
|
|
position: absolute;
|
|
left: -5rem;
|
|
top: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 0.75rem;
|
|
}
|
|
|
|
.floating-share a, .floating-share button {
|
|
width: 2.75rem;
|
|
height: 2.75rem;
|
|
border-radius: 9999px;
|
|
border: 1px solid rgba(148, 163, 184, 0.5);
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background: rgba(255, 255, 255, 0.9);
|
|
box-shadow: 0 10px 30px rgba(15, 23, 42, 0.06);
|
|
transition: all 0.2s ease;
|
|
cursor: pointer;
|
|
color: inherit;
|
|
}
|
|
|
|
.floating-share a:hover, .floating-share button:hover {
|
|
border-color: #3b82f6;
|
|
color: #3b82f6;
|
|
transform: translateY(-2px);
|
|
}
|
|
|
|
/* Code blocks styling */
|
|
.blog-body pre {
|
|
position: relative;
|
|
font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', 'Consolas', 'Courier New', monospace !important;
|
|
font-size: 14px !important;
|
|
line-height: 1.6 !important;
|
|
font-weight: 400 !important;
|
|
margin-top: 1.75rem !important;
|
|
margin-bottom: 1.75rem !important;
|
|
border: 1px solid rgba(15, 23, 42, 0.1) !important;
|
|
border-radius: 0.75rem !important;
|
|
box-shadow: 0 10px 30px rgba(15, 23, 42, 0.06) !important;
|
|
}
|
|
|
|
.blog-body pre code {
|
|
font-family: inherit !important;
|
|
font-size: inherit !important;
|
|
line-height: inherit !important;
|
|
font-weight: inherit !important;
|
|
}
|
|
|
|
/* Ensure highlight.js doesn't override our font settings */
|
|
.blog-body .hljs {
|
|
font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', 'Consolas', 'Courier New', monospace !important;
|
|
font-size: 14px !important;
|
|
line-height: 1.6 !important;
|
|
font-weight: 400 !important;
|
|
padding: 1.25rem !important;
|
|
padding-top: 3rem !important;
|
|
border-radius: 0.75rem !important;
|
|
}
|
|
|
|
/* Language label */
|
|
.code-block-header {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 0.4rem 0.75rem;
|
|
background: rgba(255, 255, 255, 0.06);
|
|
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
|
|
border-radius: 0.75rem 0.75rem 0 0;
|
|
z-index: 2;
|
|
}
|
|
|
|
.code-lang-label {
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
font-size: 11px;
|
|
font-weight: 500;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.05em;
|
|
color: rgba(255, 255, 255, 0.5);
|
|
user-select: none;
|
|
}
|
|
|
|
/* Copy button */
|
|
.code-copy-btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.35rem;
|
|
padding: 0.2rem 0.5rem;
|
|
border: none;
|
|
border-radius: 0.375rem;
|
|
background: transparent;
|
|
color: rgba(255, 255, 255, 0.5);
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
font-size: 11px;
|
|
font-weight: 500;
|
|
cursor: pointer;
|
|
transition: all 0.15s ease;
|
|
}
|
|
|
|
.code-copy-btn:hover {
|
|
background: rgba(255, 255, 255, 0.1);
|
|
color: rgba(255, 255, 255, 0.85);
|
|
}
|
|
|
|
.code-copy-btn.copied {
|
|
color: #4ade80;
|
|
}
|
|
|
|
.code-copy-btn svg {
|
|
width: 14px;
|
|
height: 14px;
|
|
}
|
|
|
|
/* Custom scrollbar for code blocks */
|
|
.blog-body pre::-webkit-scrollbar,
|
|
.blog-body pre code::-webkit-scrollbar {
|
|
height: 6px;
|
|
}
|
|
|
|
.blog-body pre::-webkit-scrollbar-track,
|
|
.blog-body pre code::-webkit-scrollbar-track {
|
|
background: transparent;
|
|
}
|
|
|
|
.blog-body pre::-webkit-scrollbar-thumb,
|
|
.blog-body pre code::-webkit-scrollbar-thumb {
|
|
background: rgba(255, 255, 255, 0.15);
|
|
border-radius: 3px;
|
|
}
|
|
|
|
.blog-body pre::-webkit-scrollbar-thumb:hover,
|
|
.blog-body pre code::-webkit-scrollbar-thumb:hover {
|
|
background: rgba(255, 255, 255, 0.3);
|
|
}
|
|
|
|
/* Inline code chips */
|
|
.blog-body :not(pre) > code {
|
|
font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', 'Consolas', 'Courier New', monospace;
|
|
font-size: 0.80em;
|
|
padding: 0.15rem 0.4rem;
|
|
border-radius: 0.375rem;
|
|
background: rgba(59, 130, 246, 0.08);
|
|
border: 1px solid rgba(59, 130, 246, 0.15);
|
|
color: #2563eb;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.blog-body :not(pre) > code strong {
|
|
font-weight: 600;
|
|
}
|
|
|
|
/* Blockquotes */
|
|
.blog-body blockquote {
|
|
border-left: 3px solid #60a5fa;
|
|
background: rgba(239, 246, 255, 0.6);
|
|
padding: 1.25rem 1.5rem;
|
|
border-radius: 0 0.75rem 0.75rem 0;
|
|
font-style: normal;
|
|
color: #1f2937;
|
|
}
|
|
|
|
.blog-body img {
|
|
border-radius: 1rem;
|
|
box-shadow: 0 20px 50px rgba(15, 23, 42, 0.08);
|
|
cursor: zoom-in;
|
|
transition: transform 0.2s;
|
|
}
|
|
|
|
.blog-body img:hover {
|
|
transform: scale(1.01);
|
|
}
|
|
|
|
.blog-body h2,
|
|
.blog-body h3,
|
|
.blog-body h4 {
|
|
scroll-margin-top: 7rem;
|
|
}
|
|
|
|
/* Links */
|
|
.blog-body a:not(.no-underline) {
|
|
text-decoration-color: rgba(59, 130, 246, 0.3);
|
|
text-underline-offset: 3px;
|
|
}
|
|
|
|
.blog-body a:not(.no-underline):hover {
|
|
text-decoration-color: rgba(59, 130, 246, 0.6);
|
|
}
|
|
|
|
@media (max-width: 1279px) {
|
|
.floating-share {
|
|
display: none !important;
|
|
}
|
|
}
|
|
|
|
/* Back to top button */
|
|
.back-to-top {
|
|
position: fixed;
|
|
bottom: 2rem;
|
|
left: 2rem;
|
|
width: 3rem;
|
|
height: 3rem;
|
|
border-radius: 9999px;
|
|
background: rgba(255, 255, 255, 0.95);
|
|
border: 1px solid rgba(148, 163, 184, 0.3);
|
|
box-shadow: 0 10px 40px rgba(15, 23, 42, 0.1);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
cursor: pointer;
|
|
opacity: 0;
|
|
visibility: hidden;
|
|
transform: translateY(10px);
|
|
transition: all 0.3s ease;
|
|
z-index: 50;
|
|
}
|
|
|
|
.back-to-top.visible {
|
|
opacity: 1;
|
|
visibility: visible;
|
|
transform: translateY(0);
|
|
}
|
|
|
|
.back-to-top:hover {
|
|
background: #fff;
|
|
border-color: #3b82f6;
|
|
transform: translateY(-3px);
|
|
box-shadow: 0 15px 50px rgba(59, 130, 246, 0.15);
|
|
}
|
|
|
|
.back-to-top svg {
|
|
width: 1.25rem;
|
|
height: 1.25rem;
|
|
color: #64748b;
|
|
transition: color 0.2s;
|
|
}
|
|
|
|
.back-to-top:hover svg {
|
|
color: #3b82f6;
|
|
}
|
|
|
|
/* Floating TOC */
|
|
.floating-toc {
|
|
position: absolute;
|
|
top: 0;
|
|
left: calc(100% + 2rem);
|
|
width: 200px;
|
|
max-height: 60vh;
|
|
z-index: 40;
|
|
}
|
|
|
|
.floating-toc.is-fixed {
|
|
position: fixed;
|
|
top: 50%;
|
|
left: calc(50% + 28rem);
|
|
transform: translateY(-50%);
|
|
width: 200px;
|
|
}
|
|
|
|
.floating-toc.is-bottom {
|
|
position: absolute;
|
|
top: auto;
|
|
bottom: 0;
|
|
left: calc(100% + 2rem);
|
|
transform: none;
|
|
width: 200px;
|
|
}
|
|
|
|
@media (min-width: 1280px) and (max-width: 1439px) {
|
|
.floating-toc {
|
|
width: 180px;
|
|
}
|
|
.floating-toc.is-fixed {
|
|
left: calc(50% + 24rem);
|
|
width: 180px;
|
|
}
|
|
.floating-toc.is-bottom {
|
|
width: 180px;
|
|
}
|
|
}
|
|
|
|
@media (min-width: 1440px) and (max-width: 1599px) {
|
|
.floating-toc {
|
|
width: 190px;
|
|
}
|
|
.floating-toc.is-fixed {
|
|
left: calc(50% + 26rem);
|
|
width: 190px;
|
|
}
|
|
.floating-toc.is-bottom {
|
|
width: 190px;
|
|
}
|
|
}
|
|
|
|
.floating-toc-inner {
|
|
background: rgba(255, 255, 255, 0.95);
|
|
backdrop-filter: blur(10px);
|
|
border: 1px solid rgba(148, 163, 184, 0.3);
|
|
border-radius: 1rem;
|
|
padding: 1rem;
|
|
box-shadow: 0 10px 40px rgba(15, 23, 42, 0.08);
|
|
}
|
|
|
|
.floating-toc-inner:hover {
|
|
box-shadow: 0 15px 50px rgba(15, 23, 42, 0.12);
|
|
border-color: rgba(59, 130, 246, 0.3);
|
|
}
|
|
|
|
/* TOC active state */
|
|
#toc a.toc-active {
|
|
color: #2563eb;
|
|
font-weight: 500;
|
|
}
|
|
|
|
#toc a {
|
|
position: relative;
|
|
padding-left: 0.75rem;
|
|
display: block;
|
|
padding-top: 0.25rem;
|
|
padding-bottom: 0.25rem;
|
|
font-size: 0.8125rem;
|
|
line-height: 1.4;
|
|
color: #64748b;
|
|
text-decoration: none;
|
|
transition: color 0.2s;
|
|
}
|
|
|
|
#toc a:hover {
|
|
color: #3b82f6;
|
|
}
|
|
|
|
#toc a::before {
|
|
content: '';
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0.35rem;
|
|
bottom: 0.35rem;
|
|
width: 2px;
|
|
background: transparent;
|
|
border-radius: 1px;
|
|
transition: background 0.2s;
|
|
}
|
|
|
|
#toc a.toc-active::before {
|
|
background: #3b82f6;
|
|
}
|
|
|
|
#toc a.toc-h3 {
|
|
padding-left: 1.25rem;
|
|
font-size: 0.75rem;
|
|
color: #94a3b8;
|
|
}
|
|
|
|
#toc a.toc-h3::before {
|
|
left: 0.5rem;
|
|
}
|
|
|
|
/* Smooth scroll behavior */
|
|
html {
|
|
scroll-behavior: smooth;
|
|
}
|
|
|
|
/* Heading anchor links */
|
|
.blog-body h2,
|
|
.blog-body h3,
|
|
.blog-body h4 {
|
|
position: relative;
|
|
}
|
|
|
|
.heading-anchor {
|
|
position: absolute;
|
|
left: -1.5rem;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
opacity: 0;
|
|
color: #94a3b8;
|
|
text-decoration: none;
|
|
font-size: 0.9em;
|
|
font-weight: 400;
|
|
transition: opacity 0.2s, color 0.2s;
|
|
line-height: 1;
|
|
}
|
|
|
|
.blog-body h2:hover .heading-anchor,
|
|
.blog-body h3:hover .heading-anchor,
|
|
.blog-body h4:hover .heading-anchor,
|
|
.heading-anchor:focus {
|
|
opacity: 1;
|
|
}
|
|
|
|
.heading-anchor:hover {
|
|
color: #3b82f6;
|
|
}
|
|
|
|
/* Collapsible code blocks */
|
|
.collapsible-code.collapsed {
|
|
max-height: 400px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.collapsible-code.collapsed::after {
|
|
content: '';
|
|
position: absolute;
|
|
bottom: 0;
|
|
left: 0;
|
|
right: 0;
|
|
height: 80px;
|
|
background: linear-gradient(to bottom, rgba(30, 30, 30, 0), rgba(30, 30, 30, 0.95));
|
|
border-radius: 0 0 0.75rem 0.75rem;
|
|
pointer-events: none;
|
|
z-index: 3;
|
|
}
|
|
|
|
.code-expand-btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.35rem;
|
|
margin-top: -0.5rem;
|
|
margin-bottom: 1.5rem;
|
|
padding: 0.35rem 1rem;
|
|
border: 1px solid rgba(148, 163, 184, 0.3);
|
|
border-radius: 9999px;
|
|
background: rgba(248, 250, 252, 1);
|
|
color: rgba(100, 116, 139, 1);
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
font-size: 12px;
|
|
font-weight: 500;
|
|
cursor: pointer;
|
|
transition: all 0.15s;
|
|
}
|
|
|
|
.code-expand-btn:hover {
|
|
background: rgba(241, 245, 249, 1);
|
|
border-color: rgba(148, 163, 184, 0.5);
|
|
color: #334155;
|
|
}
|
|
|
|
/* Image lightbox */
|
|
.blog-lightbox-overlay {
|
|
position: fixed;
|
|
inset: 0;
|
|
z-index: 100;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background: rgba(0, 0, 0, 0.85);
|
|
backdrop-filter: blur(8px);
|
|
opacity: 0;
|
|
visibility: hidden;
|
|
transition: opacity 0.25s, visibility 0.25s;
|
|
cursor: zoom-out;
|
|
}
|
|
|
|
.blog-lightbox-overlay.active {
|
|
opacity: 1;
|
|
visibility: visible;
|
|
}
|
|
|
|
.blog-lightbox-overlay img {
|
|
max-width: 90vw;
|
|
max-height: 90vh;
|
|
border-radius: 0.75rem;
|
|
box-shadow: 0 25px 80px rgba(0, 0, 0, 0.5);
|
|
transform: scale(0.95);
|
|
transition: transform 0.25s;
|
|
}
|
|
|
|
.blog-lightbox-overlay.active img {
|
|
transform: scale(1);
|
|
}
|
|
|
|
.blog-lightbox-close {
|
|
position: absolute;
|
|
top: 1.5rem;
|
|
right: 1.5rem;
|
|
width: 2.5rem;
|
|
height: 2.5rem;
|
|
border-radius: 9999px;
|
|
background: rgba(255, 255, 255, 0.1);
|
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
color: #fff;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
cursor: pointer;
|
|
transition: all 0.2s;
|
|
}
|
|
|
|
.blog-lightbox-close:hover {
|
|
background: rgba(255, 255, 255, 0.2);
|
|
}
|
|
|
|
/* Time remaining badge */
|
|
.time-remaining {
|
|
position: fixed;
|
|
bottom: 2rem;
|
|
right: 2rem;
|
|
z-index: 50;
|
|
padding: 0.4rem 0.75rem;
|
|
border-radius: 9999px;
|
|
background: rgba(255, 255, 255, 0.95);
|
|
border: 1px solid rgba(148, 163, 184, 0.3);
|
|
box-shadow: 0 10px 40px rgba(15, 23, 42, 0.1);
|
|
font-size: 12px;
|
|
font-weight: 500;
|
|
color: #64748b;
|
|
opacity: 0;
|
|
visibility: hidden;
|
|
transform: translateY(10px);
|
|
transition: all 0.3s ease;
|
|
backdrop-filter: blur(8px);
|
|
}
|
|
|
|
.time-remaining.visible {
|
|
opacity: 1;
|
|
visibility: visible;
|
|
transform: translateY(0);
|
|
}
|
|
|
|
/* Print styles */
|
|
@media print {
|
|
.reading-progress,
|
|
.back-to-top,
|
|
.floating-share,
|
|
.floating-toc,
|
|
.time-remaining,
|
|
.code-block-header,
|
|
.code-expand-btn,
|
|
.blog-lightbox-overlay,
|
|
nav,
|
|
footer,
|
|
.blog-cta-section {
|
|
display: none !important;
|
|
}
|
|
|
|
.blog-body pre {
|
|
border: 1px solid #ccc !important;
|
|
box-shadow: none !important;
|
|
max-height: none !important;
|
|
overflow: visible !important;
|
|
white-space: pre-wrap !important;
|
|
word-wrap: break-word !important;
|
|
}
|
|
|
|
.collapsible-code.collapsed {
|
|
max-height: none !important;
|
|
overflow: visible !important;
|
|
}
|
|
|
|
.collapsible-code.collapsed::after {
|
|
display: none !important;
|
|
}
|
|
|
|
.blog-body {
|
|
font-size: 12pt;
|
|
}
|
|
|
|
body {
|
|
background: #fff !important;
|
|
}
|
|
}
|
|
</style>
|
|
|
|
</head>
|
|
|
|
|
|
<body>
|
|
<div class="reading-progress" id="reading-progress"></div>
|
|
<!-- Back to top button -->
|
|
<button class="back-to-top" id="back-to-top" aria-label="Back to top" title="Back to top">
|
|
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 10l7-7m0 0l7 7m-7-7v18"/>
|
|
</svg>
|
|
</button>
|
|
|
|
<!-- Skip to main content link for accessibility -->
|
|
<a href="#main-content" class="sr-only focus:not-sr-only focus:absolute focus:top-4 focus:left-4 focus:z-50 focus:px-4 focus:py-2 focus:bg-gray-600 focus:text-white focus:rounded-md focus:outline-none focus:ring-2 focus:ring-gray-500">Skip to main content</a>
|
|
|
|
<header role="banner">
|
|
<div class="relative bg-white">
|
|
<div class="mx-auto max-w-7xl px-6">
|
|
<div class="flex items-center justify-between border-b-2 border-gray-100 py-6 md:justify-start md:space-x-10">
|
|
<div class="flex justify-start lg:w-0 lg:flex-1">
|
|
<a href="/">
|
|
<span class="sr-only">OneUptime</span>
|
|
<img class="h-8 w-auto sm:h-10" src="/img/3-transparent.svg" alt="OneUptime logo" width="140" height="40" fetchpriority="high">
|
|
</a>
|
|
</div>
|
|
<div class="-my-2 -mr-2 md:hidden">
|
|
<button type="button" onclick="openMobileMenu()"
|
|
class="inline-flex items-center justify-center rounded-md bg-white p-2 text-gray-400 hover:bg-gray-100 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-gray-500"
|
|
aria-expanded="false">
|
|
<span class="sr-only">Open menu</span>
|
|
<!-- Heroicon name: outline/bars-3 -->
|
|
<svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
|
|
stroke="currentColor" aria-hidden="true">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
<nav class="hidden space-x-10 md:flex">
|
|
<div class="relative">
|
|
<!-- Opens the searchable products modal (command-palette style). -->
|
|
<button onclick="openProductModal()" type="button"
|
|
class="text-gray-500 group inline-flex items-center rounded-md bg-white text-base font-medium hover:text-gray-900 focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2"
|
|
aria-haspopup="dialog" aria-expanded="false">
|
|
<span>Products</span>
|
|
<svg class="text-gray-400 ml-2 h-5 w-5 group-hover:text-gray-500" xmlns="http://www.w3.org/2000/svg"
|
|
viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
|
<path fill-rule="evenodd"
|
|
d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z"
|
|
clip-rule="evenodd" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Enterprise Dropdown -->
|
|
<div class="relative" onmouseenter="showSolutionsMenu()" onmouseover="showSolutionsMenu()" onmouseleave="hideSolutionsMenu()">
|
|
<button onclick="showSolutionsMenu()" type="button"
|
|
class="text-gray-500 group inline-flex items-center rounded-md bg-white text-base font-medium hover:text-gray-900 focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2"
|
|
aria-expanded="false">
|
|
<span>Enterprise</span>
|
|
<svg class="text-gray-400 ml-2 h-5 w-5 group-hover:text-gray-500" xmlns="http://www.w3.org/2000/svg"
|
|
viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
|
<path fill-rule="evenodd"
|
|
d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z"
|
|
clip-rule="evenodd" />
|
|
</svg>
|
|
</button>
|
|
|
|
<div onmouseenter="showSolutionsMenu()" onmouseover="showSolutionsMenu()" onmouseleave="hideSolutionsMenu()"
|
|
class="absolute z-20 -ml-4 pt-3 w-screen max-w-4xl transform px-2 sm:px-0 lg:left-1/2 lg:ml-0 lg:-translate-x-1/2"
|
|
id="solutions-menu" hidden style="visibility: collapse; opacity: 0;">
|
|
<div class="overflow-hidden rounded-2xl shadow-2xl ring-1 ring-gray-900/5 bg-white">
|
|
<div class="flex">
|
|
<!-- Left Column - Dark Featured Section -->
|
|
<div class="w-72 bg-gray-900 p-6 flex flex-col">
|
|
<div class="flex-1">
|
|
<p class="text-[10px] font-medium uppercase tracking-widest text-gray-500 mb-2">Enterprise</p>
|
|
<h2 class="text-xl font-semibold text-white leading-snug">Built for how you work</h2>
|
|
<p class="text-sm text-gray-400 mt-2 leading-relaxed">Scale your reliability operations with enterprise-grade tools.</p>
|
|
</div>
|
|
|
|
<div class="space-y-2 mt-6">
|
|
<a href="/enterprise/overview" class="group flex items-center gap-3 p-3 rounded-lg bg-white/5 hover:bg-white/10 transition-colors">
|
|
<div class="w-9 h-9 rounded-lg bg-white/10 flex items-center justify-center">
|
|
<svg class="h-4.5 w-4.5 text-white" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 21h19.5m-18-18v18m10.5-18v18m6-13.5V21M6.75 6.75h.75m-.75 3h.75m-.75 3h.75m3-6h.75m-.75 3h.75m-.75 3h.75M6.75 21v-3.375c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21M3 3h12m-.75 4.5H21m-3.75 3h.008v.008h-.008v-.008zm0 3h.008v.008h-.008v-.008zm0 3h.008v.008h-.008v-.008z"></path>
|
|
</svg>
|
|
</div>
|
|
<div class="flex-1">
|
|
<p class="text-sm font-medium text-white">Enterprise Overview</p>
|
|
<p class="text-xs text-gray-500">Scale with confidence</p>
|
|
</div>
|
|
</a>
|
|
<a href="/enterprise/self-hosted" class="group flex items-center gap-3 p-3 rounded-lg bg-white/5 hover:bg-white/10 transition-colors">
|
|
<div class="w-9 h-9 rounded-lg bg-white/10 flex items-center justify-center">
|
|
<svg class="h-4.5 w-4.5 text-white" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M5.25 14.25h13.5m-13.5 0a3 3 0 0 1-3-3m3 3a3 3 0 1 0 0 6h13.5a3 3 0 1 0 0-6m-16.5-3a3 3 0 0 1 3-3h13.5a3 3 0 0 1 3 3m-19.5 0a4.5 4.5 0 0 1 .9-2.7L5.7 5.1a3 3 0 0 1 2.4-1.2h7.8a3 3 0 0 1 2.4 1.2l2.55 3.45a4.5 4.5 0 0 1 .9 2.7"></path>
|
|
</svg>
|
|
</div>
|
|
<div class="flex-1">
|
|
<p class="text-sm font-medium text-white">Self-Hosted</p>
|
|
<p class="text-xs text-gray-500">Run it on your own infrastructure</p>
|
|
</div>
|
|
</a>
|
|
<a href="/enterprise/demo" class="group flex items-center gap-3 p-3 rounded-lg bg-white/5 hover:bg-white/10 transition-colors" data-testid="request-demo-desktop-link">
|
|
<div class="w-9 h-9 rounded-lg bg-white/10 flex items-center justify-center">
|
|
<svg class="h-4.5 w-4.5 text-white" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.348a1.125 1.125 0 010 1.971l-11.54 6.347a1.125 1.125 0 01-1.667-.985V5.653z"></path>
|
|
</svg>
|
|
</div>
|
|
<div class="flex-1">
|
|
<p class="text-sm font-medium text-white">Request Demo</p>
|
|
<p class="text-xs text-gray-500">See it in action</p>
|
|
</div>
|
|
</a>
|
|
</div>
|
|
|
|
<div class="mt-6 pt-5 border-t border-white/10">
|
|
<a href="/legal/contact" class="inline-flex items-center gap-2 text-sm font-medium text-white hover:text-gray-300 transition-colors">
|
|
Contact Sales
|
|
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M13.5 4.5L21 12m0 0l-7.5 7.5M21 12H3"></path>
|
|
</svg>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Right Column - Main Content -->
|
|
<div class="flex-1 p-6">
|
|
<!-- Enterprise -->
|
|
<div class="mb-6">
|
|
<p class="text-[10px] font-semibold uppercase tracking-widest text-gray-400 mb-3">Enterprise</p>
|
|
<div class="grid grid-cols-2 gap-1">
|
|
<a href="/enterprise/overview" class="group flex items-center gap-3 p-2.5 -mx-2.5 rounded-lg hover:bg-gray-50 transition-colors">
|
|
<div class="w-8 h-8 rounded-md bg-indigo-50 flex items-center justify-center flex-shrink-0">
|
|
<svg class="h-4 w-4 text-indigo-600" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 21h16.5M4.5 3h15M5.25 3v18m13.5-18v18M9 6.75h1.5m-1.5 3h1.5m-1.5 3h1.5m3-6H15m-1.5 3H15m-1.5 3H15M9 21v-3.375c0-.621.504-1.125 1.125-1.125h3.75c.621 0 1.125.504 1.125 1.125V21"></path>
|
|
</svg>
|
|
</div>
|
|
<div>
|
|
<p class="text-sm font-medium text-gray-900 group-hover:text-gray-700">Enterprise Overview</p>
|
|
<p class="text-xs text-gray-500">Solutions for large organizations</p>
|
|
</div>
|
|
</a>
|
|
<a href="/enterprise/self-hosted" class="group flex items-center gap-3 p-2.5 -mx-2.5 rounded-lg hover:bg-gray-50 transition-colors">
|
|
<div class="w-8 h-8 rounded-md bg-teal-50 flex items-center justify-center flex-shrink-0">
|
|
<svg class="h-4 w-4 text-teal-600" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M5.25 14.25h13.5m-13.5 0a3 3 0 0 1-3-3m3 3a3 3 0 1 0 0 6h13.5a3 3 0 1 0 0-6m-16.5-3a3 3 0 0 1 3-3h13.5a3 3 0 0 1 3 3"></path>
|
|
</svg>
|
|
</div>
|
|
<div>
|
|
<p class="text-sm font-medium text-gray-900 group-hover:text-gray-700">Self-Hosted</p>
|
|
<p class="text-xs text-gray-500">Deployment, architecture, support</p>
|
|
</div>
|
|
</a>
|
|
<a href="/trust" class="group flex items-center gap-3 p-2.5 -mx-2.5 rounded-lg hover:bg-gray-50 transition-colors">
|
|
<div class="w-8 h-8 rounded-md bg-blue-50 flex items-center justify-center flex-shrink-0">
|
|
<svg class="h-4 w-4 text-blue-600" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75 11.25 15 15 9.75m-3-7.036A11.959 11.959 0 0 1 3.598 6 11.99 11.99 0 0 0 3 9.749c0 5.592 3.824 10.29 9 11.623 5.176-1.332 9-6.03 9-11.622 0-1.31-.21-2.571-.598-3.751h-.152c-3.196 0-6.1-1.248-8.25-3.285Z"></path>
|
|
</svg>
|
|
</div>
|
|
<div>
|
|
<p class="text-sm font-medium text-gray-900 group-hover:text-gray-700">Trust Center</p>
|
|
<p class="text-xs text-gray-500">Certifications, evidence, governed claims</p>
|
|
</div>
|
|
</a>
|
|
<a href="/enterprise/demo" class="group flex items-center gap-3 p-2.5 -mx-2.5 rounded-lg hover:bg-gray-50 transition-colors">
|
|
<div class="w-8 h-8 rounded-md bg-emerald-50 flex items-center justify-center flex-shrink-0">
|
|
<svg class="h-4 w-4 text-emerald-600" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 012.25-2.25h13.5A2.25 2.25 0 0121 7.5v11.25m-18 0A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75m-18 0v-7.5A2.25 2.25 0 015.25 9h13.5A2.25 2.25 0 0121 11.25v7.5"></path>
|
|
</svg>
|
|
</div>
|
|
<div>
|
|
<p class="text-sm font-medium text-gray-900 group-hover:text-gray-700">Request Demo</p>
|
|
<p class="text-xs text-gray-500">Schedule a personalized demo</p>
|
|
</div>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Teams -->
|
|
<div class="pt-5 border-t border-gray-100">
|
|
<p class="text-[10px] font-semibold uppercase tracking-widest text-gray-400 mb-3">Teams</p>
|
|
<div class="grid grid-cols-4 gap-2">
|
|
<a href="/solutions/devops" class="group flex flex-col items-center gap-2 p-3 rounded-xl border border-gray-100 hover:border-gray-200 hover:bg-gray-50 transition-all">
|
|
<div class="w-10 h-10 rounded-lg bg-cyan-50 flex items-center justify-center">
|
|
<svg class="h-5 w-5 text-cyan-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M5.25 14.25h13.5m-13.5 0a3 3 0 01-3-3m3 3a3 3 0 100 6h13.5a3 3 0 100-6m-16.5-3a3 3 0 013-3h13.5a3 3 0 013 3m-19.5 0a4.5 4.5 0 01.9-2.7L5.737 5.1a3.375 3.375 0 012.7-1.35h7.126c1.062 0 2.062.5 2.7 1.35l2.587 3.45a4.5 4.5 0 01.9 2.7"></path>
|
|
</svg>
|
|
</div>
|
|
<span class="text-xs font-medium text-gray-700 group-hover:text-gray-900">DevOps</span>
|
|
</a>
|
|
<a href="/solutions/sre" class="group flex flex-col items-center gap-2 p-3 rounded-xl border border-gray-100 hover:border-gray-200 hover:bg-gray-50 transition-all">
|
|
<div class="w-10 h-10 rounded-lg bg-violet-50 flex items-center justify-center">
|
|
<svg class="h-5 w-5 text-violet-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75m-3-7.036A11.959 11.959 0 013.598 6 11.99 11.99 0 003 9.749c0 5.592 3.824 10.29 9 11.623 5.176-1.332 9-6.03 9-11.622 0-1.31-.21-2.571-.598-3.751h-.152c-3.196 0-6.1-1.248-8.25-3.285z"></path>
|
|
</svg>
|
|
</div>
|
|
<span class="text-xs font-medium text-gray-700 group-hover:text-gray-900">SRE</span>
|
|
</a>
|
|
<a href="/solutions/platform" class="group flex flex-col items-center gap-2 p-3 rounded-xl border border-gray-100 hover:border-gray-200 hover:bg-gray-50 transition-all">
|
|
<div class="w-10 h-10 rounded-lg bg-amber-50 flex items-center justify-center">
|
|
<svg class="h-5 w-5 text-amber-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M6.429 9.75L2.25 12l4.179 2.25m0-4.5l5.571 3 5.571-3m-11.142 0L2.25 7.5 12 2.25l9.75 5.25-4.179 2.25m0 4.5l4.179-2.25L12 21.75 2.25 12l4.179 2.25"></path>
|
|
</svg>
|
|
</div>
|
|
<span class="text-xs font-medium text-gray-700 group-hover:text-gray-900">Platform</span>
|
|
</a>
|
|
<a href="/solutions/developers" class="group flex flex-col items-center gap-2 p-3 rounded-xl border border-gray-100 hover:border-gray-200 hover:bg-gray-50 transition-all">
|
|
<div class="w-10 h-10 rounded-lg bg-emerald-50 flex items-center justify-center">
|
|
<svg class="h-5 w-5 text-emerald-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M17.25 6.75L22.5 12l-5.25 5.25m-10.5 0L1.5 12l5.25-5.25m7.5-3l-4.5 16.5"></path>
|
|
</svg>
|
|
</div>
|
|
<span class="text-xs font-medium text-gray-700 group-hover:text-gray-900">Developers</span>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Industries -->
|
|
<div class="pt-5 mt-5 border-t border-gray-100">
|
|
<p class="text-[10px] font-semibold uppercase tracking-widest text-gray-400 mb-3">Industries</p>
|
|
<div class="grid grid-cols-3 gap-2">
|
|
<a href="/industries/fintech" class="group flex items-center gap-3 p-2.5 rounded-lg border border-gray-100 hover:border-gray-200 hover:bg-gray-50 transition-all">
|
|
<div class="w-8 h-8 rounded-md bg-green-50 flex items-center justify-center flex-shrink-0">
|
|
<svg class="h-4 w-4 text-green-600" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6v12m-3-2.818l.879.659c1.171.879 3.07.879 4.242 0 1.172-.879 1.172-2.303 0-3.182C13.536 12.219 12.768 12 12 12c-.725 0-1.45-.22-2.003-.659-1.106-.879-1.106-2.303 0-3.182s2.9-.879 4.006 0l.415.33M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
|
</svg>
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-700 group-hover:text-gray-900">FinTech</span>
|
|
</a>
|
|
<a href="/industries/saas" class="group flex items-center gap-3 p-2.5 rounded-lg border border-gray-100 hover:border-gray-200 hover:bg-gray-50 transition-all">
|
|
<div class="w-8 h-8 rounded-md bg-blue-50 flex items-center justify-center flex-shrink-0">
|
|
<svg class="h-4 w-4 text-blue-600" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 15a4.5 4.5 0 004.5 4.5H18a3.75 3.75 0 001.332-7.257 3 3 0 00-3.758-3.848 5.25 5.25 0 00-10.233 2.33A4.502 4.502 0 002.25 15z"></path>
|
|
</svg>
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-700 group-hover:text-gray-900">SaaS</span>
|
|
</a>
|
|
<a href="/industries/healthcare" class="group flex items-center gap-3 p-2.5 rounded-lg border border-gray-100 hover:border-gray-200 hover:bg-gray-50 transition-all">
|
|
<div class="w-8 h-8 rounded-md bg-red-50 flex items-center justify-center flex-shrink-0">
|
|
<svg class="h-4 w-4 text-red-600" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12z"></path>
|
|
</svg>
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-700 group-hover:text-gray-900">Healthcare</span>
|
|
</a>
|
|
<a href="/industries/ecommerce" class="group flex items-center gap-3 p-2.5 rounded-lg border border-gray-100 hover:border-gray-200 hover:bg-gray-50 transition-all">
|
|
<div class="w-8 h-8 rounded-md bg-orange-50 flex items-center justify-center flex-shrink-0">
|
|
<svg class="h-4 w-4 text-orange-600" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 3h1.386c.51 0 .955.343 1.087.835l.383 1.437M7.5 14.25a3 3 0 00-3 3h15.75m-12.75-3h11.218c1.121-2.3 2.1-4.684 2.924-7.138a60.114 60.114 0 00-16.536-1.84M7.5 14.25L5.106 5.272M6 20.25a.75.75 0 11-1.5 0 .75.75 0 011.5 0zm12.75 0a.75.75 0 11-1.5 0 .75.75 0 011.5 0z"></path>
|
|
</svg>
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-700 group-hover:text-gray-900">E-Commerce</span>
|
|
</a>
|
|
<a href="/industries/media" class="group flex items-center gap-3 p-2.5 rounded-lg border border-gray-100 hover:border-gray-200 hover:bg-gray-50 transition-all">
|
|
<div class="w-8 h-8 rounded-md bg-purple-50 flex items-center justify-center flex-shrink-0">
|
|
<svg class="h-4 w-4 text-purple-600" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.348a1.125 1.125 0 010 1.971l-11.54 6.347a1.125 1.125 0 01-1.667-.985V5.653z"></path>
|
|
</svg>
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-700 group-hover:text-gray-900">Media</span>
|
|
</a>
|
|
<a href="/industries/government" class="group flex items-center gap-3 p-2.5 rounded-lg border border-gray-100 hover:border-gray-200 hover:bg-gray-50 transition-all">
|
|
<div class="w-8 h-8 rounded-md bg-slate-100 flex items-center justify-center flex-shrink-0">
|
|
<svg class="h-4 w-4 text-slate-600" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 21v-8.25M15.75 21v-8.25M8.25 21v-8.25M3 9l9-6 9 6m-1.5 12V10.332A48.36 48.36 0 0012 9.75c-2.551 0-5.056.2-7.5.582V21M3 21h18M12 6.75h.008v.008H12V6.75z"></path>
|
|
</svg>
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-700 group-hover:text-gray-900">Government</span>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Footer -->
|
|
<div class="px-6 py-3 bg-gray-50 border-t border-gray-100 flex items-center justify-between">
|
|
<div class="flex items-center gap-5">
|
|
<a href="/docs" class="text-sm text-gray-500 hover:text-gray-900 transition-colors">Documentation</a>
|
|
<a href="/pricing" class="text-sm text-gray-500 hover:text-gray-900 transition-colors">Pricing</a>
|
|
<a href="/blog" class="text-sm text-gray-500 hover:text-gray-900 transition-colors">Blog</a>
|
|
</div>
|
|
<a href="/accounts/register" class="inline-flex items-center gap-1.5 text-sm font-medium text-gray-900 hover:text-gray-600 transition-colors">
|
|
Get Started Free
|
|
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M13.5 4.5L21 12m0 0l-7.5 7.5M21 12H3"></path>
|
|
</svg>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<a href="/pricing" class="text-base font-medium text-gray-500 hover:text-gray-900">Pricing</a>
|
|
|
|
<!-- Resources Dropdown -->
|
|
<div class="relative" onmouseenter="showResourcesMenu()" onmouseover="showResourcesMenu()" onmouseleave="hideResourcesMenu()">
|
|
<button onclick="showResourcesMenu()" type="button"
|
|
class="text-gray-500 group inline-flex items-center rounded-md bg-white text-base font-medium hover:text-gray-900 focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2"
|
|
aria-expanded="false">
|
|
<span>Resources</span>
|
|
<svg class="text-gray-400 ml-2 h-5 w-5 group-hover:text-gray-500" xmlns="http://www.w3.org/2000/svg"
|
|
viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
|
<path fill-rule="evenodd"
|
|
d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z"
|
|
clip-rule="evenodd" />
|
|
</svg>
|
|
</button>
|
|
|
|
<div onmouseenter="showResourcesMenu()" onmouseover="showResourcesMenu()" onmouseleave="hideResourcesMenu()" id="resources-menu" hidden
|
|
class="absolute right-0 z-20 pt-3 w-screen max-w-3xl transform px-2 sm:px-0"
|
|
style="visibility: collapse; opacity: 0;">
|
|
<div class="overflow-hidden rounded-2xl shadow-2xl ring-1 ring-gray-900/5 bg-white">
|
|
<div class="flex">
|
|
<!-- Left Column - Dark Featured Section -->
|
|
<div class="w-64 bg-gray-900 p-6 flex flex-col">
|
|
<div class="flex-1">
|
|
<p class="text-[10px] font-medium uppercase tracking-widest text-gray-500 mb-2">Resources</p>
|
|
<h2 class="text-xl font-semibold text-white leading-snug">Learn & Connect</h2>
|
|
<p class="text-sm text-gray-400 mt-2 leading-relaxed">Everything you need to get started and succeed.</p>
|
|
</div>
|
|
|
|
<div class="space-y-2 mt-6">
|
|
<a href="/docs" class="group flex items-center gap-3 p-3 rounded-lg bg-white/5 hover:bg-white/10 transition-colors">
|
|
<div class="w-9 h-9 rounded-lg bg-white/10 flex items-center justify-center">
|
|
<svg class="h-4.5 w-4.5 text-white" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6.042A8.967 8.967 0 006 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 016 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 016-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0018 18a8.967 8.967 0 00-6 2.292m0-14.25v14.25"></path>
|
|
</svg>
|
|
</div>
|
|
<div class="flex-1">
|
|
<p class="text-sm font-medium text-white">Documentation</p>
|
|
<p class="text-xs text-gray-500">Guides & tutorials</p>
|
|
</div>
|
|
</a>
|
|
<a href="/reference" class="group flex items-center gap-3 p-3 rounded-lg bg-white/5 hover:bg-white/10 transition-colors">
|
|
<div class="w-9 h-9 rounded-lg bg-white/10 flex items-center justify-center">
|
|
<svg class="h-4.5 w-4.5 text-white" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="m6.75 7.5 3 2.25-3 2.25m4.5 0h3m-9 8.25h13.5A2.25 2.25 0 0021 18V6a2.25 2.25 0 00-2.25-2.25H5.25A2.25 2.25 0 003 6v12a2.25 2.25 0 002.25 2.25z"></path>
|
|
</svg>
|
|
</div>
|
|
<div class="flex-1">
|
|
<p class="text-sm font-medium text-white">API Reference</p>
|
|
<p class="text-xs text-gray-500">REST API & SDKs</p>
|
|
</div>
|
|
</a>
|
|
</div>
|
|
|
|
<div class="mt-6 pt-5 border-t border-white/10">
|
|
<a href="https://github.com/oneuptime/oneuptime" target="_blank" class="inline-flex items-center gap-2 text-sm font-medium text-white hover:text-gray-300 transition-colors">
|
|
<svg class="h-4 w-4" fill="currentColor" viewBox="0 0 24 24">
|
|
<path fill-rule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" clip-rule="evenodd"></path>
|
|
</svg>
|
|
Star on GitHub
|
|
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M13.5 4.5L21 12m0 0l-7.5 7.5M21 12H3"></path>
|
|
</svg>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Right Column - Main Content -->
|
|
<div class="flex-1 p-6">
|
|
<!-- Learn Section -->
|
|
<div class="mb-6">
|
|
<p class="text-[10px] font-semibold uppercase tracking-widest text-gray-400 mb-3">Learn</p>
|
|
<div class="grid grid-cols-2 gap-1">
|
|
<a href="/blog" class="group flex items-center gap-3 p-2.5 -mx-2.5 rounded-lg hover:bg-gray-50 transition-colors">
|
|
<div class="w-8 h-8 rounded-md bg-amber-50 flex items-center justify-center flex-shrink-0">
|
|
<svg class="h-4 w-4 text-amber-600" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 7.5h1.5m-1.5 3h1.5m-7.5 3h7.5m-7.5 3h7.5m3-9h3.375c.621 0 1.125.504 1.125 1.125V18a2.25 2.25 0 01-2.25 2.25M16.5 7.5V18a2.25 2.25 0 002.25 2.25M16.5 7.5V4.875c0-.621-.504-1.125-1.125-1.125H4.125C3.504 3.75 3 4.254 3 4.875V18a2.25 2.25 0 002.25 2.25h13.5M6 7.5h3v3H6v-3z"></path>
|
|
</svg>
|
|
</div>
|
|
<div>
|
|
<p class="text-sm font-medium text-gray-900 group-hover:text-gray-700">Blog</p>
|
|
<p class="text-xs text-gray-500">News & insights</p>
|
|
</div>
|
|
</a>
|
|
<a href="/books" class="group flex items-center gap-3 p-2.5 -mx-2.5 rounded-lg hover:bg-gray-50 transition-colors">
|
|
<div class="w-8 h-8 rounded-md bg-amber-50 flex items-center justify-center flex-shrink-0">
|
|
<svg class="h-4 w-4 text-amber-600" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24" aria-hidden="true">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6.042A8.967 8.967 0 006 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 016 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 016-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0018 18a8.967 8.967 0 00-6 2.292m0-14.25v14.25"></path>
|
|
</svg>
|
|
</div>
|
|
<div>
|
|
<p class="text-sm font-medium text-gray-900 group-hover:text-gray-700">Books</p>
|
|
<p class="text-xs text-gray-500">Ideas for better infrastructure</p>
|
|
</div>
|
|
</a>
|
|
<a href="https://status.oneuptime.com" target="_blank" class="group flex items-center gap-3 p-2.5 -mx-2.5 rounded-lg hover:bg-gray-50 transition-colors">
|
|
<div class="w-8 h-8 rounded-md bg-emerald-50 flex items-center justify-center flex-shrink-0">
|
|
<svg class="h-4 w-4 text-emerald-600" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
|
</svg>
|
|
</div>
|
|
<div>
|
|
<p class="text-sm font-medium text-gray-900 group-hover:text-gray-700">Status</p>
|
|
<p class="text-xs text-gray-500">System status</p>
|
|
</div>
|
|
</a>
|
|
<a href="https://github.com/OneUptime/oneuptime/releases" target="_blank" class="group flex items-center gap-3 p-2.5 -mx-2.5 rounded-lg hover:bg-gray-50 transition-colors">
|
|
<div class="w-8 h-8 rounded-md bg-emerald-50 flex items-center justify-center flex-shrink-0">
|
|
<svg class="h-4 w-4 text-emerald-600" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0l3.181 3.183a8.25 8.25 0 0013.803-3.7M4.031 9.865a8.25 8.25 0 0113.803-3.7l3.181 3.182m0-4.991v4.99"></path>
|
|
</svg>
|
|
</div>
|
|
<div>
|
|
<p class="text-sm font-medium text-gray-900 group-hover:text-gray-700">Changelog</p>
|
|
<p class="text-xs text-gray-500">What's new</p>
|
|
</div>
|
|
</a>
|
|
<a href="https://www.youtube.com/@OneUptimehq" target="_blank" class="group flex items-center gap-3 p-2.5 -mx-2.5 rounded-lg hover:bg-gray-50 transition-colors">
|
|
<div class="w-8 h-8 rounded-md bg-rose-50 flex items-center justify-center flex-shrink-0">
|
|
<svg class="h-4 w-4 text-rose-600" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.348a1.125 1.125 0 010 1.971l-11.54 6.347a1.125 1.125 0 01-1.667-.985V5.653z"></path>
|
|
</svg>
|
|
</div>
|
|
<div>
|
|
<p class="text-sm font-medium text-gray-900 group-hover:text-gray-700">Videos</p>
|
|
<p class="text-xs text-gray-500">Watch & learn</p>
|
|
</div>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Support & Company -->
|
|
<div class="grid grid-cols-2 gap-6 pt-5 border-t border-gray-100">
|
|
<!-- Support -->
|
|
<div>
|
|
<p class="text-[10px] font-semibold uppercase tracking-widest text-gray-400 mb-3">Support</p>
|
|
<div class="grid grid-cols-1 gap-2">
|
|
<a href="/support" class="group flex items-center gap-3 p-2.5 rounded-lg border border-gray-100 hover:border-gray-200 hover:bg-gray-50 transition-all">
|
|
<div class="w-8 h-8 rounded-md bg-sky-50 flex items-center justify-center flex-shrink-0">
|
|
<svg class="h-4 w-4 text-sky-600" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M9.879 7.519c1.171-1.025 3.071-1.025 4.242 0 1.172 1.025 1.172 2.687 0 3.712-.203.179-.43.326-.67.442-.745.361-1.45.999-1.45 1.827v.75M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9 5.25h.008v.008H12v-.008z"></path>
|
|
</svg>
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-700 group-hover:text-gray-900">Help Center</span>
|
|
</a>
|
|
<a href="/cdn-cgi/l/email-protection#f88b8d8888978a8cb897969d8d888c91959dd69b9795" class="group flex items-center gap-3 p-2.5 rounded-lg border border-gray-100 hover:border-gray-200 hover:bg-gray-50 transition-all">
|
|
<div class="w-8 h-8 rounded-md bg-indigo-50 flex items-center justify-center flex-shrink-0">
|
|
<svg class="h-4 w-4 text-indigo-600" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M21.75 6.75v10.5a2.25 2.25 0 01-2.25 2.25h-15a2.25 2.25 0 01-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0019.5 4.5h-15a2.25 2.25 0 00-2.25 2.25m19.5 0v.243a2.25 2.25 0 01-1.07 1.916l-7.5 4.615a2.25 2.25 0 01-2.36 0L3.32 8.91a2.25 2.25 0 01-1.07-1.916V6.75"></path>
|
|
</svg>
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-700 group-hover:text-gray-900">Contact Us</span>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Company -->
|
|
<div>
|
|
<p class="text-[10px] font-semibold uppercase tracking-widest text-gray-400 mb-3">Company</p>
|
|
<div class="grid grid-cols-1 gap-2">
|
|
<a href="/about" class="group flex items-center gap-3 p-2.5 rounded-lg border border-gray-100 hover:border-gray-200 hover:bg-gray-50 transition-all">
|
|
<div class="w-8 h-8 rounded-md bg-slate-100 flex items-center justify-center flex-shrink-0">
|
|
<svg class="h-4 w-4 text-slate-600" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M18 18.72a9.094 9.094 0 003.741-.479 3 3 0 00-4.682-2.72m.94 3.198l.001.031c0 .225-.012.447-.037.666A11.944 11.944 0 0112 21c-2.17 0-4.207-.576-5.963-1.584A6.062 6.062 0 016 18.719m12 0a5.971 5.971 0 00-.941-3.197m0 0A5.995 5.995 0 0012 12.75a5.995 5.995 0 00-5.058 2.772m0 0a3 3 0 00-4.681 2.72 8.986 8.986 0 003.74.477m.94-3.197a5.971 5.971 0 00-.94 3.197M15 6.75a3 3 0 11-6 0 3 3 0 016 0zm6 3a2.25 2.25 0 11-4.5 0 2.25 2.25 0 014.5 0zm-13.5 0a2.25 2.25 0 11-4.5 0 2.25 2.25 0 014.5 0z"></path>
|
|
</svg>
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-700 group-hover:text-gray-900">About Us</span>
|
|
</a>
|
|
<a href="https://shop.oneuptime.com" target="_blank" class="group flex items-center gap-3 p-2.5 rounded-lg border border-gray-100 hover:border-gray-200 hover:bg-gray-50 transition-all">
|
|
<div class="w-8 h-8 rounded-md bg-pink-50 flex items-center justify-center flex-shrink-0">
|
|
<svg class="h-4 w-4 text-pink-600" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 10.5V6a3.75 3.75 0 10-7.5 0v4.5m11.356-1.993l1.263 12c.07.665-.45 1.243-1.119 1.243H4.25a1.125 1.125 0 01-1.12-1.243l1.264-12A1.125 1.125 0 015.513 7.5h12.974c.576 0 1.059.435 1.119 1.007zM8.625 10.5a.375.375 0 11-.75 0 .375.375 0 01.75 0zm7.5 0a.375.375 0 11-.75 0 .375.375 0 01.75 0z"></path>
|
|
</svg>
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-700 group-hover:text-gray-900">Merch Store</span>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Footer -->
|
|
<div class="px-6 py-3 bg-gray-50 border-t border-gray-100 flex items-center justify-between">
|
|
<div class="flex items-center gap-5">
|
|
<a href="/legal" class="text-sm text-gray-500 hover:text-gray-900 transition-colors">Legal</a>
|
|
<a href="/legal/privacy" class="text-sm text-gray-500 hover:text-gray-900 transition-colors">Privacy</a>
|
|
<a href="/legal/terms" class="text-sm text-gray-500 hover:text-gray-900 transition-colors">Terms</a>
|
|
</div>
|
|
<span class="text-sm text-gray-500">100% Open Source</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
<div class="hidden items-center justify-end md:flex md:flex-1 lg:w-0">
|
|
<a href="/accounts" class="whitespace-nowrap text-base font-medium text-gray-500 hover:text-gray-900">Sign
|
|
in</a>
|
|
<a href="/accounts/register"
|
|
class="ml-8 inline-flex items-center justify-center whitespace-nowrap rounded-md border border-transparent bg-gray-900 px-4 py-2 text-base font-medium text-white shadow-sm hover:bg-gray-900 hover:text-white"
|
|
data-testid="Sign-up">Sign up</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!--
|
|
Mobile menu, show/hide based on mobile menu state.
|
|
|
|
Entering: "duration-200 ease-out"
|
|
From: "opacity-0 scale-95"
|
|
To: "opacity-100 scale-100"
|
|
Leaving: "duration-100 ease-in"
|
|
From: "opacity-100 scale-100"
|
|
To: "opacity-0 scale-95"
|
|
-->
|
|
|
|
<div id="mobile-menu" hidden class="absolute inset-x-0 top-0 origin-top-right transform p-2 transition md:hidden z-20"
|
|
style="visibility: collapse;">
|
|
<div class="divide-y-2 divide-gray-50 rounded-lg bg-white shadow-lg ring-1 ring-black ring-opacity-5">
|
|
<div class="px-5 pt-5 pb-6">
|
|
<div class="flex items-center justify-between">
|
|
<div>
|
|
<img class="h-8 w-auto" src="/img/3-transparent.svg" alt="OneUptime">
|
|
</div>
|
|
<div class="-mr-2">
|
|
<button type="button"
|
|
class="inline-flex items-center justify-center rounded-md bg-white p-2 text-gray-400 hover:bg-gray-100 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-gray-500"
|
|
onclick="closeMobileMenu()">
|
|
<span class="sr-only">Close menu</span>
|
|
<!-- Heroicon name: outline/x-mark -->
|
|
<svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
|
|
stroke="currentColor" aria-hidden="true">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="mt-6">
|
|
<nav class="grid grid-cols-2 gap-3">
|
|
<!-- Status Page - Emerald -->
|
|
<a href="/product/status-page" class="flex items-center gap-3 rounded-xl p-3 hover:bg-emerald-50 ring-1 ring-transparent hover:ring-emerald-200">
|
|
<div class="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-emerald-50 ring-1 ring-emerald-200">
|
|
<!-- Status Page Icon - Checkmark in circle -->
|
|
<svg class="h-4 w-4 text-emerald-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-900">Status Page</span>
|
|
</a>
|
|
|
|
<!-- Incidents - Rose -->
|
|
<a href="/product/incident-management" class="flex items-center gap-3 rounded-xl p-3 hover:bg-rose-50 ring-1 ring-transparent hover:ring-rose-200">
|
|
<div class="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-rose-50 ring-1 ring-rose-200">
|
|
<!-- Incidents Icon - Warning triangle -->
|
|
<svg class="h-4 w-4 text-rose-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-900">Incidents</span>
|
|
</a>
|
|
|
|
<!-- Monitoring - Blue -->
|
|
<a href="/product/monitoring" class="flex items-center gap-3 rounded-xl p-3 hover:bg-blue-50 ring-1 ring-transparent hover:ring-blue-200">
|
|
<div class="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-blue-50 ring-1 ring-blue-200">
|
|
<!-- Monitoring Icon - Globe with grid lines -->
|
|
<svg class="h-4 w-4 text-blue-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 21a9.004 9.004 0 008.716-6.747M12 21a9.004 9.004 0 01-8.716-6.747M12 21c2.485 0 4.5-4.03 4.5-9S14.485 3 12 3m0 18c-2.485 0-4.5-4.03-4.5-9S9.515 3 12 3m0 0a8.997 8.997 0 017.843 4.582M12 3a8.997 8.997 0 00-7.843 4.582m15.686 0A11.953 11.953 0 0112 10.5c-2.998 0-5.74-1.1-7.843-2.918m15.686 0A8.959 8.959 0 0121 12c0 .778-.099 1.533-.284 2.253m0 0A17.919 17.919 0 0112 16.5c-3.162 0-6.133-.815-8.716-2.247m0 0A9.015 9.015 0 013 12c0-1.605.42-3.113 1.157-4.418"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-900">Monitoring</span>
|
|
</a>
|
|
|
|
<!-- On-Call - Stone -->
|
|
<a href="/product/on-call" class="flex items-center gap-3 rounded-xl p-3 hover:bg-stone-50 ring-1 ring-transparent hover:ring-stone-200">
|
|
<div class="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-stone-50 ring-1 ring-stone-200">
|
|
<!-- On-Call Icon - Phone -->
|
|
<svg class="h-4 w-4 text-stone-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 6.75c0 8.284 6.716 15 15 15h2.25a2.25 2.25 0 002.25-2.25v-1.372c0-.516-.351-.966-.852-1.091l-4.423-1.106c-.44-.11-.902.055-1.173.417l-.97 1.293c-.282.376-.769.542-1.21.38a12.035 12.035 0 01-7.143-7.143c-.162-.441.004-.928.38-1.21l1.293-.97c.363-.271.527-.734.417-1.173L6.963 3.102a1.125 1.125 0 00-1.091-.852H4.5A2.25 2.25 0 002.25 4.5v2.25z"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-900">On-Call</span>
|
|
</a>
|
|
|
|
<!-- Scheduled Maintenance - Teal -->
|
|
<a href="/product/scheduled-maintenance" class="flex items-center gap-3 rounded-xl p-3 hover:bg-teal-50 ring-1 ring-transparent hover:ring-teal-200">
|
|
<div class="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-teal-50 ring-1 ring-teal-200">
|
|
<!-- Scheduled Maintenance Icon - Calendar with wrench -->
|
|
<svg class="h-4 w-4 text-teal-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 012.25-2.25h13.5A2.25 2.25 0 0121 7.5v11.25m-18 0A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75m-18 0v-7.5A2.25 2.25 0 015.25 9h13.5A2.25 2.25 0 0121 11.25v7.5m-9-6h.008v.008H12v-.008zM12 15h.008v.008H12V15zm0 2.25h.008v.008H12v-.008zM9.75 15h.008v.008H9.75V15zm0 2.25h.008v.008H9.75v-.008zM7.5 15h.008v.008H7.5V15zm0 2.25h.008v.008H7.5v-.008zm6.75-4.5h.008v.008h-.008v-.008zm0 2.25h.008v.008h-.008V15zm0 2.25h.008v.008h-.008v-.008zm2.25-4.5h.008v.008H16.5v-.008zm0 2.25h.008v.008H16.5V15z"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-900">Maintenance</span>
|
|
</a>
|
|
|
|
<!-- Observability - Indigo -->
|
|
<a href="/product/observability" class="flex items-center gap-3 rounded-xl p-3 hover:bg-indigo-50 ring-1 ring-transparent hover:ring-indigo-200">
|
|
<div class="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-indigo-50 ring-1 ring-indigo-200">
|
|
<!-- Observability Icon - eye over pulse line -->
|
|
<svg class="h-4 w-4 text-indigo-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z"></path>
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12h1.2l.9-1.8 1.8 3.6.9-1.8H15"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-900">Observability</span>
|
|
</a>
|
|
|
|
<!-- Topology - Teal -->
|
|
<a href="/product/topology" class="flex items-center gap-3 rounded-xl p-3 hover:bg-teal-50 ring-1 ring-transparent hover:ring-teal-200">
|
|
<div class="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-teal-50 ring-1 ring-teal-200">
|
|
<!-- Topology Icon - connected nodes / graph -->
|
|
<svg class="h-4 w-4 text-teal-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<line x1="7.5" y1="6.75" x2="7.5" y2="14.5" stroke-linecap="round"></line>
|
|
<line x1="8.9" y1="5.9" x2="15.3" y2="9.6" stroke-linecap="round"></line>
|
|
<line x1="8.7" y1="16.4" x2="15.1" y2="12.9" stroke-linecap="round"></line>
|
|
<circle cx="7.5" cy="5.5" r="2" stroke-linecap="round" stroke-linejoin="round"></circle>
|
|
<circle cx="17" cy="11" r="2" stroke-linecap="round" stroke-linejoin="round"></circle>
|
|
<circle cx="7.5" cy="16.5" r="2" stroke-linecap="round" stroke-linejoin="round"></circle>
|
|
</svg>
|
|
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-900">Topology</span>
|
|
</a>
|
|
|
|
<!-- Security Events - Red -->
|
|
<a href="/product/security-events" class="flex items-center gap-3 rounded-xl p-3 hover:bg-red-50 ring-1 ring-transparent hover:ring-red-200">
|
|
<div class="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-red-50 ring-1 ring-red-200">
|
|
<!-- Security Events Icon - shield with alert mark -->
|
|
<svg class="h-4 w-4 text-red-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 2.75l7.25 2.7v5.72c0 4.32-2.94 8.35-7.25 9.58-4.31-1.23-7.25-5.26-7.25-9.58V5.45L12 2.75z"></path>
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 8.4v3.9"></path>
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 15.35h.01"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-900">Security Events</span>
|
|
</a>
|
|
|
|
<!-- Logs - Amber -->
|
|
<a href="/product/logs-management" class="flex items-center gap-3 rounded-xl p-3 hover:bg-amber-50 ring-1 ring-transparent hover:ring-amber-200">
|
|
<div class="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-amber-50 ring-1 ring-amber-200">
|
|
<!-- Logs Icon - Stacked horizontal lines -->
|
|
<svg class="h-4 w-4 text-amber-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 12h16.5m-16.5 3.75h16.5M3.75 19.5h16.5M5.625 4.5h12.75a1.875 1.875 0 010 3.75H5.625a1.875 1.875 0 010-3.75z"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-900">Logs</span>
|
|
</a>
|
|
|
|
<!-- Metrics - Purple -->
|
|
<a href="/product/metrics" class="flex items-center gap-3 rounded-xl p-3 hover:bg-purple-50 ring-1 ring-transparent hover:ring-purple-200">
|
|
<div class="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-purple-50 ring-1 ring-purple-200">
|
|
<!-- Metrics Icon - Line chart / heartbeat -->
|
|
<svg class="h-4 w-4 text-purple-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M2 12h3l2-4 3 8 3-6 2 4h7"></path>
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M2 20h20"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-900">Metrics</span>
|
|
</a>
|
|
|
|
<!-- Traces - Yellow -->
|
|
<a href="/product/traces" class="flex items-center gap-3 rounded-xl p-3 hover:bg-yellow-50 ring-1 ring-transparent hover:ring-yellow-200">
|
|
<div class="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-yellow-50 ring-1 ring-yellow-200">
|
|
<!-- Traces Icon - Waterfall / span diagram -->
|
|
<svg class="h-4 w-4 text-yellow-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<rect x="2" y="3" width="20" height="4" rx="0.5"></rect>
|
|
<rect x="2" y="10" width="10" height="4" rx="0.5"></rect>
|
|
<rect x="2" y="17" width="5" height="4" rx="0.5"></rect>
|
|
<rect x="17" y="17" width="5" height="4" rx="0.5"></rect>
|
|
</svg>
|
|
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-900">Traces</span>
|
|
</a>
|
|
|
|
<!-- Exceptions - Orange -->
|
|
<a href="/product/exceptions" class="flex items-center gap-3 rounded-xl p-3 hover:bg-orange-50 ring-1 ring-transparent hover:ring-orange-200">
|
|
<div class="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-orange-50 ring-1 ring-orange-200">
|
|
<!-- Exceptions Icon - Bug -->
|
|
<svg class="h-4 w-4 text-orange-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<ellipse cx="12" cy="14" rx="5" ry="6"></ellipse>
|
|
<path stroke-linecap="round" d="M9 8.5C9 6.5 10.5 5 12 5s3 1.5 3 3.5M4 11l3 1m10-1 3 1M4 17l3-1m10 1 3-1M12 8v12M9 14h6"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-900">Exceptions</span>
|
|
</a>
|
|
|
|
<!-- Services - Indigo -->
|
|
<a href="/product/services" class="flex items-center gap-3 rounded-xl p-3 hover:bg-indigo-50 ring-1 ring-transparent hover:ring-indigo-200">
|
|
<div class="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-indigo-50 ring-1 ring-indigo-200">
|
|
<!-- Services Icon - Stacked squares -->
|
|
<svg class="h-4 w-4 text-indigo-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M6.429 9.75L2.25 12l4.179 2.25m0-4.5l5.571 3 5.571-3m-11.142 0L2.25 7.5 12 2.25l9.75 5.25-4.179 2.25m0 4.5L21.75 12l-4.179-2.25m0 4.5l-5.571 3-5.571-3"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-900">Services</span>
|
|
</a>
|
|
|
|
<!-- Kubernetes - Cyan -->
|
|
<a href="/product/kubernetes" class="flex items-center gap-3 rounded-xl p-3 hover:bg-cyan-50 ring-1 ring-transparent hover:ring-cyan-200">
|
|
<div class="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-cyan-50 ring-1 ring-cyan-200">
|
|
<!-- Kubernetes Icon - Helm wheel -->
|
|
<svg class="h-4 w-4 text-cyan-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<polygon stroke-linecap="round" stroke-linejoin="round" points="12,2.5 19.43,6.08 21.26,14.11 15.95,20.64 8.05,20.56 2.74,14.27 4.57,6.22"></polygon>
|
|
<circle cx="12" cy="12" r="2.2" stroke-linecap="round" stroke-linejoin="round"></circle>
|
|
<line x1="12" y1="9.8" x2="12" y2="4" stroke-linecap="round"></line>
|
|
<line x1="14.12" y1="10.24" x2="17.54" y2="6.64" stroke-linecap="round"></line>
|
|
<line x1="14.14" y1="12.49" x2="19.31" y2="13.67" stroke-linecap="round"></line>
|
|
<line x1="13.12" y1="14.0" x2="15.12" y2="18.82" stroke-linecap="round"></line>
|
|
<line x1="10.88" y1="14.0" x2="8.88" y2="18.76" stroke-linecap="round"></line>
|
|
<line x1="9.86" y1="12.49" x2="4.69" y2="13.79" stroke-linecap="round"></line>
|
|
<line x1="9.88" y1="10.24" x2="6.46" y2="6.53" stroke-linecap="round"></line>
|
|
</svg>
|
|
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-900">Kubernetes</span>
|
|
</a>
|
|
|
|
<!-- Docker - Blue -->
|
|
<a href="/product/docker" class="flex items-center gap-3 rounded-xl p-3 hover:bg-blue-50 ring-1 ring-transparent hover:ring-blue-200">
|
|
<div class="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-blue-50 ring-1 ring-blue-200">
|
|
<!-- Docker Icon - Container stack -->
|
|
<svg class="h-4 w-4 text-blue-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<rect x="3" y="10" width="3" height="3" rx="0.3" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<rect x="6.5" y="10" width="3" height="3" rx="0.3" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<rect x="10" y="10" width="3" height="3" rx="0.3" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<rect x="13.5" y="10" width="3" height="3" rx="0.3" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<rect x="6.5" y="6.5" width="3" height="3" rx="0.3" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<rect x="10" y="6.5" width="3" height="3" rx="0.3" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<rect x="13.5" y="6.5" width="3" height="3" rx="0.3" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<rect x="10" y="3" width="3" height="3" rx="0.3" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M2 14c1 2.5 3.5 4 7 4 5.5 0 9.5-2.5 11-7 1 0.2 2.2 0 3-0.7"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-900">Docker</span>
|
|
</a>
|
|
|
|
<!-- Podman - Blue -->
|
|
<a href="/product/podman" class="flex items-center gap-3 rounded-xl p-3 hover:bg-blue-50 ring-1 ring-transparent hover:ring-blue-200">
|
|
<div class="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-blue-50 ring-1 ring-blue-200">
|
|
<!-- Podman Icon - seal mascot's face inside the octagon from Podman's emblem. The official artwork (a mother seal flanked by two pups, with whiskers and water lines) turns to mush below ~48px, and this partial renders at h-3.5 to h-5, so this keeps only the cues that survive: the octagonal frame, the brow arches, the eyes and the round muzzle. Mirrors IconProp.Podman in Common/UI/Components/Icon/Icon.tsx. -->
|
|
<svg class="h-4 w-4 text-blue-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<!-- Octagonal frame of the emblem, doubling as the seal's head -->
|
|
<path d="M15.79 2.85H8.21L2.85 8.21v7.58l5.36 5.36h7.58l5.36-5.36V8.21Z" stroke-linejoin="round"></path>
|
|
<!-- Brow arches -->
|
|
<path d="M7.7 8.3C8.2 7.7 9.2 7.6 9.9 8M16.3 8.3C15.8 7.7 14.8 7.6 14.1 8" stroke-width="1.2" stroke-linecap="round"></path>
|
|
<!-- Eyes -->
|
|
<circle cx="9.1" cy="10.7" r="1.25" fill="currentColor" stroke="none"></circle>
|
|
<circle cx="14.9" cy="10.7" r="1.25" fill="currentColor" stroke="none"></circle>
|
|
<!-- Muzzle and nose -->
|
|
<circle cx="12" cy="15.2" r="2.6"></circle>
|
|
<circle cx="12" cy="14.35" r="0.6" fill="currentColor" stroke="none"></circle>
|
|
</svg>
|
|
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-900">Podman</span>
|
|
</a>
|
|
|
|
<!-- Hosts - Slate -->
|
|
<a href="/product/host" class="flex items-center gap-3 rounded-xl p-3 hover:bg-slate-50 ring-1 ring-transparent hover:ring-slate-200">
|
|
<div class="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-slate-50 ring-1 ring-slate-200">
|
|
<!-- Host Icon - Stacked servers -->
|
|
<svg class="h-4 w-4 text-slate-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<rect x="3.5" y="4" width="17" height="6" rx="1" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<rect x="3.5" y="14" width="17" height="6" rx="1" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<circle cx="7" cy="7" r="0.6" fill="currentColor"></circle>
|
|
<circle cx="7" cy="17" r="0.6" fill="currentColor"></circle>
|
|
<line x1="10" y1="7" x2="17" y2="7" stroke-linecap="round"></line>
|
|
<line x1="10" y1="17" x2="17" y2="17" stroke-linecap="round"></line>
|
|
</svg>
|
|
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-900">Hosts</span>
|
|
</a>
|
|
|
|
<!-- Proxmox - Orange -->
|
|
<a href="/product/proxmox" class="flex items-center gap-3 rounded-xl p-3 hover:bg-orange-50 ring-1 ring-transparent hover:ring-orange-200">
|
|
<div class="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-orange-50 ring-1 ring-orange-200">
|
|
<!-- Proxmox Icon - official Proxmox logo mark (Simple Icons, CC0) -->
|
|
<svg class="h-4 w-4 text-orange-600" fill="currentColor" stroke="none" viewBox="0 0 24 24">
|
|
<path d="M4.928 1.825c-1.09.553-1.09.64-.07 1.78 5.655 6.295 7.004 7.782 7.107 7.782.139.017 7.971-8.542 8.058-8.801.034-.07-.208-.312-.519-.536-.415-.312-.864-.433-1.712-.467-1.59-.104-2.144.242-4.115 2.455-.899 1.003-1.66 1.833-1.66 1.833-.017 0-.76-.813-1.642-1.798S8.473 2.1 8.127 1.91c-.796-.45-2.421-.484-3.2-.086zM1.297 4.367C.45 4.695 0 5.007 0 5.248c0 .121 1.331 1.678 2.94 3.459 1.625 1.78 2.939 3.268 2.939 3.302 0 .035-1.331 1.522-2.94 3.303C1.314 17.11.017 18.683.035 18.822c.086.467 1.504 1.055 2.541 1.055 1.678-.018 2.058-.312 5.603-4.202 1.78-1.954 3.233-3.614 3.233-3.666 0-.069-1.435-1.694-3.199-3.63-2.3-2.508-3.423-3.632-3.96-3.874-.812-.398-2.126-.467-2.956-.138zm18.467.12c-.502.26-1.764 1.505-3.943 3.891-1.763 1.937-3.199 3.562-3.199 3.631 0 .07 1.453 1.712 3.234 3.666 3.544 3.89 3.925 4.184 5.602 4.202 1.038 0 2.455-.588 2.542-1.055.017-.156-1.28-1.712-2.905-3.493-1.608-1.78-2.94-3.285-2.94-3.32 0-.034 1.332-1.539 2.94-3.32C22.72 6.91 24.017 5.352 24 5.214c-.087-.45-1.366-.968-2.473-1.038-.795-.034-1.21.035-1.763.312zM7.954 16.973c-2.144 2.369-3.908 4.374-3.943 4.46-.034.07.208.312.52.537.414.311.864.432 1.711.467 1.574.103 2.161-.26 4.15-2.508.864-.968 1.608-1.78 1.625-1.78s.761.812 1.643 1.798c2.023 2.248 2.559 2.576 4.132 2.49.848-.035 1.297-.156 1.712-.467.311-.225.553-.467.519-.536-.087-.26-7.92-8.819-8.058-8.801-.069 0-1.867 1.954-4.011 4.34z"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-900">Proxmox</span>
|
|
</a>
|
|
|
|
<!-- VMware - Indigo -->
|
|
<a href="/product/vmware" class="flex items-center gap-3 rounded-xl p-3 hover:bg-indigo-50 ring-1 ring-transparent hover:ring-indigo-200">
|
|
<div class="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-indigo-50 ring-1 ring-indigo-200">
|
|
<!-- VMware Icon - neutral hypervisor mark (host chassis with three virtual machines on the hypervisor layer). Drawn in-house to match the dashboard IconProp.VMware; not the VMware wordmark. VMware is a trademark of Broadcom Inc. -->
|
|
<svg class="h-4 w-4 text-indigo-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<rect x="3" y="4" width="18" height="16" rx="2" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<path stroke-linecap="round" d="M3 16h18"></path>
|
|
<rect x="6" y="7" width="3" height="6" rx="0.75" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<rect x="10.5" y="7" width="3" height="6" rx="0.75" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<rect x="15" y="7" width="3" height="6" rx="0.75" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
</svg>
|
|
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-900">VMware</span>
|
|
</a>
|
|
|
|
<!-- AI / LLM Observability - Violet -->
|
|
<a href="/product/ai-observability" class="flex items-center gap-3 rounded-xl p-3 hover:bg-violet-50 ring-1 ring-transparent hover:ring-violet-200">
|
|
<div class="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-violet-50 ring-1 ring-violet-200">
|
|
<!-- AI / LLM Observability Icon - sparkles mark -->
|
|
<svg class="h-4 w-4 text-violet-600" fill="none" stroke="currentColor" stroke-width="1.6" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M9.813 3.75 11 6.75l3 1.187-3 1.188-1.188 3-1.187-3-3-1.188 3-1.187 1.187-3Z" />
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M17.5 11.5 18.5 14l2.5 1-2.5 1-1 2.5-1-2.5-2.5-1 2.5-1 1-2.5Z" />
|
|
</svg>
|
|
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-900">AI / LLM Observability</span>
|
|
</a>
|
|
|
|
<!-- Ceph - Red -->
|
|
<a href="/product/ceph" class="flex items-center gap-3 rounded-xl p-3 hover:bg-red-50 ring-1 ring-transparent hover:ring-red-200">
|
|
<div class="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-red-50 ring-1 ring-red-200">
|
|
<!-- Ceph Icon - official Ceph logo mark (Simple Icons, CC0) -->
|
|
<svg class="h-4 w-4 text-red-600" fill="currentColor" stroke="none" viewBox="0 0 24 24">
|
|
<path d="M11.959.257A11.912 11.912 0 003.503 3.76 11.92 11.92 0 000 12.217a11.934 11.934 0 001.207 5.243c.72 1.474 1.888 2.944 3.208 4.044.86-.47 1.35-.99 1.453-1.545.1-.533-.134-1.107-.737-1.805a9.031 9.031 0 01-2.219-5.937c0-4.988 4.058-9.047 9.047-9.047h.08c4.99 0 9.048 4.059 9.048 9.047a9.03 9.03 0 01-2.218 5.936c-.599.693-.84 1.292-.735 1.83.108.556.595 1.068 1.449 1.522 1.322-1.1 2.489-2.57 3.209-4.046A11.898 11.898 0 0024 12.217a11.929 11.929 0 00-3.503-8.457A11.923 11.923 0 0012.04.257h-.041zm-.005 4.837a7.072 7.072 0 00-3.76 1.075A7.202 7.202 0 006.15 8.093a7.164 7.164 0 00-1.161 2.65 7.188 7.188 0 00.04 3.125 7.14 7.14 0 001.22 2.607c.154.207.326.396.509.597l.185.202.005.006c.007.007.017.016.026.027.635.738.957 1.533.957 2.36a3.4 3.4 0 01-1.788 2.989 11.924 11.924 0 002.685 1.087c.14-.088.614-.441 1.077-1.083a4.899 4.899 0 00.94-2.99 6.595 6.595 0 00-.49-2.37 6.717 6.717 0 00-1.302-2.033l-.002-.004-.124-.142c-.21-.245-.428-.497-.602-.792a4.104 4.104 0 01-.462-1.135 4.258 4.258 0 01-.024-1.85 4.25 4.25 0 01.686-1.564 4.216 4.216 0 013.432-1.773H12.042a4.202 4.202 0 013.432 1.773c.33.466.568 1.007.686 1.565a4.27 4.27 0 01-.023 1.849c-.093.39-.249.772-.463 1.135-.173.295-.391.547-.602.792l-.123.142-.004.004a6.736 6.736 0 00-1.301 2.033 6.607 6.607 0 00-.49 2.37 4.897 4.897 0 00.94 2.99c.463.642.937.995 1.076 1.083a11.776 11.776 0 002.687-1.087 3.399 3.399 0 01-1.789-2.988c0-.817.313-1.59.956-2.359.009-.012.02-.022.027-.03l.006-.004.184-.204c.183-.2.355-.39.51-.596a7.14 7.14 0 001.22-2.608 7.21 7.21 0 00.04-3.124 7.185 7.185 0 00-1.16-2.65 7.203 7.203 0 00-2.044-1.924 7.074 7.074 0 00-3.762-1.075h-.09zM12 9.97a2.365 2.365 0 00-2.362 2.361A2.364 2.364 0 0012 14.691c1.301 0 2.36-1.059 2.36-2.36A2.364 2.364 0 0012 9.968z"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-900">Ceph</span>
|
|
</a>
|
|
|
|
<!-- Docker Swarm - Blue -->
|
|
<a href="/product/docker-swarm" class="flex items-center gap-3 rounded-xl p-3 hover:bg-blue-50 ring-1 ring-transparent hover:ring-blue-200">
|
|
<div class="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-blue-50 ring-1 ring-blue-200">
|
|
<!-- Docker Swarm Icon - Generic container cluster of connected nodes (not the official Docker logo) -->
|
|
<svg class="h-4 w-4 text-blue-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<rect x="9.5" y="2.5" width="5" height="5" rx="0.75" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<rect x="3" y="14" width="5" height="5" rx="0.75" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<rect x="9.5" y="14" width="5" height="5" rx="0.75" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<rect x="16" y="14" width="5" height="5" rx="0.75" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<line x1="12" y1="7.5" x2="12" y2="14" stroke-linecap="round"></line>
|
|
<line x1="11" y1="9.5" x2="5.5" y2="14" stroke-linecap="round"></line>
|
|
<line x1="13" y1="9.5" x2="18.5" y2="14" stroke-linecap="round"></line>
|
|
<circle cx="12" cy="5" r="0.6" fill="currentColor"></circle>
|
|
<circle cx="5.5" cy="16.5" r="0.6" fill="currentColor"></circle>
|
|
<circle cx="12" cy="16.5" r="0.6" fill="currentColor"></circle>
|
|
<circle cx="18.5" cy="16.5" r="0.6" fill="currentColor"></circle>
|
|
</svg>
|
|
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-900">Docker Swarm</span>
|
|
</a>
|
|
|
|
<!-- IoT Devices - Teal -->
|
|
<a href="/product/iot" class="flex items-center gap-3 rounded-xl p-3 hover:bg-teal-50 ring-1 ring-transparent hover:ring-teal-200">
|
|
<div class="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-teal-50 ring-1 ring-teal-200">
|
|
<!-- IoT Devices Icon - CPU chip (Heroicons, MIT) -->
|
|
<svg class="h-4 w-4 text-teal-600" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.7">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M8.25 3v1.5M4.5 8.25H3m18 0h-1.5M4.5 12H3m18 0h-1.5m-15 3.75H3m18 0h-1.5M8.25 19.5V21M12 3v1.5m0 15V21m3.75-18v1.5m0 15V21m-9-1.5h10.5a2.25 2.25 0 0 0 2.25-2.25V6.75a2.25 2.25 0 0 0-2.25-2.25H6.75A2.25 2.25 0 0 0 4.5 6.75v10.5a2.25 2.25 0 0 0 2.25 2.25Zm.75-12h9v9h-9v-9Z" />
|
|
</svg>
|
|
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-900">IoT Devices</span>
|
|
</a>
|
|
|
|
<!-- Network Devices - Sky -->
|
|
<a href="/product/network-monitoring" class="flex items-center gap-3 rounded-xl p-3 hover:bg-sky-50 ring-1 ring-transparent hover:ring-sky-200">
|
|
<div class="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-sky-50 ring-1 ring-sky-200">
|
|
<!-- Network Devices Icon - switch with uplinks -->
|
|
<svg class="h-4 w-4 text-sky-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<rect x="3" y="13.5" width="18" height="6" rx="1" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<circle cx="6.5" cy="16.5" r="0.6" fill="currentColor"></circle>
|
|
<line x1="9.5" y1="16.5" x2="12.5" y2="16.5" stroke-linecap="round"></line>
|
|
<line x1="14.5" y1="16.5" x2="17.5" y2="16.5" stroke-linecap="round"></line>
|
|
<line x1="12" y1="13.5" x2="12" y2="9.5" stroke-linecap="round"></line>
|
|
<line x1="12" y1="9.5" x2="6" y2="9.5" stroke-linecap="round"></line>
|
|
<line x1="12" y1="9.5" x2="18" y2="9.5" stroke-linecap="round"></line>
|
|
<line x1="6" y1="9.5" x2="6" y2="7" stroke-linecap="round"></line>
|
|
<line x1="18" y1="9.5" x2="18" y2="7" stroke-linecap="round"></line>
|
|
<circle cx="6" cy="5.75" r="1.25" stroke-linecap="round" stroke-linejoin="round"></circle>
|
|
<circle cx="18" cy="5.75" r="1.25" stroke-linecap="round" stroke-linejoin="round"></circle>
|
|
</svg>
|
|
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-900">Network Devices</span>
|
|
</a>
|
|
|
|
<!-- Serverless - Fuchsia -->
|
|
<a href="/product/serverless" class="flex items-center gap-3 rounded-xl p-3 hover:bg-fuchsia-50 ring-1 ring-transparent hover:ring-fuchsia-200">
|
|
<div class="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-fuchsia-50 ring-1 ring-fuchsia-200">
|
|
<!-- Serverless Icon - Lightning bolt (functions) -->
|
|
<svg class="h-4 w-4 text-fuchsia-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 13.5l10.5-11.25L12 10.5h8.25L9.75 21.75 12 13.5H3.75z"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-900">Serverless</span>
|
|
</a>
|
|
|
|
<!-- Cloud - Sky -->
|
|
<a href="/product/cloud" class="flex items-center gap-3 rounded-xl p-3 hover:bg-sky-50 ring-1 ring-transparent hover:ring-sky-200">
|
|
<div class="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-sky-50 ring-1 ring-sky-200">
|
|
<!-- Cloud Icon -->
|
|
<svg class="h-4 w-4 text-sky-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 15a4.5 4.5 0 004.5 4.5H18a3.75 3.75 0 001.332-7.257 3 3 0 00-3.758-3.848 5.25 5.25 0 00-10.233 2.33A4.502 4.502 0 002.25 15z"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-900">Cloud</span>
|
|
</a>
|
|
|
|
<!-- Profiles - Rose -->
|
|
<a href="/product/profiles" class="flex items-center gap-3 rounded-xl p-3 hover:bg-rose-50 ring-1 ring-transparent hover:ring-rose-200">
|
|
<div class="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-rose-50 ring-1 ring-rose-200">
|
|
<!-- Profiles Icon - Flame/fire for flamegraph -->
|
|
<svg class="h-4 w-4 text-rose-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0112 21 8.25 8.25 0 016.038 7.048 8.287 8.287 0 009 9.6a8.983 8.983 0 013.361-6.867 8.21 8.21 0 003 2.48z"></path>
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 00.495-7.467 5.99 5.99 0 00-1.925 3.546 5.974 5.974 0 01-2.133-1.001A3.75 3.75 0 0012 18z"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-900">Profiles</span>
|
|
</a>
|
|
|
|
<!-- RUM - Indigo -->
|
|
<a href="/product/rum" class="flex items-center gap-3 rounded-xl p-3 hover:bg-indigo-50 ring-1 ring-transparent hover:ring-indigo-200">
|
|
<div class="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-indigo-50 ring-1 ring-indigo-200">
|
|
<!-- RUM Icon - Cursor rays (real user interaction) -->
|
|
<svg class="h-4 w-4 text-indigo-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M15.042 21.672L13.684 16.6m0 0l-2.51 2.225.569-9.47 5.227 7.917-3.286-.672zM12 2.25V4.5m5.834.166l-1.591 1.591M20.25 10.5H18M7.757 14.743l-1.59 1.59M6 10.5H3.75m4.007-4.243l-1.59-1.59"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-900">RUM</span>
|
|
</a>
|
|
|
|
<!-- Workflows - Sky -->
|
|
<a href="/product/workflows" class="flex items-center gap-3 rounded-xl p-3 hover:bg-sky-50 ring-1 ring-transparent hover:ring-sky-200">
|
|
<div class="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-sky-50 ring-1 ring-sky-200">
|
|
<!-- Workflows Icon - Flow diagram (rotated 180°) -->
|
|
<svg class="h-4 w-4 text-sky-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24" style="transform: rotate(180deg)">
|
|
<rect x="3" y="3" width="6" height="4" rx="1" stroke-width="1.5"></rect>
|
|
<rect x="15" y="3" width="6" height="4" rx="1" stroke-width="1.5"></rect>
|
|
<rect x="9" y="17" width="6" height="4" rx="1" stroke-width="1.5"></rect>
|
|
<path stroke-linecap="round" d="M6 7v3a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V7M12 12v5"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-900">Workflows</span>
|
|
</a>
|
|
|
|
<!-- Dashboards - Indigo -->
|
|
<a href="/product/dashboards" class="flex items-center gap-3 rounded-xl p-3 hover:bg-indigo-50 ring-1 ring-transparent hover:ring-indigo-200">
|
|
<div class="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-indigo-50 ring-1 ring-indigo-200">
|
|
<!-- Dashboards Icon - Pie chart -->
|
|
<svg class="h-4 w-4 text-indigo-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M10.5 6a7.5 7.5 0 107.5 7.5h-7.5V6z"></path>
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M13.5 10.5H21A7.5 7.5 0 0013.5 3v7.5z"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-900">Dashboards</span>
|
|
</a>
|
|
|
|
<!-- AI Agent - Violet (Featured) -->
|
|
<a href="/product/ai-agent" class="col-span-2 flex items-center gap-3 rounded-xl p-3 bg-gradient-to-r from-violet-50 to-purple-50 ring-1 ring-violet-200">
|
|
<div class="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-lg bg-violet-100 ring-1 ring-violet-300">
|
|
<!-- AI Agent Icon - Sparkles -->
|
|
<svg class="h-4 w-4 text-violet-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M9.813 15.904 9 18.75l-.813-2.846a4.5 4.5 0 0 0-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 0 0 3.09-3.09L9 5.25l.813 2.846a4.5 4.5 0 0 0 3.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 0 0-3.09 3.09ZM18.259 8.715 18 9.75l-.259-1.035a3.375 3.375 0 0 0-2.455-2.456L14.25 6l1.036-.259a3.375 3.375 0 0 0 2.455-2.456L18 2.25l.259 1.035a3.375 3.375 0 0 0 2.456 2.456L21.75 6l-1.035.259a3.375 3.375 0 0 0-2.456 2.456ZM16.894 20.567 16.5 21.75l-.394-1.183a2.25 2.25 0 0 0-1.423-1.423L13.5 18.75l1.183-.394a2.25 2.25 0 0 0 1.423-1.423l.394-1.183.394 1.183a2.25 2.25 0 0 0 1.423 1.423l1.183.394-1.183.394a2.25 2.25 0 0 0-1.423 1.423Z"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-900">AI</span>
|
|
</a>
|
|
</nav>
|
|
|
|
<!-- Enterprise Section -->
|
|
<div class="mt-6 pt-6 border-t border-gray-100">
|
|
<p class="text-xs font-semibold text-gray-400 uppercase tracking-wider mb-3">Enterprise</p>
|
|
<div class="grid grid-cols-3 gap-2">
|
|
<a href="/solutions/devops" class="flex flex-col items-center p-3 rounded-xl border border-gray-100 hover:border-cyan-200 hover:bg-cyan-50/50">
|
|
<div class="w-8 h-8 rounded-lg bg-gradient-to-br from-cyan-500 to-teal-600 flex items-center justify-center mb-2">
|
|
<svg class="h-4 w-4 text-white" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M5.25 14.25h13.5m-13.5 0a3 3 0 01-3-3m3 3a3 3 0 100 6h13.5a3 3 0 100-6m-16.5-3a3 3 0 013-3h13.5a3 3 0 013 3"></path>
|
|
</svg>
|
|
</div>
|
|
<span class="text-xs font-medium text-gray-900 text-center">DevOps</span>
|
|
</a>
|
|
<a href="/solutions/sre" class="flex flex-col items-center p-3 rounded-xl border border-gray-100 hover:border-violet-200 hover:bg-violet-50/50">
|
|
<div class="w-8 h-8 rounded-lg bg-gradient-to-br from-violet-500 to-purple-600 flex items-center justify-center mb-2">
|
|
<svg class="h-4 w-4 text-white" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75m-3-7.036A11.959 11.959 0 013.598 6 11.99 11.99 0 003 9.749c0 5.592 3.824 10.29 9 11.623 5.176-1.332 9-6.03 9-11.622 0-1.31-.21-2.571-.598-3.751h-.152c-3.196 0-6.1-1.248-8.25-3.285z"></path>
|
|
</svg>
|
|
</div>
|
|
<span class="text-xs font-medium text-gray-900 text-center">SRE</span>
|
|
</a>
|
|
<a href="/solutions/platform" class="flex flex-col items-center p-3 rounded-xl border border-gray-100 hover:border-amber-200 hover:bg-amber-50/50">
|
|
<div class="w-8 h-8 rounded-lg bg-gradient-to-br from-amber-500 to-orange-600 flex items-center justify-center mb-2">
|
|
<svg class="h-4 w-4 text-white" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M6.429 9.75L2.25 12l4.179 2.25m0-4.5l5.571 3 5.571-3m-11.142 0L2.25 7.5 12 2.25l9.75 5.25-4.179 2.25"></path>
|
|
</svg>
|
|
</div>
|
|
<span class="text-xs font-medium text-gray-900 text-center">Platform</span>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="space-y-6 py-6 px-5 border-t border-gray-100">
|
|
<div class="grid grid-cols-2 gap-y-4 gap-x-8">
|
|
<a href="/pricing" class="text-base font-medium text-gray-900 hover:text-gray-700">Pricing</a>
|
|
|
|
<a href="/docs" class="text-base font-medium text-gray-900 hover:text-gray-700">Docs</a>
|
|
|
|
<a href="/enterprise/demo" class="text-base font-medium text-gray-900 hover:text-gray-700"
|
|
data-testid="request-demo-mobile-link">Request Demo</a>
|
|
|
|
<a href="/enterprise/self-hosted" class="text-base font-medium text-gray-900 hover:text-gray-700">Self-Hosted</a>
|
|
|
|
<a href="/trust" class="text-base font-medium text-gray-900 hover:text-gray-700">Trust Center</a>
|
|
|
|
<a href="/support" class="text-base font-medium text-gray-900 hover:text-gray-700">Support</a>
|
|
|
|
<a href="/books" class="text-base font-medium text-gray-900 hover:text-gray-700">Books</a>
|
|
</div>
|
|
<div>
|
|
<a href="/accounts/register"
|
|
class="flex w-full items-center justify-center rounded-md border border-transparent bg-gray-900 px-4 py-2 text-base font-medium text-white shadow-sm hover:bg-gray-900">Sign
|
|
up</a>
|
|
<p class="mt-6 text-center text-base font-medium text-gray-500">
|
|
Existing customer?
|
|
<a href="/accounts" class="text-gray-600 hover:text-gray-500">Sign in</a>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ============================================================= -->
|
|
<!-- Products search modal (command-palette, mirrors the in-app -->
|
|
<!-- NavBarMenuModal). Rendered at header root so its fixed overlay -->
|
|
<!-- is never clipped by a transformed ancestor. -->
|
|
<!-- ============================================================= -->
|
|
<div id="product-modal" class="relative z-50 hidden" role="dialog" aria-modal="true" aria-label="Products">
|
|
<!-- Backdrop -->
|
|
<div id="product-modal-backdrop"
|
|
class="fixed inset-0 bg-gray-900/50 backdrop-blur-sm opacity-0 transition-opacity duration-200"></div>
|
|
|
|
<!-- Scroll + click-away container -->
|
|
<div class="fixed inset-0 z-50 overflow-y-auto" onclick="closeProductModal()">
|
|
<div class="flex min-h-full items-start justify-center p-4 sm:p-6">
|
|
<div id="product-modal-card"
|
|
class="relative mt-[6vh] flex w-full max-w-3xl translate-y-2 scale-[0.98] flex-col overflow-hidden rounded-2xl bg-white opacity-0 shadow-2xl ring-1 ring-gray-900/5 transition-all duration-200 ease-out"
|
|
style="max-height: 82vh;" onclick="event.stopPropagation()">
|
|
|
|
<!-- Header -->
|
|
<div class="border-b border-gray-100 bg-gradient-to-br from-indigo-50/70 via-white to-white px-5 pt-5 pb-4 sm:px-6">
|
|
<div class="flex items-start justify-between gap-4">
|
|
<div class="min-w-0">
|
|
<p class="text-[11px] font-semibold uppercase tracking-[0.16em] text-indigo-500">Products</p>
|
|
<h2 class="mt-1 text-lg font-semibold text-gray-900">Explore the OneUptime platform</h2>
|
|
<p class="mt-0.5 hidden text-sm text-gray-500 sm:block">One platform for monitoring, observability & incident response.</p>
|
|
</div>
|
|
<button type="button" onclick="closeProductModal()" aria-label="Close"
|
|
class="flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full text-gray-400 transition-colors hover:bg-white hover:text-gray-600 hover:shadow-sm">
|
|
<svg class="h-5 w-5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"></path>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
<!-- Search box -->
|
|
<div class="mt-4 flex items-center gap-3 rounded-xl border border-gray-200 bg-white px-3.5 py-2.5 shadow-sm transition focus-within:border-indigo-300 focus-within:ring-2 focus-within:ring-indigo-100">
|
|
<svg class="h-5 w-5 flex-shrink-0 text-gray-400" fill="none" stroke="currentColor" stroke-width="1.8" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M21 21l-4.35-4.35M17 11a6 6 0 11-12 0 6 6 0 0112 0z"></path>
|
|
</svg>
|
|
<input id="product-modal-search" type="text" role="combobox" aria-expanded="true"
|
|
aria-controls="product-modal-body" aria-label="Search products" autocomplete="off" autocorrect="off"
|
|
autocapitalize="off" spellcheck="false" placeholder="Search products…"
|
|
class="flex-1 border-0 bg-transparent p-0 text-base text-gray-900 placeholder-gray-400 focus:outline-none focus:ring-0" />
|
|
<button id="product-modal-clear" type="button" onclick="clearProductSearch()" aria-label="Clear search"
|
|
style="display:none;"
|
|
class="h-6 w-6 flex-shrink-0 items-center justify-center rounded-full text-gray-400 hover:bg-gray-100 hover:text-gray-600">
|
|
<svg class="h-4 w-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"></path>
|
|
</svg>
|
|
</button>
|
|
<kbd id="product-modal-kbd"
|
|
class="hidden flex-shrink-0 items-center rounded border border-gray-200 bg-gray-50 px-1.5 py-0.5 text-xs font-medium text-gray-400 sm:inline-flex">⌘K</kbd>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Body -->
|
|
<div id="product-modal-body" role="listbox" aria-label="Products"
|
|
class="flex-1 overflow-y-auto overscroll-contain px-5 py-5 sm:px-6">
|
|
|
|
<!-- Featured: AI Agent (hidden while searching) -->
|
|
<a id="product-modal-featured" href="/product/ai-agent"
|
|
class="group mb-5 flex items-center gap-4 rounded-xl border border-violet-200 bg-gradient-to-r from-violet-50 via-purple-50 to-fuchsia-50 p-4 transition-colors hover:border-violet-300">
|
|
<div class="flex h-11 w-11 flex-shrink-0 items-center justify-center rounded-xl bg-gradient-to-br from-violet-100 to-purple-100 ring-1 ring-violet-300">
|
|
<!-- AI Agent Icon - Sparkles -->
|
|
<svg class="h-5 w-5 text-violet-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M9.813 15.904 9 18.75l-.813-2.846a4.5 4.5 0 0 0-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 0 0 3.09-3.09L9 5.25l.813 2.846a4.5 4.5 0 0 0 3.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 0 0-3.09 3.09ZM18.259 8.715 18 9.75l-.259-1.035a3.375 3.375 0 0 0-2.455-2.456L14.25 6l1.036-.259a3.375 3.375 0 0 0 2.455-2.456L18 2.25l.259 1.035a3.375 3.375 0 0 0 2.456 2.456L21.75 6l-1.035.259a3.375 3.375 0 0 0-2.456 2.456ZM16.894 20.567 16.5 21.75l-.394-1.183a2.25 2.25 0 0 0-1.423-1.423L13.5 18.75l1.183-.394a2.25 2.25 0 0 0 1.423-1.423l.394-1.183.394 1.183a2.25 2.25 0 0 0 1.423 1.423l1.183.394-1.183.394a2.25 2.25 0 0 0-1.423 1.423Z"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="min-w-0 flex-1">
|
|
<p class="text-sm font-semibold text-gray-900">AI</p>
|
|
<p class="mt-0.5 text-xs leading-relaxed text-gray-600 line-clamp-2">Investigates incidents with AI and turns findings into fix pull requests for your review.</p>
|
|
</div>
|
|
<svg class="h-5 w-5 flex-shrink-0 text-violet-400 transition-colors group-hover:text-violet-600" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M13.5 4.5L21 12m0 0l-7.5 7.5M21 12H3"></path>
|
|
</svg>
|
|
</a>
|
|
|
|
<!-- Essentials -->
|
|
<div class="product-group mb-6">
|
|
<h3 class="mb-2.5 px-1 text-[11px] font-semibold uppercase tracking-[0.1em] text-gray-500">Essentials</h3>
|
|
<div class="grid grid-cols-1 gap-2 sm:grid-cols-2 lg:grid-cols-3">
|
|
<a href="/product/monitoring" class="product-card group flex h-full items-start gap-3 rounded-xl border border-transparent p-3 text-left transition-colors duration-150 hover:border-indigo-200 hover:bg-indigo-50/40" data-search="monitoring uptime synthetic checks">
|
|
<div class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-blue-50 ring-1 ring-blue-200">
|
|
<!-- Monitoring Icon - Globe with grid lines -->
|
|
<svg class="h-5 w-5 text-blue-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 21a9.004 9.004 0 008.716-6.747M12 21a9.004 9.004 0 01-8.716-6.747M12 21c2.485 0 4.5-4.03 4.5-9S14.485 3 12 3m0 18c-2.485 0-4.5-4.03-4.5-9S9.515 3 12 3m0 0a8.997 8.997 0 017.843 4.582M12 3a8.997 8.997 0 00-7.843 4.582m15.686 0A11.953 11.953 0 0112 10.5c-2.998 0-5.74-1.1-7.843-2.918m15.686 0A8.959 8.959 0 0121 12c0 .778-.099 1.533-.284 2.253m0 0A17.919 17.919 0 0112 16.5c-3.162 0-6.133-.815-8.716-2.247m0 0A9.015 9.015 0 013 12c0-1.605.42-3.113 1.157-4.418"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="min-w-0 flex-1">
|
|
<p class="product-card-title truncate text-sm font-medium text-gray-900">Monitoring</p>
|
|
<p class="mt-0.5 text-xs leading-relaxed text-gray-500 line-clamp-2">Uptime & synthetic checks</p>
|
|
</div>
|
|
</a>
|
|
<a href="/product/status-page" class="product-card group flex h-full items-start gap-3 rounded-xl border border-transparent p-3 text-left transition-colors duration-150 hover:border-indigo-200 hover:bg-indigo-50/40" data-search="status page communicate incidents to users">
|
|
<div class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-emerald-50 ring-1 ring-emerald-200">
|
|
<!-- Status Page Icon - Checkmark in circle -->
|
|
<svg class="h-5 w-5 text-emerald-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="min-w-0 flex-1">
|
|
<p class="product-card-title truncate text-sm font-medium text-gray-900">Status Page</p>
|
|
<p class="mt-0.5 text-xs leading-relaxed text-gray-500 line-clamp-2">Communicate incidents to users</p>
|
|
</div>
|
|
</a>
|
|
<a href="/product/incident-management" class="product-card group flex h-full items-start gap-3 rounded-xl border border-transparent p-3 text-left transition-colors duration-150 hover:border-indigo-200 hover:bg-indigo-50/40" data-search="incidents detect manage resolve">
|
|
<div class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-rose-50 ring-1 ring-rose-200">
|
|
<!-- Incidents Icon - Warning triangle -->
|
|
<svg class="h-5 w-5 text-rose-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="min-w-0 flex-1">
|
|
<p class="product-card-title truncate text-sm font-medium text-gray-900">Incidents</p>
|
|
<p class="mt-0.5 text-xs leading-relaxed text-gray-500 line-clamp-2">Detect, manage & resolve</p>
|
|
</div>
|
|
</a>
|
|
<a href="/product/on-call" class="product-card group flex h-full items-start gap-3 rounded-xl border border-transparent p-3 text-left transition-colors duration-150 hover:border-indigo-200 hover:bg-indigo-50/40" data-search="on-call alerts smart routing escalations">
|
|
<div class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-stone-100 ring-1 ring-stone-300">
|
|
<!-- On-Call Icon - Phone -->
|
|
<svg class="h-5 w-5 text-stone-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 6.75c0 8.284 6.716 15 15 15h2.25a2.25 2.25 0 002.25-2.25v-1.372c0-.516-.351-.966-.852-1.091l-4.423-1.106c-.44-.11-.902.055-1.173.417l-.97 1.293c-.282.376-.769.542-1.21.38a12.035 12.035 0 01-7.143-7.143c-.162-.441.004-.928.38-1.21l1.293-.97c.363-.271.527-.734.417-1.173L6.963 3.102a1.125 1.125 0 00-1.091-.852H4.5A2.25 2.25 0 002.25 4.5v2.25z"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="min-w-0 flex-1">
|
|
<p class="product-card-title truncate text-sm font-medium text-gray-900">On-Call & Alerts</p>
|
|
<p class="mt-0.5 text-xs leading-relaxed text-gray-500 line-clamp-2">Smart routing & escalations</p>
|
|
</div>
|
|
</a>
|
|
<a href="/product/scheduled-maintenance" class="product-card group flex h-full items-start gap-3 rounded-xl border border-transparent p-3 text-left transition-colors duration-150 hover:border-indigo-200 hover:bg-indigo-50/40" data-search="scheduled maintenance plan communicate downtime">
|
|
<div class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-teal-50 ring-1 ring-teal-200">
|
|
<!-- Scheduled Maintenance Icon - Calendar with wrench -->
|
|
<svg class="h-5 w-5 text-teal-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 012.25-2.25h13.5A2.25 2.25 0 0121 7.5v11.25m-18 0A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75m-18 0v-7.5A2.25 2.25 0 015.25 9h13.5A2.25 2.25 0 0121 11.25v7.5m-9-6h.008v.008H12v-.008zM12 15h.008v.008H12V15zm0 2.25h.008v.008H12v-.008zM9.75 15h.008v.008H9.75V15zm0 2.25h.008v.008H9.75v-.008zM7.5 15h.008v.008H7.5V15zm0 2.25h.008v.008H7.5v-.008zm6.75-4.5h.008v.008h-.008v-.008zm0 2.25h.008v.008h-.008V15zm0 2.25h.008v.008h-.008v-.008zm2.25-4.5h.008v.008H16.5v-.008zm0 2.25h.008v.008H16.5V15z"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="min-w-0 flex-1">
|
|
<p class="product-card-title truncate text-sm font-medium text-gray-900">Scheduled Maintenance</p>
|
|
<p class="mt-0.5 text-xs leading-relaxed text-gray-500 line-clamp-2">Plan & communicate downtime</p>
|
|
</div>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Observability -->
|
|
<div class="product-group mb-6">
|
|
<h3 class="mb-2.5 px-1 text-[11px] font-semibold uppercase tracking-[0.1em] text-gray-500">Observability</h3>
|
|
<div class="grid grid-cols-1 gap-2 sm:grid-cols-2 lg:grid-cols-3">
|
|
<a href="/product/observability" class="product-card group flex h-full items-start gap-3 rounded-xl border border-transparent p-3 text-left transition-colors duration-150 hover:border-indigo-200 hover:bg-indigo-50/40" data-search="observability platform logs metrics traces opentelemetry otel correlate signals">
|
|
<div class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-indigo-50 ring-1 ring-indigo-200">
|
|
<!-- Observability Icon - eye over pulse line -->
|
|
<svg class="h-5 w-5 text-indigo-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z"></path>
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12h1.2l.9-1.8 1.8 3.6.9-1.8H15"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="min-w-0 flex-1">
|
|
<p class="product-card-title truncate text-sm font-medium text-gray-900">Observability</p>
|
|
<p class="mt-0.5 text-xs leading-relaxed text-gray-500 line-clamp-2">Logs, metrics & traces in one</p>
|
|
</div>
|
|
</a>
|
|
<a href="/product/topology" class="product-card group flex h-full items-start gap-3 rounded-xl border border-transparent p-3 text-left transition-colors duration-150 hover:border-indigo-200 hover:bg-indigo-50/40" data-search="topology service map infrastructure network map dependency graph traces lldp service mesh">
|
|
<div class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-teal-50 ring-1 ring-teal-200">
|
|
<!-- Topology Icon - connected nodes / graph -->
|
|
<svg class="h-5 w-5 text-teal-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<line x1="7.5" y1="6.75" x2="7.5" y2="14.5" stroke-linecap="round"></line>
|
|
<line x1="8.9" y1="5.9" x2="15.3" y2="9.6" stroke-linecap="round"></line>
|
|
<line x1="8.7" y1="16.4" x2="15.1" y2="12.9" stroke-linecap="round"></line>
|
|
<circle cx="7.5" cy="5.5" r="2" stroke-linecap="round" stroke-linejoin="round"></circle>
|
|
<circle cx="17" cy="11" r="2" stroke-linecap="round" stroke-linejoin="round"></circle>
|
|
<circle cx="7.5" cy="16.5" r="2" stroke-linecap="round" stroke-linejoin="round"></circle>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="min-w-0 flex-1">
|
|
<p class="product-card-title truncate text-sm font-medium text-gray-900">Topology</p>
|
|
<p class="mt-0.5 text-xs leading-relaxed text-gray-500 line-clamp-2">Service, infra & network maps</p>
|
|
</div>
|
|
</a>
|
|
<a href="/product/security-events" class="product-card group flex h-full items-start gap-3 rounded-xl border border-transparent p-3 text-left transition-colors duration-150 hover:border-indigo-200 hover:bg-indigo-50/40" data-search="security events siem ocsf sigma detection rules threat detection audit soar chronicle google secops">
|
|
<div class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-red-50 ring-1 ring-red-200">
|
|
<!-- Security Events Icon - shield with alert mark -->
|
|
<svg class="h-5 w-5 text-red-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 2.75l7.25 2.7v5.72c0 4.32-2.94 8.35-7.25 9.58-4.31-1.23-7.25-5.26-7.25-9.58V5.45L12 2.75z"></path>
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 8.4v3.9"></path>
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 15.35h.01"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="min-w-0 flex-1">
|
|
<p class="product-card-title truncate text-sm font-medium text-gray-900">Security Events</p>
|
|
<p class="mt-0.5 text-xs leading-relaxed text-gray-500 line-clamp-2">SIEM signals & Sigma detections</p>
|
|
</div>
|
|
</a>
|
|
<a href="/product/logs-management" class="product-card group flex h-full items-start gap-3 rounded-xl border border-transparent p-3 text-left transition-colors duration-150 hover:border-indigo-200 hover:bg-indigo-50/40" data-search="logs fastest log ingest search">
|
|
<div class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-amber-50 ring-1 ring-amber-200">
|
|
<!-- Logs Icon - Stacked horizontal lines -->
|
|
<svg class="h-5 w-5 text-amber-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 12h16.5m-16.5 3.75h16.5M3.75 19.5h16.5M5.625 4.5h12.75a1.875 1.875 0 010 3.75H5.625a1.875 1.875 0 010-3.75z"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="min-w-0 flex-1">
|
|
<p class="product-card-title truncate text-sm font-medium text-gray-900">Logs</p>
|
|
<p class="mt-0.5 text-xs leading-relaxed text-gray-500 line-clamp-2">Fastest log ingest & search</p>
|
|
</div>
|
|
</a>
|
|
<a href="/product/metrics" class="product-card group flex h-full items-start gap-3 rounded-xl border border-transparent p-3 text-left transition-colors duration-150 hover:border-indigo-200 hover:bg-indigo-50/40" data-search="metrics application infra metrics">
|
|
<div class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-purple-50 ring-1 ring-purple-200">
|
|
<!-- Metrics Icon - Line chart / heartbeat -->
|
|
<svg class="h-5 w-5 text-purple-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M2 12h3l2-4 3 8 3-6 2 4h7"></path>
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M2 20h20"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="min-w-0 flex-1">
|
|
<p class="product-card-title truncate text-sm font-medium text-gray-900">Metrics</p>
|
|
<p class="mt-0.5 text-xs leading-relaxed text-gray-500 line-clamp-2">Application & infra metrics</p>
|
|
</div>
|
|
</a>
|
|
<a href="/product/traces" class="product-card group flex h-full items-start gap-3 rounded-xl border border-transparent p-3 text-left transition-colors duration-150 hover:border-indigo-200 hover:bg-indigo-50/40" data-search="traces distributed request tracing">
|
|
<div class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-yellow-50 ring-1 ring-yellow-200">
|
|
<!-- Traces Icon - Waterfall / span diagram -->
|
|
<svg class="h-5 w-5 text-yellow-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<rect x="2" y="3" width="20" height="4" rx="0.5"></rect>
|
|
<rect x="2" y="10" width="10" height="4" rx="0.5"></rect>
|
|
<rect x="2" y="17" width="5" height="4" rx="0.5"></rect>
|
|
<rect x="17" y="17" width="5" height="4" rx="0.5"></rect>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="min-w-0 flex-1">
|
|
<p class="product-card-title truncate text-sm font-medium text-gray-900">Traces</p>
|
|
<p class="mt-0.5 text-xs leading-relaxed text-gray-500 line-clamp-2">Distributed request tracing</p>
|
|
</div>
|
|
</a>
|
|
<a href="/product/exceptions" class="product-card group flex h-full items-start gap-3 rounded-xl border border-transparent p-3 text-left transition-colors duration-150 hover:border-indigo-200 hover:bg-indigo-50/40" data-search="exceptions error tracking debugging">
|
|
<div class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-orange-50 ring-1 ring-orange-200">
|
|
<!-- Exceptions Icon - Bug -->
|
|
<svg class="h-5 w-5 text-orange-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<ellipse cx="12" cy="14" rx="5" ry="6"></ellipse>
|
|
<path stroke-linecap="round" d="M9 8.5C9 6.5 10.5 5 12 5s3 1.5 3 3.5M4 11l3 1m10-1 3 1M4 17l3-1m10 1 3-1M12 8v12M9 14h6"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="min-w-0 flex-1">
|
|
<p class="product-card-title truncate text-sm font-medium text-gray-900">Exceptions</p>
|
|
<p class="mt-0.5 text-xs leading-relaxed text-gray-500 line-clamp-2">Error tracking & debugging</p>
|
|
</div>
|
|
</a>
|
|
<a href="/product/profiles" class="product-card group flex h-full items-start gap-3 rounded-xl border border-transparent p-3 text-left transition-colors duration-150 hover:border-indigo-200 hover:bg-indigo-50/40" data-search="profiles cpu memory profiling">
|
|
<div class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-rose-50 ring-1 ring-rose-200">
|
|
<!-- Profiles Icon - Flame/fire for flamegraph -->
|
|
<svg class="h-5 w-5 text-rose-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0112 21 8.25 8.25 0 016.038 7.048 8.287 8.287 0 009 9.6a8.983 8.983 0 013.361-6.867 8.21 8.21 0 003 2.48z"></path>
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 00.495-7.467 5.99 5.99 0 00-1.925 3.546 5.974 5.974 0 01-2.133-1.001A3.75 3.75 0 0012 18z"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="min-w-0 flex-1">
|
|
<p class="product-card-title truncate text-sm font-medium text-gray-900">Profiles</p>
|
|
<p class="mt-0.5 text-xs leading-relaxed text-gray-500 line-clamp-2">CPU & memory profiling</p>
|
|
</div>
|
|
</a>
|
|
<a href="/product/rum" class="product-card group flex h-full items-start gap-3 rounded-xl border border-transparent p-3 text-left transition-colors duration-150 hover:border-indigo-200 hover:bg-indigo-50/40" data-search="rum real user monitoring">
|
|
<div class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-indigo-50 ring-1 ring-indigo-200">
|
|
<!-- RUM Icon - Cursor rays (real user interaction) -->
|
|
<svg class="h-5 w-5 text-indigo-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M15.042 21.672L13.684 16.6m0 0l-2.51 2.225.569-9.47 5.227 7.917-3.286-.672zM12 2.25V4.5m5.834.166l-1.591 1.591M20.25 10.5H18M7.757 14.743l-1.59 1.59M6 10.5H3.75m4.007-4.243l-1.59-1.59"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="min-w-0 flex-1">
|
|
<p class="product-card-title truncate text-sm font-medium text-gray-900">RUM</p>
|
|
<p class="mt-0.5 text-xs leading-relaxed text-gray-500 line-clamp-2">Real user monitoring</p>
|
|
</div>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Infrastructure -->
|
|
<div class="product-group mb-6">
|
|
<h3 class="mb-2.5 px-1 text-[11px] font-semibold uppercase tracking-[0.1em] text-gray-500">Infrastructure</h3>
|
|
<div class="grid grid-cols-1 gap-2 sm:grid-cols-2 lg:grid-cols-3">
|
|
<a href="/product/services" class="product-card group flex h-full items-start gap-3 rounded-xl border border-transparent p-3 text-left transition-colors duration-150 hover:border-indigo-200 hover:bg-indigo-50/40" data-search="services catalog every service you run">
|
|
<div class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-indigo-50 ring-1 ring-indigo-200">
|
|
<!-- Services Icon - Stacked squares -->
|
|
<svg class="h-5 w-5 text-indigo-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M6.429 9.75L2.25 12l4.179 2.25m0-4.5l5.571 3 5.571-3m-11.142 0L2.25 7.5 12 2.25l9.75 5.25-4.179 2.25m0 4.5L21.75 12l-4.179-2.25m0 4.5l-5.571 3-5.571-3"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="min-w-0 flex-1">
|
|
<p class="product-card-title truncate text-sm font-medium text-gray-900">Services</p>
|
|
<p class="mt-0.5 text-xs leading-relaxed text-gray-500 line-clamp-2">Catalog every service you run</p>
|
|
</div>
|
|
</a>
|
|
<a href="/product/kubernetes" class="product-card group flex h-full items-start gap-3 rounded-xl border border-transparent p-3 text-left transition-colors duration-150 hover:border-indigo-200 hover:bg-indigo-50/40" data-search="kubernetes cluster pod observability k8s">
|
|
<div class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-cyan-50 ring-1 ring-cyan-200">
|
|
<!-- Kubernetes Icon - Helm wheel -->
|
|
<svg class="h-5 w-5 text-cyan-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<polygon stroke-linecap="round" stroke-linejoin="round" points="12,2.5 19.43,6.08 21.26,14.11 15.95,20.64 8.05,20.56 2.74,14.27 4.57,6.22"></polygon>
|
|
<circle cx="12" cy="12" r="2.2" stroke-linecap="round" stroke-linejoin="round"></circle>
|
|
<line x1="12" y1="9.8" x2="12" y2="4" stroke-linecap="round"></line>
|
|
<line x1="14.12" y1="10.24" x2="17.54" y2="6.64" stroke-linecap="round"></line>
|
|
<line x1="14.14" y1="12.49" x2="19.31" y2="13.67" stroke-linecap="round"></line>
|
|
<line x1="13.12" y1="14.0" x2="15.12" y2="18.82" stroke-linecap="round"></line>
|
|
<line x1="10.88" y1="14.0" x2="8.88" y2="18.76" stroke-linecap="round"></line>
|
|
<line x1="9.86" y1="12.49" x2="4.69" y2="13.79" stroke-linecap="round"></line>
|
|
<line x1="9.88" y1="10.24" x2="6.46" y2="6.53" stroke-linecap="round"></line>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="min-w-0 flex-1">
|
|
<p class="product-card-title truncate text-sm font-medium text-gray-900">Kubernetes</p>
|
|
<p class="mt-0.5 text-xs leading-relaxed text-gray-500 line-clamp-2">Cluster & pod observability</p>
|
|
</div>
|
|
</a>
|
|
<a href="/product/docker" class="product-card group flex h-full items-start gap-3 rounded-xl border border-transparent p-3 text-left transition-colors duration-150 hover:border-indigo-200 hover:bg-indigo-50/40" data-search="docker host container observability">
|
|
<div class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-blue-50 ring-1 ring-blue-200">
|
|
<!-- Docker Icon - Container stack -->
|
|
<svg class="h-5 w-5 text-blue-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<rect x="3" y="10" width="3" height="3" rx="0.3" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<rect x="6.5" y="10" width="3" height="3" rx="0.3" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<rect x="10" y="10" width="3" height="3" rx="0.3" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<rect x="13.5" y="10" width="3" height="3" rx="0.3" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<rect x="6.5" y="6.5" width="3" height="3" rx="0.3" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<rect x="10" y="6.5" width="3" height="3" rx="0.3" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<rect x="13.5" y="6.5" width="3" height="3" rx="0.3" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<rect x="10" y="3" width="3" height="3" rx="0.3" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M2 14c1 2.5 3.5 4 7 4 5.5 0 9.5-2.5 11-7 1 0.2 2.2 0 3-0.7"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="min-w-0 flex-1">
|
|
<p class="product-card-title truncate text-sm font-medium text-gray-900">Docker</p>
|
|
<p class="mt-0.5 text-xs leading-relaxed text-gray-500 line-clamp-2">Host & container observability</p>
|
|
</div>
|
|
</a>
|
|
<a href="/product/podman" class="product-card group flex h-full items-start gap-3 rounded-xl border border-transparent p-3 text-left transition-colors duration-150 hover:border-indigo-200 hover:bg-indigo-50/40" data-search="podman host container observability">
|
|
<div class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-blue-50 ring-1 ring-blue-200">
|
|
<!-- Podman Icon - seal mascot's face inside the octagon from Podman's emblem. The official artwork (a mother seal flanked by two pups, with whiskers and water lines) turns to mush below ~48px, and this partial renders at h-3.5 to h-5, so this keeps only the cues that survive: the octagonal frame, the brow arches, the eyes and the round muzzle. Mirrors IconProp.Podman in Common/UI/Components/Icon/Icon.tsx. -->
|
|
<svg class="h-5 w-5 text-blue-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<!-- Octagonal frame of the emblem, doubling as the seal's head -->
|
|
<path d="M15.79 2.85H8.21L2.85 8.21v7.58l5.36 5.36h7.58l5.36-5.36V8.21Z" stroke-linejoin="round"></path>
|
|
<!-- Brow arches -->
|
|
<path d="M7.7 8.3C8.2 7.7 9.2 7.6 9.9 8M16.3 8.3C15.8 7.7 14.8 7.6 14.1 8" stroke-width="1.2" stroke-linecap="round"></path>
|
|
<!-- Eyes -->
|
|
<circle cx="9.1" cy="10.7" r="1.25" fill="currentColor" stroke="none"></circle>
|
|
<circle cx="14.9" cy="10.7" r="1.25" fill="currentColor" stroke="none"></circle>
|
|
<!-- Muzzle and nose -->
|
|
<circle cx="12" cy="15.2" r="2.6"></circle>
|
|
<circle cx="12" cy="14.35" r="0.6" fill="currentColor" stroke="none"></circle>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="min-w-0 flex-1">
|
|
<p class="product-card-title truncate text-sm font-medium text-gray-900">Podman</p>
|
|
<p class="mt-0.5 text-xs leading-relaxed text-gray-500 line-clamp-2">Host & container observability</p>
|
|
</div>
|
|
</a>
|
|
<a href="/product/host" class="product-card group flex h-full items-start gap-3 rounded-xl border border-transparent p-3 text-left transition-colors duration-150 hover:border-indigo-200 hover:bg-indigo-50/40" data-search="hosts auto-discovered server metrics">
|
|
<div class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-slate-50 ring-1 ring-slate-200">
|
|
<!-- Host Icon - Stacked servers -->
|
|
<svg class="h-5 w-5 text-slate-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<rect x="3.5" y="4" width="17" height="6" rx="1" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<rect x="3.5" y="14" width="17" height="6" rx="1" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<circle cx="7" cy="7" r="0.6" fill="currentColor"></circle>
|
|
<circle cx="7" cy="17" r="0.6" fill="currentColor"></circle>
|
|
<line x1="10" y1="7" x2="17" y2="7" stroke-linecap="round"></line>
|
|
<line x1="10" y1="17" x2="17" y2="17" stroke-linecap="round"></line>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="min-w-0 flex-1">
|
|
<p class="product-card-title truncate text-sm font-medium text-gray-900">Hosts</p>
|
|
<p class="mt-0.5 text-xs leading-relaxed text-gray-500 line-clamp-2">Auto-discovered server metrics</p>
|
|
</div>
|
|
</a>
|
|
<a href="/product/proxmox" class="product-card group flex h-full items-start gap-3 rounded-xl border border-transparent p-3 text-left transition-colors duration-150 hover:border-indigo-200 hover:bg-indigo-50/40" data-search="proxmox ve clusters vms backups">
|
|
<div class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-orange-50 ring-1 ring-orange-200">
|
|
<!-- Proxmox Icon - official Proxmox logo mark (Simple Icons, CC0) -->
|
|
<svg class="h-5 w-5 text-orange-600" fill="currentColor" stroke="none" viewBox="0 0 24 24">
|
|
<path d="M4.928 1.825c-1.09.553-1.09.64-.07 1.78 5.655 6.295 7.004 7.782 7.107 7.782.139.017 7.971-8.542 8.058-8.801.034-.07-.208-.312-.519-.536-.415-.312-.864-.433-1.712-.467-1.59-.104-2.144.242-4.115 2.455-.899 1.003-1.66 1.833-1.66 1.833-.017 0-.76-.813-1.642-1.798S8.473 2.1 8.127 1.91c-.796-.45-2.421-.484-3.2-.086zM1.297 4.367C.45 4.695 0 5.007 0 5.248c0 .121 1.331 1.678 2.94 3.459 1.625 1.78 2.939 3.268 2.939 3.302 0 .035-1.331 1.522-2.94 3.303C1.314 17.11.017 18.683.035 18.822c.086.467 1.504 1.055 2.541 1.055 1.678-.018 2.058-.312 5.603-4.202 1.78-1.954 3.233-3.614 3.233-3.666 0-.069-1.435-1.694-3.199-3.63-2.3-2.508-3.423-3.632-3.96-3.874-.812-.398-2.126-.467-2.956-.138zm18.467.12c-.502.26-1.764 1.505-3.943 3.891-1.763 1.937-3.199 3.562-3.199 3.631 0 .07 1.453 1.712 3.234 3.666 3.544 3.89 3.925 4.184 5.602 4.202 1.038 0 2.455-.588 2.542-1.055.017-.156-1.28-1.712-2.905-3.493-1.608-1.78-2.94-3.285-2.94-3.32 0-.034 1.332-1.539 2.94-3.32C22.72 6.91 24.017 5.352 24 5.214c-.087-.45-1.366-.968-2.473-1.038-.795-.034-1.21.035-1.763.312zM7.954 16.973c-2.144 2.369-3.908 4.374-3.943 4.46-.034.07.208.312.52.537.414.311.864.432 1.711.467 1.574.103 2.161-.26 4.15-2.508.864-.968 1.608-1.78 1.625-1.78s.761.812 1.643 1.798c2.023 2.248 2.559 2.576 4.132 2.49.848-.035 1.297-.156 1.712-.467.311-.225.553-.467.519-.536-.087-.26-7.92-8.819-8.058-8.801-.069 0-1.867 1.954-4.011 4.34z"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="min-w-0 flex-1">
|
|
<p class="product-card-title truncate text-sm font-medium text-gray-900">Proxmox</p>
|
|
<p class="mt-0.5 text-xs leading-relaxed text-gray-500 line-clamp-2">VE clusters, VMs & backups</p>
|
|
</div>
|
|
</a>
|
|
<a href="/product/vmware" class="product-card group flex h-full items-start gap-3 rounded-xl border border-transparent p-3 text-left transition-colors duration-150 hover:border-indigo-200 hover:bg-indigo-50/40" data-search="vmware vsphere vcenter esxi hosts vms virtual machines datastores vsan clusters resource pools">
|
|
<div class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-indigo-50 ring-1 ring-indigo-200">
|
|
<!-- VMware Icon - neutral hypervisor mark (host chassis with three virtual machines on the hypervisor layer). Drawn in-house to match the dashboard IconProp.VMware; not the VMware wordmark. VMware is a trademark of Broadcom Inc. -->
|
|
<svg class="h-5 w-5 text-indigo-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<rect x="3" y="4" width="18" height="16" rx="2" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<path stroke-linecap="round" d="M3 16h18"></path>
|
|
<rect x="6" y="7" width="3" height="6" rx="0.75" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<rect x="10.5" y="7" width="3" height="6" rx="0.75" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<rect x="15" y="7" width="3" height="6" rx="0.75" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="min-w-0 flex-1">
|
|
<p class="product-card-title truncate text-sm font-medium text-gray-900">VMware</p>
|
|
<p class="mt-0.5 text-xs leading-relaxed text-gray-500 line-clamp-2">vCenter, ESXi hosts, VMs & datastores</p>
|
|
</div>
|
|
</a>
|
|
<a href="/product/ai-observability" class="product-card group flex h-full items-start gap-3 rounded-xl border border-transparent p-3 text-left transition-colors duration-150 hover:border-indigo-200 hover:bg-indigo-50/40" data-search="ai llm observability gen_ai openai anthropic tokens cost prompts agents">
|
|
<div class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-violet-50 ring-1 ring-violet-200">
|
|
<!-- AI / LLM Observability Icon - sparkles mark -->
|
|
<svg class="h-5 w-5 text-violet-600" fill="none" stroke="currentColor" stroke-width="1.6" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M9.813 3.75 11 6.75l3 1.187-3 1.188-1.188 3-1.187-3-3-1.188 3-1.187 1.187-3Z" />
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M17.5 11.5 18.5 14l2.5 1-2.5 1-1 2.5-1-2.5-2.5-1 2.5-1 1-2.5Z" />
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="min-w-0 flex-1">
|
|
<p class="product-card-title truncate text-sm font-medium text-gray-900">AI / LLM Observability</p>
|
|
<p class="mt-0.5 text-xs leading-relaxed text-gray-500 line-clamp-2">Tokens, cost, traces & prompts</p>
|
|
</div>
|
|
</a>
|
|
<a href="/product/ceph" class="product-card group flex h-full items-start gap-3 rounded-xl border border-transparent p-3 text-left transition-colors duration-150 hover:border-indigo-200 hover:bg-indigo-50/40" data-search="ceph storage cluster health">
|
|
<div class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-red-50 ring-1 ring-red-200">
|
|
<!-- Ceph Icon - official Ceph logo mark (Simple Icons, CC0) -->
|
|
<svg class="h-5 w-5 text-red-600" fill="currentColor" stroke="none" viewBox="0 0 24 24">
|
|
<path d="M11.959.257A11.912 11.912 0 003.503 3.76 11.92 11.92 0 000 12.217a11.934 11.934 0 001.207 5.243c.72 1.474 1.888 2.944 3.208 4.044.86-.47 1.35-.99 1.453-1.545.1-.533-.134-1.107-.737-1.805a9.031 9.031 0 01-2.219-5.937c0-4.988 4.058-9.047 9.047-9.047h.08c4.99 0 9.048 4.059 9.048 9.047a9.03 9.03 0 01-2.218 5.936c-.599.693-.84 1.292-.735 1.83.108.556.595 1.068 1.449 1.522 1.322-1.1 2.489-2.57 3.209-4.046A11.898 11.898 0 0024 12.217a11.929 11.929 0 00-3.503-8.457A11.923 11.923 0 0012.04.257h-.041zm-.005 4.837a7.072 7.072 0 00-3.76 1.075A7.202 7.202 0 006.15 8.093a7.164 7.164 0 00-1.161 2.65 7.188 7.188 0 00.04 3.125 7.14 7.14 0 001.22 2.607c.154.207.326.396.509.597l.185.202.005.006c.007.007.017.016.026.027.635.738.957 1.533.957 2.36a3.4 3.4 0 01-1.788 2.989 11.924 11.924 0 002.685 1.087c.14-.088.614-.441 1.077-1.083a4.899 4.899 0 00.94-2.99 6.595 6.595 0 00-.49-2.37 6.717 6.717 0 00-1.302-2.033l-.002-.004-.124-.142c-.21-.245-.428-.497-.602-.792a4.104 4.104 0 01-.462-1.135 4.258 4.258 0 01-.024-1.85 4.25 4.25 0 01.686-1.564 4.216 4.216 0 013.432-1.773H12.042a4.202 4.202 0 013.432 1.773c.33.466.568 1.007.686 1.565a4.27 4.27 0 01-.023 1.849c-.093.39-.249.772-.463 1.135-.173.295-.391.547-.602.792l-.123.142-.004.004a6.736 6.736 0 00-1.301 2.033 6.607 6.607 0 00-.49 2.37 4.897 4.897 0 00.94 2.99c.463.642.937.995 1.076 1.083a11.776 11.776 0 002.687-1.087 3.399 3.399 0 01-1.789-2.988c0-.817.313-1.59.956-2.359.009-.012.02-.022.027-.03l.006-.004.184-.204c.183-.2.355-.39.51-.596a7.14 7.14 0 001.22-2.608 7.21 7.21 0 00.04-3.124 7.185 7.185 0 00-1.16-2.65 7.203 7.203 0 00-2.044-1.924 7.074 7.074 0 00-3.762-1.075h-.09zM12 9.97a2.365 2.365 0 00-2.362 2.361A2.364 2.364 0 0012 14.691c1.301 0 2.36-1.059 2.36-2.36A2.364 2.364 0 0012 9.968z"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="min-w-0 flex-1">
|
|
<p class="product-card-title truncate text-sm font-medium text-gray-900">Ceph</p>
|
|
<p class="mt-0.5 text-xs leading-relaxed text-gray-500 line-clamp-2">Storage cluster health</p>
|
|
</div>
|
|
</a>
|
|
<a href="/product/docker-swarm" class="product-card group flex h-full items-start gap-3 rounded-xl border border-transparent p-3 text-left transition-colors duration-150 hover:border-indigo-200 hover:bg-indigo-50/40" data-search="docker swarm nodes services tasks stacks">
|
|
<div class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-blue-50 ring-1 ring-blue-200">
|
|
<!-- Docker Swarm Icon - Generic container cluster of connected nodes (not the official Docker logo) -->
|
|
<svg class="h-5 w-5 text-blue-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<rect x="9.5" y="2.5" width="5" height="5" rx="0.75" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<rect x="3" y="14" width="5" height="5" rx="0.75" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<rect x="9.5" y="14" width="5" height="5" rx="0.75" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<rect x="16" y="14" width="5" height="5" rx="0.75" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<line x1="12" y1="7.5" x2="12" y2="14" stroke-linecap="round"></line>
|
|
<line x1="11" y1="9.5" x2="5.5" y2="14" stroke-linecap="round"></line>
|
|
<line x1="13" y1="9.5" x2="18.5" y2="14" stroke-linecap="round"></line>
|
|
<circle cx="12" cy="5" r="0.6" fill="currentColor"></circle>
|
|
<circle cx="5.5" cy="16.5" r="0.6" fill="currentColor"></circle>
|
|
<circle cx="12" cy="16.5" r="0.6" fill="currentColor"></circle>
|
|
<circle cx="18.5" cy="16.5" r="0.6" fill="currentColor"></circle>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="min-w-0 flex-1">
|
|
<p class="product-card-title truncate text-sm font-medium text-gray-900">Docker Swarm</p>
|
|
<p class="mt-0.5 text-xs leading-relaxed text-gray-500 line-clamp-2">Nodes, services, tasks & stacks</p>
|
|
</div>
|
|
</a>
|
|
<a href="/product/iot" class="product-card group flex h-full items-start gap-3 rounded-xl border border-transparent p-3 text-left transition-colors duration-150 hover:border-indigo-200 hover:bg-indigo-50/40" data-search="iot devices fleets sensors gateways battery signal telemetry">
|
|
<div class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-teal-50 ring-1 ring-teal-200">
|
|
<!-- IoT Devices Icon - CPU chip (Heroicons, MIT) -->
|
|
<svg class="h-5 w-5 text-teal-600" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.7">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M8.25 3v1.5M4.5 8.25H3m18 0h-1.5M4.5 12H3m18 0h-1.5m-15 3.75H3m18 0h-1.5M8.25 19.5V21M12 3v1.5m0 15V21m3.75-18v1.5m0 15V21m-9-1.5h10.5a2.25 2.25 0 0 0 2.25-2.25V6.75a2.25 2.25 0 0 0-2.25-2.25H6.75A2.25 2.25 0 0 0 4.5 6.75v10.5a2.25 2.25 0 0 0 2.25 2.25Zm.75-12h9v9h-9v-9Z" />
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="min-w-0 flex-1">
|
|
<p class="product-card-title truncate text-sm font-medium text-gray-900">IoT Devices</p>
|
|
<p class="mt-0.5 text-xs leading-relaxed text-gray-500 line-clamp-2">Fleets, sensors & gateways</p>
|
|
</div>
|
|
</a>
|
|
<a href="/product/network-monitoring" class="product-card group flex h-full items-start gap-3 rounded-xl border border-transparent p-3 text-left transition-colors duration-150 hover:border-indigo-200 hover:bg-indigo-50/40" data-search="network devices snmp switches routers firewalls interfaces lldp topology latency">
|
|
<div class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-sky-50 ring-1 ring-sky-200">
|
|
<!-- Network Devices Icon - switch with uplinks -->
|
|
<svg class="h-5 w-5 text-sky-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<rect x="3" y="13.5" width="18" height="6" rx="1" stroke-linecap="round" stroke-linejoin="round"></rect>
|
|
<circle cx="6.5" cy="16.5" r="0.6" fill="currentColor"></circle>
|
|
<line x1="9.5" y1="16.5" x2="12.5" y2="16.5" stroke-linecap="round"></line>
|
|
<line x1="14.5" y1="16.5" x2="17.5" y2="16.5" stroke-linecap="round"></line>
|
|
<line x1="12" y1="13.5" x2="12" y2="9.5" stroke-linecap="round"></line>
|
|
<line x1="12" y1="9.5" x2="6" y2="9.5" stroke-linecap="round"></line>
|
|
<line x1="12" y1="9.5" x2="18" y2="9.5" stroke-linecap="round"></line>
|
|
<line x1="6" y1="9.5" x2="6" y2="7" stroke-linecap="round"></line>
|
|
<line x1="18" y1="9.5" x2="18" y2="7" stroke-linecap="round"></line>
|
|
<circle cx="6" cy="5.75" r="1.25" stroke-linecap="round" stroke-linejoin="round"></circle>
|
|
<circle cx="18" cy="5.75" r="1.25" stroke-linecap="round" stroke-linejoin="round"></circle>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="min-w-0 flex-1">
|
|
<p class="product-card-title truncate text-sm font-medium text-gray-900">Network Devices</p>
|
|
<p class="mt-0.5 text-xs leading-relaxed text-gray-500 line-clamp-2">Switches, routers & firewalls</p>
|
|
</div>
|
|
</a>
|
|
<a href="/product/serverless" class="product-card group flex h-full items-start gap-3 rounded-xl border border-transparent p-3 text-left transition-colors duration-150 hover:border-indigo-200 hover:bg-indigo-50/40" data-search="serverless functions cold starts lambda">
|
|
<div class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-fuchsia-50 ring-1 ring-fuchsia-200">
|
|
<!-- Serverless Icon - Lightning bolt (functions) -->
|
|
<svg class="h-5 w-5 text-fuchsia-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 13.5l10.5-11.25L12 10.5h8.25L9.75 21.75 12 13.5H3.75z"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="min-w-0 flex-1">
|
|
<p class="product-card-title truncate text-sm font-medium text-gray-900">Serverless</p>
|
|
<p class="mt-0.5 text-xs leading-relaxed text-gray-500 line-clamp-2">Functions & cold starts</p>
|
|
</div>
|
|
</a>
|
|
<a href="/product/cloud" class="product-card group flex h-full items-start gap-3 rounded-xl border border-transparent p-3 text-left transition-colors duration-150 hover:border-indigo-200 hover:bg-indigo-50/40" data-search="cloud aws gcp azure">
|
|
<div class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-sky-50 ring-1 ring-sky-200">
|
|
<!-- Cloud Icon -->
|
|
<svg class="h-5 w-5 text-sky-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 15a4.5 4.5 0 004.5 4.5H18a3.75 3.75 0 001.332-7.257 3 3 0 00-3.758-3.848 5.25 5.25 0 00-10.233 2.33A4.502 4.502 0 002.25 15z"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="min-w-0 flex-1">
|
|
<p class="product-card-title truncate text-sm font-medium text-gray-900">Cloud</p>
|
|
<p class="mt-0.5 text-xs leading-relaxed text-gray-500 line-clamp-2">AWS, GCP & Azure</p>
|
|
</div>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Automation & Analytics -->
|
|
<div class="product-group mb-1">
|
|
<h3 class="mb-2.5 px-1 text-[11px] font-semibold uppercase tracking-[0.1em] text-gray-500">Automation & Analytics</h3>
|
|
<div class="grid grid-cols-1 gap-2 sm:grid-cols-2 lg:grid-cols-3">
|
|
<a href="/product/workflows" class="product-card group flex h-full items-start gap-3 rounded-xl border border-transparent p-3 text-left transition-colors duration-150 hover:border-indigo-200 hover:bg-indigo-50/40" data-search="workflows no-code automation builder">
|
|
<div class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-sky-50 ring-1 ring-sky-200">
|
|
<!-- Workflows Icon - Flow diagram (rotated 180°) -->
|
|
<svg class="h-5 w-5 text-sky-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24" style="transform: rotate(180deg)">
|
|
<rect x="3" y="3" width="6" height="4" rx="1" stroke-width="1.5"></rect>
|
|
<rect x="15" y="3" width="6" height="4" rx="1" stroke-width="1.5"></rect>
|
|
<rect x="9" y="17" width="6" height="4" rx="1" stroke-width="1.5"></rect>
|
|
<path stroke-linecap="round" d="M6 7v3a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V7M12 12v5"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="min-w-0 flex-1">
|
|
<p class="product-card-title truncate text-sm font-medium text-gray-900">Workflows</p>
|
|
<p class="mt-0.5 text-xs leading-relaxed text-gray-500 line-clamp-2">No-code automation builder</p>
|
|
</div>
|
|
</a>
|
|
<a href="/product/runbooks" class="product-card group flex h-full items-start gap-3 rounded-xl border border-transparent p-3 text-left transition-colors duration-150 hover:border-indigo-200 hover:bg-indigo-50/40" data-search="runbooks auto-trigger response steps">
|
|
<div class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-teal-50 ring-1 ring-teal-200">
|
|
<!-- Runbooks Icon - Document with checklist -->
|
|
<svg class="h-5 w-5 text-teal-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M9 8l1.2 1.2L13 6.5"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="min-w-0 flex-1">
|
|
<p class="product-card-title truncate text-sm font-medium text-gray-900">Runbooks</p>
|
|
<p class="mt-0.5 text-xs leading-relaxed text-gray-500 line-clamp-2">Auto-trigger response steps</p>
|
|
</div>
|
|
</a>
|
|
<a href="/product/dashboards" class="product-card group flex h-full items-start gap-3 rounded-xl border border-transparent p-3 text-left transition-colors duration-150 hover:border-indigo-200 hover:bg-indigo-50/40" data-search="dashboards custom data visualizations">
|
|
<div class="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-indigo-50 ring-1 ring-indigo-200">
|
|
<!-- Dashboards Icon - Pie chart -->
|
|
<svg class="h-5 w-5 text-indigo-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M10.5 6a7.5 7.5 0 107.5 7.5h-7.5V6z"></path>
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M13.5 10.5H21A7.5 7.5 0 0013.5 3v7.5z"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="min-w-0 flex-1">
|
|
<p class="product-card-title truncate text-sm font-medium text-gray-900">Dashboards</p>
|
|
<p class="mt-0.5 text-xs leading-relaxed text-gray-500 line-clamp-2">Custom data visualizations</p>
|
|
</div>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Empty state -->
|
|
<div id="product-modal-empty" style="display:none;" class="flex-col items-center justify-center py-16 text-center">
|
|
<div class="mb-3 flex h-12 w-12 items-center justify-center rounded-full bg-gray-50 ring-1 ring-gray-100">
|
|
<svg class="h-5 w-5 text-gray-400" fill="none" stroke="currentColor" stroke-width="1.8" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M21 21l-4.35-4.35M17 11a6 6 0 11-12 0 6 6 0 0112 0z"></path>
|
|
</svg>
|
|
</div>
|
|
<p class="text-sm font-medium text-gray-900">No products found</p>
|
|
<p id="product-modal-empty-q" class="mt-1 text-xs text-gray-500"></p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Footer -->
|
|
<div class="flex items-center justify-between gap-4 border-t border-gray-100 bg-gray-50/80 px-5 py-3 sm:px-6">
|
|
<a href="https://github.com/oneuptime/oneuptime" target="_blank" rel="noopener" class="group flex min-w-0 items-center gap-3">
|
|
<div class="flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg bg-gray-900 transition-colors group-hover:bg-gray-700">
|
|
<svg class="h-4 w-4 text-white" fill="currentColor" viewBox="0 0 24 24">
|
|
<path fill-rule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" clip-rule="evenodd"></path>
|
|
</svg>
|
|
</div>
|
|
<div class="min-w-0 text-left">
|
|
<p class="truncate text-sm font-medium text-gray-900">100% Open Source</p>
|
|
<p class="truncate text-xs text-gray-500">Self-host or use our cloud</p>
|
|
</div>
|
|
</a>
|
|
<div class="hidden flex-shrink-0 items-center gap-2 text-xs text-gray-400 md:flex">
|
|
<span class="flex items-center gap-1">
|
|
<kbd class="inline-flex h-5 min-w-[1.25rem] items-center justify-center rounded border border-gray-200 bg-white px-1 text-[11px] font-medium text-gray-500 shadow-sm">↑</kbd>
|
|
<kbd class="inline-flex h-5 min-w-[1.25rem] items-center justify-center rounded border border-gray-200 bg-white px-1 text-[11px] font-medium text-gray-500 shadow-sm">↓</kbd>
|
|
</span>
|
|
<kbd class="inline-flex h-5 min-w-[1.25rem] items-center justify-center rounded border border-gray-200 bg-white px-1 text-[11px] font-medium text-gray-500 shadow-sm">↵</kbd>
|
|
<kbd class="inline-flex h-5 min-w-[1.25rem] items-center justify-center rounded border border-gray-200 bg-white px-1 text-[11px] font-medium text-gray-500 shadow-sm">esc</kbd>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<script data-cfasync="false" src="/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js"></script><script>
|
|
|
|
let solutionsMenuTimer = null;
|
|
let resourcesMenuTimer = null;
|
|
|
|
// Closed panels must leave layout so they cannot create invisible overflow.
|
|
function closeMobileMenu() {
|
|
document.getElementById("mobile-menu").hidden = true;
|
|
document.getElementById("mobile-menu").style.visibility = "collapse";
|
|
}
|
|
|
|
function openMobileMenu() {
|
|
document.getElementById("mobile-menu").hidden = false;
|
|
document.getElementById("mobile-menu").style.visibility = "visible";
|
|
}
|
|
|
|
// ===== Products search modal (command-palette) =====
|
|
var productActiveIndex = 0;
|
|
|
|
function getVisibleProductCards() {
|
|
return Array.prototype.slice
|
|
.call(document.querySelectorAll("#product-modal .product-card"))
|
|
.filter(function (card) {
|
|
return card.style.display !== "none";
|
|
});
|
|
}
|
|
|
|
function setProductActive(index) {
|
|
var cards = getVisibleProductCards();
|
|
if (cards.length === 0) {
|
|
productActiveIndex = -1;
|
|
return;
|
|
}
|
|
if (index < 0) {
|
|
index = 0;
|
|
}
|
|
if (index > cards.length - 1) {
|
|
index = cards.length - 1;
|
|
}
|
|
productActiveIndex = index;
|
|
cards.forEach(function (card, i) {
|
|
if (i === index) {
|
|
card.classList.add("border-indigo-300", "bg-indigo-50", "shadow-sm");
|
|
card.classList.remove("border-transparent");
|
|
card.scrollIntoView({ block: "nearest" });
|
|
} else {
|
|
card.classList.remove("border-indigo-300", "bg-indigo-50", "shadow-sm");
|
|
card.classList.add("border-transparent");
|
|
}
|
|
});
|
|
}
|
|
|
|
function highlightProductMatches(query) {
|
|
document
|
|
.querySelectorAll("#product-modal .product-card-title")
|
|
.forEach(function (el) {
|
|
var text = el.getAttribute("data-text");
|
|
if (text === null) {
|
|
text = el.textContent;
|
|
el.setAttribute("data-text", text);
|
|
}
|
|
if (!query) {
|
|
el.textContent = text;
|
|
return;
|
|
}
|
|
var idx = text.toLowerCase().indexOf(query);
|
|
if (idx === -1) {
|
|
el.textContent = text;
|
|
return;
|
|
}
|
|
el.textContent = "";
|
|
el.appendChild(document.createTextNode(text.slice(0, idx)));
|
|
var mark = document.createElement("mark");
|
|
mark.className = "rounded-sm bg-yellow-100 px-0.5 text-inherit";
|
|
mark.textContent = text.slice(idx, idx + query.length);
|
|
el.appendChild(mark);
|
|
el.appendChild(document.createTextNode(text.slice(idx + query.length)));
|
|
});
|
|
}
|
|
|
|
function filterProductModal() {
|
|
var input = document.getElementById("product-modal-search");
|
|
var query = (input.value || "").trim().toLowerCase();
|
|
var anyVisible = false;
|
|
|
|
document
|
|
.querySelectorAll("#product-modal .product-card")
|
|
.forEach(function (card) {
|
|
var hay = card.getAttribute("data-search") || "";
|
|
var match = !query || hay.indexOf(query) !== -1;
|
|
card.style.display = match ? "" : "none";
|
|
if (match) {
|
|
anyVisible = true;
|
|
}
|
|
});
|
|
|
|
document
|
|
.querySelectorAll("#product-modal .product-group")
|
|
.forEach(function (group) {
|
|
var visible =
|
|
group.querySelectorAll(".product-card").length > 0 &&
|
|
Array.prototype.slice
|
|
.call(group.querySelectorAll(".product-card"))
|
|
.some(function (card) {
|
|
return card.style.display !== "none";
|
|
});
|
|
group.style.display = visible ? "" : "none";
|
|
});
|
|
|
|
// Featured banner only shows while idle (no search query).
|
|
var featured = document.getElementById("product-modal-featured");
|
|
if (featured) {
|
|
featured.style.display = query ? "none" : "";
|
|
}
|
|
|
|
var empty = document.getElementById("product-modal-empty");
|
|
empty.style.display = anyVisible ? "none" : "flex";
|
|
document.getElementById("product-modal-empty-q").textContent = query
|
|
? "“" + query + "”"
|
|
: "";
|
|
|
|
var clear = document.getElementById("product-modal-clear");
|
|
clear.style.display = query ? "inline-flex" : "none";
|
|
document.getElementById("product-modal-kbd").style.display = query
|
|
? "none"
|
|
: "";
|
|
|
|
highlightProductMatches(query);
|
|
setProductActive(0);
|
|
}
|
|
|
|
function clearProductSearch() {
|
|
var input = document.getElementById("product-modal-search");
|
|
input.value = "";
|
|
filterProductModal();
|
|
input.focus();
|
|
}
|
|
|
|
function openProductModal() {
|
|
var modal = document.getElementById("product-modal");
|
|
if (!modal) {
|
|
return;
|
|
}
|
|
var input = document.getElementById("product-modal-search");
|
|
input.value = "";
|
|
filterProductModal();
|
|
modal.classList.remove("hidden");
|
|
document.body.style.overflow = "hidden";
|
|
requestAnimationFrame(function () {
|
|
var backdrop = document.getElementById("product-modal-backdrop");
|
|
backdrop.classList.add("opacity-100");
|
|
backdrop.classList.remove("opacity-0");
|
|
var card = document.getElementById("product-modal-card");
|
|
card.classList.add("opacity-100", "translate-y-0", "scale-100");
|
|
card.classList.remove("opacity-0", "translate-y-2", "scale-[0.98]");
|
|
});
|
|
setTimeout(function () {
|
|
input.focus();
|
|
}, 60);
|
|
}
|
|
|
|
function closeProductModal() {
|
|
var modal = document.getElementById("product-modal");
|
|
if (!modal || modal.classList.contains("hidden")) {
|
|
return;
|
|
}
|
|
var backdrop = document.getElementById("product-modal-backdrop");
|
|
backdrop.classList.add("opacity-0");
|
|
backdrop.classList.remove("opacity-100");
|
|
var card = document.getElementById("product-modal-card");
|
|
card.classList.add("opacity-0", "translate-y-2", "scale-[0.98]");
|
|
card.classList.remove("opacity-100", "translate-y-0", "scale-100");
|
|
document.body.style.overflow = "";
|
|
setTimeout(function () {
|
|
modal.classList.add("hidden");
|
|
}, 200);
|
|
}
|
|
|
|
function moveProductVertical(direction) {
|
|
var cards = getVisibleProductCards();
|
|
if (cards.length === 0) {
|
|
return;
|
|
}
|
|
var active = cards[productActiveIndex] || cards[0];
|
|
var activeRect = active.getBoundingClientRect();
|
|
var activeCenterX = activeRect.left + activeRect.width / 2;
|
|
|
|
var targetTop = null;
|
|
cards.forEach(function (card) {
|
|
var top = card.getBoundingClientRect().top;
|
|
if (direction === "down" && top > activeRect.top + 1) {
|
|
if (targetTop === null || top < targetTop) {
|
|
targetTop = top;
|
|
}
|
|
}
|
|
if (direction === "up" && top < activeRect.top - 1) {
|
|
if (targetTop === null || top > targetTop) {
|
|
targetTop = top;
|
|
}
|
|
}
|
|
});
|
|
if (targetTop === null) {
|
|
return;
|
|
}
|
|
|
|
var bestIndex = productActiveIndex;
|
|
var bestDistance = Infinity;
|
|
cards.forEach(function (card, i) {
|
|
var rect = card.getBoundingClientRect();
|
|
if (Math.abs(rect.top - targetTop) <= 1) {
|
|
var centerX = rect.left + rect.width / 2;
|
|
var distance = Math.abs(centerX - activeCenterX);
|
|
if (distance < bestDistance) {
|
|
bestDistance = distance;
|
|
bestIndex = i;
|
|
}
|
|
}
|
|
});
|
|
setProductActive(bestIndex);
|
|
}
|
|
|
|
function handleProductKeydown(event) {
|
|
if (event.key === "Escape") {
|
|
event.preventDefault();
|
|
closeProductModal();
|
|
return;
|
|
}
|
|
var cards = getVisibleProductCards();
|
|
if (cards.length === 0) {
|
|
return;
|
|
}
|
|
if (event.key === "ArrowRight") {
|
|
event.preventDefault();
|
|
setProductActive(productActiveIndex + 1);
|
|
} else if (event.key === "ArrowLeft") {
|
|
event.preventDefault();
|
|
setProductActive(productActiveIndex - 1);
|
|
} else if (event.key === "ArrowDown") {
|
|
event.preventDefault();
|
|
moveProductVertical("down");
|
|
} else if (event.key === "ArrowUp") {
|
|
event.preventDefault();
|
|
moveProductVertical("up");
|
|
} else if (event.key === "Enter") {
|
|
event.preventDefault();
|
|
var card = cards[productActiveIndex] || cards[0];
|
|
if (card && card.href) {
|
|
window.location.href = card.href;
|
|
}
|
|
}
|
|
}
|
|
|
|
(function initProductModal() {
|
|
var input = document.getElementById("product-modal-search");
|
|
if (input) {
|
|
input.addEventListener("input", filterProductModal);
|
|
input.addEventListener("keydown", handleProductKeydown);
|
|
}
|
|
document.addEventListener("keydown", function (event) {
|
|
var modal = document.getElementById("product-modal");
|
|
var isOpen = modal && !modal.classList.contains("hidden");
|
|
if ((event.key === "k" || event.key === "K") && (event.metaKey || event.ctrlKey)) {
|
|
event.preventDefault();
|
|
if (isOpen) {
|
|
closeProductModal();
|
|
} else {
|
|
openProductModal();
|
|
}
|
|
} else if (event.key === "Escape" && isOpen) {
|
|
closeProductModal();
|
|
}
|
|
});
|
|
})();
|
|
|
|
function showSolutionsMenu() {
|
|
if (solutionsMenuTimer) {
|
|
clearTimeout(solutionsMenuTimer);
|
|
solutionsMenuTimer = null;
|
|
}
|
|
var menu = document.getElementById("solutions-menu");
|
|
menu.hidden = false;
|
|
menu.style.visibility = "visible";
|
|
menu.style.opacity = "1";
|
|
}
|
|
|
|
function hideSolutionsMenu() {
|
|
if (solutionsMenuTimer) {
|
|
clearTimeout(solutionsMenuTimer);
|
|
}
|
|
solutionsMenuTimer = setTimeout(() => {
|
|
var menu = document.getElementById("solutions-menu");
|
|
menu.hidden = true;
|
|
menu.style.opacity = "0";
|
|
menu.style.visibility = "collapse";
|
|
solutionsMenuTimer = null;
|
|
}, 150);
|
|
}
|
|
|
|
function showResourcesMenu() {
|
|
if (resourcesMenuTimer) {
|
|
clearTimeout(resourcesMenuTimer);
|
|
resourcesMenuTimer = null;
|
|
}
|
|
var menu = document.getElementById("resources-menu");
|
|
menu.hidden = false;
|
|
menu.style.visibility = "visible";
|
|
menu.style.opacity = "1";
|
|
}
|
|
|
|
function hideResourcesMenu() {
|
|
if (resourcesMenuTimer) {
|
|
clearTimeout(resourcesMenuTimer);
|
|
}
|
|
resourcesMenuTimer = setTimeout(() => {
|
|
var menu = document.getElementById("resources-menu");
|
|
menu.hidden = true;
|
|
menu.style.opacity = "0";
|
|
menu.style.visibility = "collapse";
|
|
resourcesMenuTimer = null;
|
|
}, 150);
|
|
}
|
|
|
|
</script>
|
|
</header>
|
|
|
|
<!-- Image lightbox overlay -->
|
|
<div class="blog-lightbox-overlay" id="lightbox-overlay">
|
|
<button class="blog-lightbox-close" aria-label="Close lightbox">
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/></svg>
|
|
</button>
|
|
<img id="lightbox-img" src="" alt="" />
|
|
</div>
|
|
|
|
<!-- Time remaining badge -->
|
|
<div class="time-remaining" id="time-remaining">
|
|
<svg class="inline w-3 h-3 mr-1" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M12 6v6l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>
|
|
<span id="time-remaining-text"></span>
|
|
</div>
|
|
|
|
<div class="relative isolate overflow-hidden bg-white">
|
|
|
|
<!-- Hero / Title Section -->
|
|
<div class="pt-20 pb-12 sm:pt-28 sm:pb-20">
|
|
<div class="mx-auto max-w-4xl px-6 lg:px-8 text-center relative">
|
|
<h1 class="text-4xl sm:text-5xl font-extrabold tracking-tight text-gray-900 leading-tight">
|
|
What are Error Budgets? A Guide to Managing Reliability
|
|
</h1>
|
|
<p class="mt-6 text-xl text-gray-600 leading-relaxed max-w-3xl mx-auto">
|
|
Error budgets are a fundamental concept in Site Reliability Engineering that help teams balance innovation with reliability.
|
|
</p>
|
|
<div class="mt-8 flex flex-wrap items-center justify-center gap-4 text-sm text-gray-500">
|
|
|
|
|
|
|
|
<div class="flex items-center gap-3">
|
|
<div class="flex -space-x-2 shrink-0">
|
|
|
|
<img loading="lazy" decoding="async" src="https://avatars.githubusercontent.com/nawazdhandala?s=64" alt="Nawaz Dhandala" title="Nawaz Dhandala" class="h-8 w-8 rounded-full ring-2 ring-white shadow-sm bg-gray-100 object-cover">
|
|
|
|
</div>
|
|
<div class="text-[11px] leading-4 text-gray-700">
|
|
<span class="font-medium">By @nawazdhandala</span>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<span class="hidden sm:inline select-none">•</span>
|
|
<span>Sep 03, 2025</span>
|
|
<span class="hidden sm:inline select-none">•</span>
|
|
|
|
<span id="reading-time" class="inline-flex items-center gap-1.5 px-3 py-1 rounded-full bg-blue-50 border border-blue-100 text-blue-600">
|
|
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" d="M12 6v6l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>
|
|
<span class="sr-only">Reading time</span>
|
|
</span>
|
|
</div>
|
|
<div class="mt-8">
|
|
|
|
|
|
<div class="flex flex-wrap gap-2">
|
|
|
|
<a href="/blog/tag/site-reliability-engineering" class="group/tag">
|
|
<span class="inline-flex items-center gap-1.5 rounded-full border border-rose-200 bg-rose-50 px-3 py-1 text-xs font-medium text-rose-700 shadow-sm hover:bg-rose-100 hover:border-rose-300 transition">
|
|
<span class="h-1.5 w-1.5 rounded-full bg-rose-400"></span>
|
|
Site Reliability Engineering </span>
|
|
</a>
|
|
|
|
<a href="/blog/tag/sre" class="group/tag">
|
|
<span class="inline-flex items-center gap-1.5 rounded-full border border-blue-200 bg-blue-50 px-3 py-1 text-xs font-medium text-blue-700 shadow-sm hover:bg-blue-100 hover:border-blue-300 transition">
|
|
<span class="h-1.5 w-1.5 rounded-full bg-blue-400"></span>
|
|
SRE </span>
|
|
</a>
|
|
|
|
<a href="/blog/tag/observability" class="group/tag">
|
|
<span class="inline-flex items-center gap-1.5 rounded-full border border-amber-200 bg-amber-50 px-3 py-1 text-xs font-medium text-amber-700 shadow-sm hover:bg-amber-100 hover:border-amber-300 transition">
|
|
<span class="h-1.5 w-1.5 rounded-full bg-amber-400"></span>
|
|
Observability </span>
|
|
</a>
|
|
|
|
<a href="/blog/tag/slo" class="group/tag">
|
|
<span class="inline-flex items-center gap-1.5 rounded-full border border-rose-200 bg-rose-50 px-3 py-1 text-xs font-medium text-rose-700 shadow-sm hover:bg-rose-100 hover:border-rose-300 transition">
|
|
<span class="h-1.5 w-1.5 rounded-full bg-rose-400"></span>
|
|
SLO </span>
|
|
</a>
|
|
|
|
<a href="/blog/tag/error-budget" class="group/tag">
|
|
<span class="inline-flex items-center gap-1.5 rounded-full border border-sky-200 bg-sky-50 px-3 py-1 text-xs font-medium text-sky-700 shadow-sm hover:bg-sky-100 hover:border-sky-300 transition">
|
|
<span class="h-1.5 w-1.5 rounded-full bg-sky-400"></span>
|
|
Error Budget </span>
|
|
</a>
|
|
|
|
<a href="/blog/tag/reliability" class="group/tag">
|
|
<span class="inline-flex items-center gap-1.5 rounded-full border border-purple-200 bg-purple-50 px-3 py-1 text-xs font-medium text-purple-700 shadow-sm hover:bg-purple-100 hover:border-purple-300 transition">
|
|
<span class="h-1.5 w-1.5 rounded-full bg-purple-400"></span>
|
|
Reliability </span>
|
|
</a>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Content -->
|
|
<div class="pb-24">
|
|
<div class="mx-auto max-w-4xl px-6 lg:px-8">
|
|
<div class="relative" id="content-wrapper">
|
|
<!-- Floating TOC -->
|
|
<div class="floating-toc hidden xl:block" id="floating-toc">
|
|
<div class="floating-toc-inner">
|
|
<h2 class="text-xs font-semibold tracking-wider text-blue-600 uppercase mb-3 flex items-center gap-2">
|
|
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h7"/></svg>
|
|
On this page
|
|
</h2>
|
|
<nav id="toc" aria-label="Table of contents" class="overflow-y-auto max-h-[50vh] pr-1"></nav>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Main content -->
|
|
<article>
|
|
<div class="relative">
|
|
<div class="floating-share hidden xl:flex" aria-label="Share this article">
|
|
<a title="Share on X" target="_blank" rel="noopener" href="https://twitter.com/intent/tweet?text=%20What%20are%20Error%20Budgets%3F%20A%20Guide%20to%20Managing%20Reliability&url=https%3A%2F%2Foneuptime.com%2Fblog%2Fpost%2F2025-09-03-what-are-error-budgets%2Fview">
|
|
<svg class="w-4 h-4" viewBox="0 0 24 24" fill="currentColor"><path d="M17.53 3h3.77l-8.26 9.45L23 21h-6.17l-4.8-6.01L6.4 21H2.62l8.63-9.87L1 3h6.32l4.33 5.41L17.53 3Zm-1.33 15.62h2.09L7.94 4.29H5.71l10.49 14.33Z"/></svg>
|
|
</a>
|
|
<a title="Share on LinkedIn" target="_blank" rel="noopener" href="https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Foneuptime.com%2Fblog%2Fpost%2F2025-09-03-what-are-error-budgets%2Fview">
|
|
<svg class="w-4 h-4" viewBox="0 0 24 24" fill="currentColor"><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.049c.476-.9 1.637-1.85 3.37-1.85 3.601 0 4.266 2.37 4.266 5.455v6.286ZM5.337 7.433a2.062 2.062 0 1 1 0-4.124 2.062 2.062 0 0 1 0 4.124ZM7.119 20.452H3.553V9h3.566v11.452ZM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003Z"/></svg>
|
|
</a>
|
|
<a title="Discuss on Hacker News" target="_blank" rel="noopener" href="https://news.ycombinator.com/submitlink?u=https%3A%2F%2Foneuptime.com%2Fblog%2Fpost%2F2025-09-03-what-are-error-budgets%2Fview&t=%20What%20are%20Error%20Budgets%3F%20A%20Guide%20to%20Managing%20Reliability">
|
|
<svg class="w-4 h-4" viewBox="0 0 24 24" aria-hidden="true">
|
|
<circle cx="12" cy="12" r="10" fill="currentColor" opacity="0.92"></circle>
|
|
<path d="M7.2 6.2L12 12.8l4.8-6.6M12 13.4V17.8" fill="none" stroke="#ffffff" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"></path>
|
|
</svg>
|
|
</a>
|
|
<button title="Copy link" class="copy-link-btn" data-url="https://oneuptime.com/blog/post/2025-09-03-what-are-error-budgets/view">
|
|
<svg class="w-4 h-4 copy-link-icon" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"/></svg>
|
|
<svg class="w-4 h-4 copy-link-check hidden" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7"/></svg>
|
|
</button>
|
|
</div>
|
|
<div class="blog-body prose prose-gray max-w-none prose-headings:scroll-mt-28 prose-headings:font-display prose-headings:font-semibold lg:prose-headings:scroll-mt-[8.5rem] prose-a:font-semibold prose-a:text-gray-600 hover:prose-a:text-gray-500 prose-img:rounded-xl prose-pre:rounded-xl prose-code:text-gray-600">
|
|
<p class="mt-5 mb-2 leading-8 text-gray-600 text-lg">In the world of software engineering, reliability isn't just about keeping systems running, it's about making smart trade-offs between stability and innovation. Enter error budgets: the secret weapon that helps teams like ours at OneUptime maintain high availability while shipping features at breakneck speed.</p><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg">But what exactly are error budgets? How do you manage them? And how do they differ from those familiar SLOs? Let's dive in.</p><h2 class="my-5 mt-8 text-3xl font-bold tracking-tight text-gray-800">What Are Error Budgets?</h2><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg">An error budget is the acceptable amount of downtime or errors your service can experience before it violates your Service Level Objectives (SLOs). It's essentially permission to fail- within limits.</p><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg">Think of it this way: If your SLO is 99.9% uptime (allowing for about 8.77 hours of downtime per year), your error budget is that 8.77 hours. As long as you stay within that budget, you're meeting your reliability targets.</p><blockquote class="p-4 pt-1 pb-1 my-4 border-s-4 border-indigo-500">
|
|
<div class="leading-8 text-gray-600"><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg">"Error budgets give teams the freedom to innovate while maintaining accountability for reliability."</p></div>
|
|
</blockquote><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg">The concept originated at Google as part of their Site Reliability Engineering (SRE) practices. </p><blockquote class="p-4 pt-1 pb-1 my-4 border-s-4 border-indigo-500">
|
|
<div class="leading-8 text-gray-600"><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg">Instead of aiming for 100% uptime (which is often unrealistic and expensive), SRE teams define acceptable failure rates and use error budgets to track them.</p></div>
|
|
</blockquote><h2 class="my-5 mt-8 text-3xl font-bold tracking-tight text-gray-800">How Error Budgets Differ from SLOs</h2><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg">While SLOs and error budgets are closely related, they're not the same thing:</p><ul class="list-disc pl-6 my-6 space-y-2 text-gray-700"><li class="leading-7"><strong class="font-semibold text-gray-800">SLOs</strong> define what "good" looks like (e.g., "99.9% of requests should succeed")</li><li class="leading-7"><strong class="font-semibold text-gray-800">Error budgets</strong> quantify how much "bad" is acceptable (e.g., "You can have 0.1% of requests fail")</li></ul><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg">SLOs are your target, error budgets are your tolerance for missing that target. If you exhaust your error budget, you're violating your SLOs.</p><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg">The key difference is in mindset: SLOs are about aspiration, error budgets are about reality. They acknowledge that perfect reliability is impossible and expensive, so they give teams breathing room to experiment and learn.</p><h2 class="my-5 mt-8 text-3xl font-bold tracking-tight text-gray-800">How to Manage Error Budgets</h2><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg">Managing error budgets effectively requires a combination of measurement, monitoring, and decision-making. Here's how to do it right:</p><h3 class="my-5 mt-8 text-2xl font-bold tracking-tight text-gray-800">1. Define Clear SLOs First</h3><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg">Before you can have an error budget, you need SLOs. Start by identifying what matters most to your users:</p><ul class="list-disc pl-6 my-6 space-y-2 text-gray-700"><li class="leading-7">What metrics indicate success for your service?</li><li class="leading-7">What level of performance would make users abandon your product?</li><li class="leading-7">What's the minimum viable reliability for your business?</li></ul><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg">For example, at OneUptime, our SLOs focus on incident detection time and resolution time, because those directly impact our customers' ability to respond to outages.</p><h3 class="my-5 mt-8 text-2xl font-bold tracking-tight text-gray-800">2. Calculate Your Error Budget</h3><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg">Once you have SLOs, calculating the error budget is straightforward. The formula below shows how to derive your acceptable failure threshold from your reliability target. This calculation is fundamental because it transforms your aspirational SLO into a concrete, measurable budget that your team can track and manage.</p><pre class="language-python rounded-md"><code class="language-python rounded-md"># Error Budget Formula
|
|
|
|
# ====================
|
|
# This calculates the maximum allowable downtime or failure rate
|
|
# that your service can experience while still meeting your SLO.
|
|
|
|
# Formula:
|
|
Error_Budget = 100% - SLO_Target
|
|
|
|
# Example calculation for a 99.9% availability SLO:
|
|
# -------------------------------------------------
|
|
SLO_Target = 99.9 # Your service level objective (percentage)
|
|
Error_Budget = 100 - SLO_Target # = 0.1%
|
|
|
|
# Convert to time (assuming 30-day month):
|
|
minutes_per_month = 30 * 24 * 60 # = 43,200 minutes
|
|
allowed_downtime_minutes = minutes_per_month * (Error_Budget / 100)
|
|
# Result: 43.2 minutes of allowed downtime per month
|
|
|
|
# Key insight: The higher your SLO, the smaller your error budget
|
|
# 99% SLO -> 1% budget -> ~7.2 hours/month
|
|
# 99.9% SLO -> 0.1% budget -> ~43 minutes/month
|
|
# 99.99% SLO -> 0.01% budget -> ~4.3 minutes/month</code></pre><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg">For a 99.9% SLO:</p><ul class="list-disc pl-6 my-6 space-y-2 text-gray-700"><li class="leading-7">Error Budget = 0.1% (or 8.77 hours per year)</li><li class="leading-7">This means you can have 0.1% of requests fail or 8.77 hours of downtime</li></ul><h3 class="my-5 mt-8 text-2xl font-bold tracking-tight text-gray-800">3. Track Burn Rate</h3><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg">Burn rate is how quickly you're consuming your error budget. It's calculated as shown below. Understanding burn rate is critical because it tells you not just whether you're failing, but how fast you're approaching your reliability limits. A high burn rate is an early warning signal that demands immediate attention before your error budget is fully exhausted.</p><pre class="language-python rounded-md"><code class="language-python rounded-md"># Burn Rate Formula
|
|
# =================
|
|
# This measures how fast you're consuming your error budget.
|
|
# It's the ratio of actual failure rate to your allowed failure rate.
|
|
|
|
# Formula:
|
|
Burn_Rate = Actual_Error_Rate / Allowed_Error_Rate
|
|
|
|
# Expanded formula:
|
|
Burn_Rate = (Actual_Errors / Total_Requests) / (Error_Budget / 100)
|
|
|
|
# Example calculation:
|
|
# --------------------
|
|
# Given: 99.9% SLO (0.1% error budget), 1,000,000 requests, 1,500 errors
|
|
total_requests = 1_000_000
|
|
actual_errors = 1_500
|
|
error_budget_percent = 0.1 # From our 99.9% SLO
|
|
|
|
actual_error_rate = actual_errors / total_requests # = 0.0015 = 0.15%
|
|
allowed_error_rate = error_budget_percent / 100 # = 0.001 = 0.1%
|
|
|
|
burn_rate = actual_error_rate / allowed_error_rate # = 1.5
|
|
|
|
# Interpretation Guide:
|
|
# ---------------------
|
|
# Burn Rate = 1.0 -> Sustainable: consuming budget at expected rate
|
|
# Burn Rate > 1.0 -> Warning: consuming budget faster than planned
|
|
# Burn Rate < 1.0 -> Healthy: room for innovation and experimentation
|
|
#
|
|
# In our example (burn_rate = 1.5):
|
|
# We're consuming budget 50% faster than sustainable.
|
|
# At this rate, a 30-day budget would be exhausted in 20 days.
|
|
|
|
# Alert thresholds (common practice):
|
|
# - Burn Rate > 2.0 for 1 hour -> Critical alert (fast burn)
|
|
# - Burn Rate > 1.0 for 6 hours -> Warning alert (slow burn)</code></pre><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg">A burn rate of 1 means you're consuming your error budget at the expected rate. Anything above 1 means you're on track to exhaust it early.</p><h3 class="my-5 mt-8 text-2xl font-bold tracking-tight text-gray-800">4. Set Up Alerts</h3><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg">Create alerts for different burn rate thresholds:</p><ul class="list-disc pl-6 my-6 space-y-2 text-gray-700"><li class="leading-7">50% of budget consumed (warning)</li><li class="leading-7">80% of budget consumed (critical)</li><li class="leading-7">100% of budget consumed (emergency)</li></ul><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg">These alerts should trigger discussions about whether to slow down feature releases or invest in reliability improvements.</p><h3 class="my-5 mt-8 text-2xl font-bold tracking-tight text-gray-800">5. Make Data-Driven Decisions</h3><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg">Use your error budget to inform development decisions:</p><ul class="list-disc pl-6 my-6 space-y-2 text-gray-700"><li class="leading-7"><strong class="font-semibold text-gray-800">Green budget</strong>: Full speed ahead on new features</li><li class="leading-7"><strong class="font-semibold text-gray-800">Yellow budget</strong>: Proceed with caution, consider reliability impact</li><li class="leading-7"><strong class="font-semibold text-gray-800">Red budget</strong>: Focus on stability, pause non-critical features</li></ul><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg">This creates a natural feedback loop where reliability becomes everyone's responsibility, not just the ops team's.</p><h2 class="my-5 mt-8 text-3xl font-bold tracking-tight text-gray-800">What to Look Out For</h2><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg">While error budgets are powerful, they're not without pitfalls. Here are the common traps to avoid:</p><h3 class="my-5 mt-8 text-2xl font-bold tracking-tight text-gray-800">1. Setting Unrealistic SLOs</h3><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg">If your SLOs are too aggressive (like 99.999% uptime), your error budget becomes tiny. This leads to constant alerts and stifles innovation. Start conservative and adjust based on real user needs.</p><h3 class="my-5 mt-8 text-2xl font-bold tracking-tight text-gray-800">2. Ignoring Seasonal Variations</h3><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg">Error budgets should account for different usage patterns. If your service sees 10x traffic during peak hours, your error budget might burn faster then. Consider time-based budgeting or adjusting SLOs seasonally.</p><h3 class="my-5 mt-8 text-2xl font-bold tracking-tight text-gray-800">3. Focusing Only on Availability</h3><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg">Error budgets aren't just about uptime. Consider other dimensions like latency, error rates, and data freshness. A service might be "up" but still violating user expectations.</p><h3 class="my-5 mt-8 text-2xl font-bold tracking-tight text-gray-800">4. Not Communicating Across Teams</h3><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg">Error budgets work best when everyone understands them. Developers need to know how their code affects reliability, and product managers need to understand the trade-offs between features and stability.</p><h3 class="my-5 mt-8 text-2xl font-bold tracking-tight text-gray-800">5. Using Error Budgets as Excuses</h3><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg">"Don't worry about that bug, we have error budget!" is not the right attitude. Error budgets are for planned risk-taking, not sloppiness. Always strive to improve reliability even when you have budget left.</p><h3 class="my-5 mt-8 text-2xl font-bold tracking-tight text-gray-800">6. Forgetting About Recovery</h3><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg">When you do exhaust your error budget, have a plan to recover. This might involve rolling back recent changes, implementing circuit breakers, or temporarily reducing functionality.</p><h2 class="my-5 mt-8 text-3xl font-bold tracking-tight text-gray-800">Real-World Examples</h2><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg">Let's look at how error budgets work in practice:</p><h3 class="my-5 mt-8 text-2xl font-bold tracking-tight text-gray-800">E-commerce Platform</h3><ul class="list-disc pl-6 my-6 space-y-2 text-gray-700"><li class="leading-7">SLO: 99.95% availability during business hours</li><li class="leading-7">Error Budget: 0.05% (about 22 minutes per month)</li><li class="leading-7">When budget is low: Team prioritizes stability over new checkout features</li></ul><h3 class="my-5 mt-8 text-2xl font-bold tracking-tight text-gray-800">API Service</h3><ul class="list-disc pl-6 my-6 space-y-2 text-gray-700"><li class="leading-7">SLO: 99.9% success rate for all endpoints</li><li class="leading-7">Error Budget: 0.1% (43.2 minutes of errors per month)</li><li class="leading-7">Burn rate monitoring helps identify problematic endpoints early</li></ul><h3 class="my-5 mt-8 text-2xl font-bold tracking-tight text-gray-800">Mobile App</h3><ul class="list-disc pl-6 my-6 space-y-2 text-gray-700"><li class="leading-7">SLO: 99% of users can complete key flows without errors</li><li class="leading-7">Error Budget: 1% (adjusted for user count)</li><li class="leading-7">Used to balance A/B testing with stability</li></ul><h2 class="my-5 mt-8 text-3xl font-bold tracking-tight text-gray-800">The Cultural Impact</h2><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg">Beyond the mechanics, error budgets change how teams think about reliability. They shift the conversation from "How do we prevent all failures?" to "How much failure can we tolerate, and how do we learn from it?"</p><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg">This mindset encourages:</p><ul class="list-disc pl-6 my-6 space-y-2 text-gray-700"><li class="leading-7">Blameless postmortems</li><li class="leading-7">Automated testing and deployment</li><li class="leading-7">Proactive monitoring and alerting</li><li class="leading-7">Cross-functional collaboration</li></ul><h2 class="my-5 mt-8 text-3xl font-bold tracking-tight text-gray-800">Getting Started</h2><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg">Ready to implement error budgets? Start small:</p><ol class="list-decimal pl-6 my-6 space-y-2 text-gray-700"><li class="leading-7">Pick one service or endpoint</li><li class="leading-7">Define realistic SLOs based on user needs</li><li class="leading-7">Calculate your error budget</li><li class="leading-7">Set up basic monitoring and alerting</li><li class="leading-7">Use the data to inform your next sprint planning</li></ol><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg">Remember, error budgets are a tool, not a goal. The real objective is delivering reliable software that delights users while enabling your business to grow.</p><blockquote class="p-4 pt-1 pb-1 my-4 border-s-4 border-indigo-500">
|
|
<div class="leading-8 text-gray-600"><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg">"Error budgets don't eliminate failures- they make failures productive."</p></div>
|
|
</blockquote><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg"><strong class="font-semibold text-gray-800">About OneUptime:</strong> We're building the next generation of observability tools to make SRE practices like error budgets accessible to every engineering team. Learn more about how we can help you implement error budgets and SLOs at <a href="https://oneuptime.com" class="font-semibold text-indigo-600 underline underline-offset-2 decoration-indigo-300 hover:decoration-indigo-500 hover:text-indigo-500 transition-colors">OneUptime.com</a>.</p><p class="mt-5 mb-2 leading-8 text-gray-600 text-lg"><strong class="font-semibold text-gray-800">Related Reading:</strong></p><ul class="list-disc pl-6 my-6 space-y-2 text-gray-700"><li class="leading-7"><a href="https://oneuptime.com/blog/post/2023-06-12-sli-sla-slo/view" class="font-semibold text-indigo-600 underline underline-offset-2 decoration-indigo-300 hover:decoration-indigo-500 hover:text-indigo-500 transition-colors">What is SLA, SLI and SLO's?</a></li><li class="leading-7"><a href="https://oneuptime.com/blog/post/2025-09-01-the-five-stages-of-sre-maturity/view" class="font-semibold text-indigo-600 underline underline-offset-2 decoration-indigo-300 hover:decoration-indigo-500 hover:text-indigo-500 transition-colors">The Five Stages of SRE Maturity: From Chaos to Operational Excellence</a></li></ul> </div>
|
|
</div>
|
|
|
|
<!-- Share -->
|
|
<div class="mt-14 border-t border-gray-200/70 pt-8 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-6">
|
|
<div class="text-sm font-medium text-gray-600">Share this article</div>
|
|
<div class="flex gap-3">
|
|
<a title="Share on X" target="_blank" rel="noopener" class="group inline-flex items-center justify-center h-9 w-9 rounded-lg border border-gray-200 hover:border-gray-400 hover:bg-gray-100 transition" href="https://twitter.com/intent/tweet?text=%20What%20are%20Error%20Budgets%3F%20A%20Guide%20to%20Managing%20Reliability&url=https%3A%2F%2Foneuptime.com%2Fblog%2Fpost%2F2025-09-03-what-are-error-budgets%2Fview">
|
|
<svg class="w-4 h-4 text-gray-500 group-hover:text-gray-600" viewBox="0 0 24 24" fill="currentColor"><path d="M17.53 3h3.77l-8.26 9.45L23 21h-6.17l-4.8-6.01L6.4 21H2.62l8.63-9.87L1 3h6.32l4.33 5.41L17.53 3Zm-1.33 15.62h2.09L7.94 4.29H5.71l10.49 14.33Z"/></svg>
|
|
</a>
|
|
<a title="Share on LinkedIn" target="_blank" rel="noopener" class="group inline-flex items-center justify-center h-9 w-9 rounded-lg border border-gray-200 hover:border-gray-400 hover:bg-gray-100 transition" href="https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Foneuptime.com%2Fblog%2Fpost%2F2025-09-03-what-are-error-budgets%2Fview">
|
|
<svg class="w-4 h-4 text-gray-500 group-hover:text-gray-600" viewBox="0 0 24 24" fill="currentColor"><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.049c.476-.9 1.637-1.85 3.37-1.85 3.601 0 4.266 2.37 4.266 5.455v6.286ZM5.337 7.433a2.062 2.062 0 1 1 0-4.124 2.062 2.062 0 0 1 0 4.124ZM7.119 20.452H3.553V9h3.566v11.452ZM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003Z"/></svg>
|
|
</a>
|
|
<a title="Discuss on Hacker News" target="_blank" rel="noopener" class="group inline-flex items-center justify-center h-9 w-9 rounded-lg border border-gray-200 hover:border-gray-400 hover:bg-gray-100 transition" href="https://news.ycombinator.com/submitlink?u=https%3A%2F%2Foneuptime.com%2Fblog%2Fpost%2F2025-09-03-what-are-error-budgets%2Fview&t=%20What%20are%20Error%20Budgets%3F%20A%20Guide%20to%20Managing%20Reliability">
|
|
<svg class="w-4 h-4 text-gray-500 group-hover:text-gray-600" viewBox="0 0 24 24" aria-hidden="true">
|
|
<circle cx="12" cy="12" r="10" fill="currentColor" opacity="0.92"></circle>
|
|
<path d="M7.2 6.2L12 12.8l4.8-6.6M12 13.4V17.8" fill="none" stroke="#ffffff" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"></path>
|
|
</svg>
|
|
</a>
|
|
<button title="Copy link" class="copy-link-btn group inline-flex items-center justify-center h-9 w-9 rounded-lg border border-gray-200 hover:border-gray-400 hover:bg-gray-100 transition" data-url="https://oneuptime.com/blog/post/2025-09-03-what-are-error-budgets/view">
|
|
<svg class="w-4 h-4 text-gray-500 group-hover:text-gray-600 copy-link-icon" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"/></svg>
|
|
<svg class="w-4 h-4 text-green-500 copy-link-check hidden" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7"/></svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Author -->
|
|
|
|
<div class="mt-16 p-6 sm:p-8 rounded-2xl bg-gradient-to-br from-gray-50 to-blue-50/30 border border-gray-200 shadow-sm hover:shadow-md hover:border-blue-200/60 transition-all duration-300">
|
|
<div class="flex flex-col sm:flex-row gap-5 sm:gap-6 items-start">
|
|
<!-- Added explicit width/height + lazy loading for below-the-fold author bio image -->
|
|
<div class="relative">
|
|
<img class="h-16 w-16 sm:h-20 sm:w-20 rounded-full ring-4 ring-white shadow-md" src="https://avatars.githubusercontent.com/nawazdhandala" alt="Nawaz Dhandala" width="80" height="80" loading="lazy" decoding="async">
|
|
<div class="absolute -bottom-1 -right-1 h-6 w-6 bg-emerald-400 rounded-full border-2 border-white flex items-center justify-center">
|
|
<svg class="w-3 h-3 text-white" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/></svg>
|
|
</div>
|
|
</div>
|
|
<div class="flex-1">
|
|
<div class="flex items-center gap-2 mb-1">
|
|
<h3 class="text-lg font-semibold text-gray-900">Nawaz Dhandala</h3>
|
|
<span class="text-xs font-medium text-blue-600 bg-blue-50 px-2 py-0.5 rounded-full">Author</span>
|
|
</div>
|
|
<p class="text-sm text-gray-500 mb-3">@nawazdhandala • Sep 03, 2025 • <span id="reading-time-inline"></span></p>
|
|
<div class="text-sm text-gray-600 leading-relaxed">Nawaz is building OneUptime with a passion for engineering reliable systems and improving observability.</div>
|
|
<div class="mt-4 flex flex-wrap gap-3">
|
|
<a href="https://github.com/nawazdhandala" target="_blank" class="text-xs font-medium text-gray-600 hover:text-gray-900 inline-flex items-center gap-1.5 px-3 py-1.5 rounded-full bg-white border border-gray-200 hover:border-gray-300 shadow-sm transition-all duration-200">
|
|
<svg class="w-3.5 h-3.5" fill="currentColor" viewBox="0 0 24 24"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg>
|
|
GitHub
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Technically validated shield + contribute (merged) -->
|
|
|
|
<div class="mt-16 rounded-2xl border border-gray-200 bg-white shadow-sm overflow-hidden">
|
|
|
|
<!-- Technically validated — subtle trust strip -->
|
|
<div class="flex flex-wrap items-center gap-x-2.5 gap-y-1 px-6 py-3 sm:px-8 border-b border-gray-100 bg-gray-50/40">
|
|
<svg class="w-4 h-4 flex-shrink-0 text-emerald-500" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
|
<path fill-rule="evenodd" d="M9.661 2.237a.531.531 0 0 1 .678 0 11.947 11.947 0 0 0 7.078 2.749.5.5 0 0 1 .479.425c.069.52.104 1.05.104 1.59 0 5.162-3.26 9.563-7.834 11.256a.48.48 0 0 1-.332 0C5.16 16.564 1.9 12.163 1.9 7c0-.538.035-1.069.104-1.589a.5.5 0 0 1 .48-.425 11.947 11.947 0 0 0 7.077-2.75ZM13.857 8.19a.75.75 0 0 0-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 1 0-1.06 1.061l2.5 2.5a.75.75 0 0 0 1.137-.089l4-5.5Z" clip-rule="evenodd"/>
|
|
</svg>
|
|
<span class="text-sm font-medium text-gray-600">Technically validated</span>
|
|
|
|
<span class="text-xs text-gray-400"><span class="select-none text-gray-300">·</span> Jun 23, 2026</span>
|
|
|
|
<button type="button" id="validation-open" data-file="2025-09-03-what-are-error-budgets" class="group ml-auto inline-flex items-center gap-1 text-xs font-medium text-gray-500 hover:text-emerald-600 transition-colors duration-200">
|
|
View report
|
|
<svg class="w-3 h-3 transition-transform duration-200 group-hover:translate-x-0.5" fill="none" stroke="currentColor" stroke-width="2.5" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" d="M9 5l7 7-7 7"/></svg>
|
|
</button>
|
|
</div>
|
|
|
|
|
|
<!-- Improve this blog post -->
|
|
<div class="px-6 py-7 sm:px-8 sm:py-8">
|
|
<div class="flex flex-col sm:flex-row gap-5 sm:gap-6 items-start">
|
|
<div class="flex-shrink-0 h-12 w-12 bg-gray-100 rounded-xl flex items-center justify-center mx-auto sm:mx-0">
|
|
<svg class="w-6 h-6 text-gray-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24" aria-hidden="true">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10" />
|
|
</svg>
|
|
</div>
|
|
<div class="flex-1 text-center sm:text-left">
|
|
<h3 class="text-base sm:text-lg font-semibold text-gray-900 mb-2">Help improve this post</h3>
|
|
<p class="text-sm text-gray-600 leading-relaxed mb-4">Every OneUptime blog post is open source. Found a typo, an inaccuracy, or have a clearer way to explain something? Anyone can contribute — your edits make this post better for everyone who reads it next.</p>
|
|
<div class="flex flex-wrap justify-center sm:justify-start gap-3">
|
|
|
|
<a href="https://github.com/oneuptime/blog/tree/master/posts/2025-09-03-what-are-error-budgets" target="_blank" rel="noopener" class="inline-flex items-center gap-2 px-4 py-2 rounded-lg bg-emerald-600 text-white text-sm font-medium hover:bg-emerald-700 shadow-sm transition-all duration-200">
|
|
<svg class="w-4 h-4" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg>
|
|
Edit this post on GitHub
|
|
</a>
|
|
|
|
<a href="https://github.com/oneuptime/blog" target="_blank" rel="noopener" class="inline-flex items-center gap-2 px-4 py-2 rounded-lg bg-white text-gray-700 text-sm font-medium border border-gray-200 hover:border-gray-300 hover:bg-gray-50 shadow-sm transition-all duration-200">
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253" /></svg>
|
|
Contributing guidelines
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</article>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<style>
|
|
.blog-cta-card {
|
|
position: relative;
|
|
z-index: 1;
|
|
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
}
|
|
.blog-cta-card:hover {
|
|
transform: translateY(-2px);
|
|
}
|
|
</style>
|
|
|
|
<div class="relative isolate overflow-hidden bg-white border-t border-gray-900/10">
|
|
<!-- Subtle grid pattern background matching hero -->
|
|
<div class="absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#f0f0f0_1px,transparent_1px),linear-gradient(to_bottom,#f0f0f0_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_50%,#000_70%,transparent_110%)]"></div>
|
|
|
|
<div class="py-24 sm:py-32">
|
|
<div class="mx-auto max-w-7xl px-6 lg:px-8">
|
|
<div class="mx-auto max-w-3xl text-center">
|
|
<!-- Open-source badge -->
|
|
<a href="https://github.com/oneuptime/oneuptime" target="_blank" class="group mb-8 inline-flex items-center gap-1.5 rounded-full bg-gray-50 px-4 py-1.5 text-sm text-gray-600 ring-1 ring-inset ring-gray-200 transition-all hover:bg-gray-100 hover:ring-gray-300">
|
|
<svg class="h-4 w-4" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
|
<path fill-rule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" clip-rule="evenodd" />
|
|
</svg>
|
|
<span>Open source</span>
|
|
<svg class="h-3.5 w-3.5 text-gray-400 transition-transform group-hover:translate-x-0.5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M9 5l7 7-7 7"></path></svg>
|
|
</a>
|
|
|
|
<!-- Main headline -->
|
|
<h2 class="text-2xl font-medium tracking-tight text-gray-900 sm:text-3xl lg:text-4xl lg:leading-[1.15]">
|
|
OneUptime is the Open-Source <br class="hidden sm:block" />Observability Platform
|
|
</h2>
|
|
|
|
<!-- Subheadline -->
|
|
<p class="mt-6 text-base leading-7 text-gray-600 sm:text-lg sm:leading-8 max-w-xl mx-auto">
|
|
Your complete reliability stack unified: infrastructure monitoring, incident management, status pages, and APM. Open-source and self-hostable.
|
|
</p>
|
|
|
|
<!-- CTA buttons -->
|
|
<div class="mt-10 flex flex-col sm:flex-row items-center justify-center gap-3 sm:gap-4">
|
|
<a href="/accounts/register"
|
|
class="w-full sm:w-auto inline-flex items-center justify-center rounded-lg bg-gray-900 px-6 py-2.5 text-sm font-medium text-white shadow-sm transition-all hover:bg-gray-700 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-900">
|
|
Get started for free
|
|
<svg class="ml-2 h-4 w-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M13 7l5 5m0 0l-5 5m5-5H6"></path></svg>
|
|
</a>
|
|
<a href="/enterprise/demo" class="w-full sm:w-auto inline-flex items-center justify-center rounded-lg bg-white px-6 py-2.5 text-sm font-medium text-gray-700 shadow-sm ring-1 ring-inset ring-gray-300 transition-all hover:bg-gray-50 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-600">
|
|
Request a demo
|
|
</a>
|
|
</div>
|
|
|
|
<!-- Product grid -->
|
|
<div class="mt-16 grid grid-cols-2 gap-4 sm:grid-cols-6 sm:gap-5 auto-rows-fr">
|
|
<!-- Status Page - Emerald -->
|
|
<a href="/product/status-page" class="blog-cta-card group flex flex-col items-center justify-center text-center rounded-2xl bg-white px-4 py-5 ring-1 ring-inset ring-gray-200 transition-all hover:ring-emerald-300 hover:shadow-[0_0_0_2px_rgb(16_185_129/0.3),0_4px_12px_-4px_rgb(16_185_129/0.15)] h-full">
|
|
<div class="flex h-11 w-11 items-center justify-center rounded-xl bg-emerald-50 ring-1 ring-emerald-200">
|
|
<!-- Status Page Icon - Checkmark in circle -->
|
|
<svg class="h-5 w-5 text-emerald-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="mt-3 text-sm font-medium text-gray-900">Status Page</div>
|
|
<div class="mt-1 text-xs text-gray-500">Real-time status updates</div>
|
|
</a>
|
|
|
|
<!-- Incidents - Rose -->
|
|
<a href="/product/incident-management" class="blog-cta-card group flex flex-col items-center justify-center text-center rounded-2xl bg-white px-4 py-5 ring-1 ring-inset ring-gray-200 transition-all hover:ring-rose-300 hover:shadow-[0_0_0_2px_rgb(244_63_94/0.3),0_4px_12px_-4px_rgb(244_63_94/0.15)] h-full">
|
|
<div class="flex h-11 w-11 items-center justify-center rounded-xl bg-rose-50 ring-1 ring-rose-200">
|
|
<!-- Incidents Icon - Warning triangle -->
|
|
<svg class="h-5 w-5 text-rose-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="mt-3 text-sm font-medium text-gray-900">Incidents</div>
|
|
<div class="mt-1 text-xs text-gray-500">Detect and resolve fast</div>
|
|
</a>
|
|
|
|
<!-- Monitoring - Blue -->
|
|
<a href="/product/monitoring" class="blog-cta-card group flex flex-col items-center justify-center text-center rounded-2xl bg-white px-4 py-5 ring-1 ring-inset ring-gray-200 transition-all hover:ring-blue-300 hover:shadow-[0_0_0_2px_rgb(59_130_246/0.3),0_4px_12px_-4px_rgb(59_130_246/0.15)] h-full">
|
|
<div class="flex h-11 w-11 items-center justify-center rounded-xl bg-blue-50 ring-1 ring-blue-200">
|
|
<!-- Monitoring Icon - Globe with grid lines -->
|
|
<svg class="h-5 w-5 text-blue-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 21a9.004 9.004 0 008.716-6.747M12 21a9.004 9.004 0 01-8.716-6.747M12 21c2.485 0 4.5-4.03 4.5-9S14.485 3 12 3m0 18c-2.485 0-4.5-4.03-4.5-9S9.515 3 12 3m0 0a8.997 8.997 0 017.843 4.582M12 3a8.997 8.997 0 00-7.843 4.582m15.686 0A11.953 11.953 0 0112 10.5c-2.998 0-5.74-1.1-7.843-2.918m15.686 0A8.959 8.959 0 0121 12c0 .778-.099 1.533-.284 2.253m0 0A17.919 17.919 0 0112 16.5c-3.162 0-6.133-.815-8.716-2.247m0 0A9.015 9.015 0 013 12c0-1.605.42-3.113 1.157-4.418"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="mt-3 text-sm font-medium text-gray-900">Monitoring</div>
|
|
<div class="mt-1 text-xs text-gray-500">Monitor any resource</div>
|
|
</a>
|
|
|
|
<!-- On-Call - Stone -->
|
|
<a href="/product/on-call" class="blog-cta-card group flex flex-col items-center justify-center text-center rounded-2xl bg-white px-4 py-5 ring-1 ring-inset ring-gray-200 transition-all hover:ring-stone-300 hover:shadow-[0_0_0_2px_rgb(120_113_108/0.3),0_4px_12px_-4px_rgb(120_113_108/0.15)] h-full">
|
|
<div class="flex h-11 w-11 items-center justify-center rounded-xl bg-stone-50 ring-1 ring-stone-200">
|
|
<!-- On-Call Icon - Phone -->
|
|
<svg class="h-5 w-5 text-stone-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 6.75c0 8.284 6.716 15 15 15h2.25a2.25 2.25 0 002.25-2.25v-1.372c0-.516-.351-.966-.852-1.091l-4.423-1.106c-.44-.11-.902.055-1.173.417l-.97 1.293c-.282.376-.769.542-1.21.38a12.035 12.035 0 01-7.143-7.143c-.162-.441.004-.928.38-1.21l1.293-.97c.363-.271.527-.734.417-1.173L6.963 3.102a1.125 1.125 0 00-1.091-.852H4.5A2.25 2.25 0 002.25 4.5v2.25z"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="mt-3 text-sm font-medium text-gray-900">On-Call</div>
|
|
<div class="mt-1 text-xs text-gray-500">Smart alert routing</div>
|
|
</a>
|
|
|
|
<!-- Scheduled Maintenance - Teal -->
|
|
<a href="/product/scheduled-maintenance" class="blog-cta-card group flex flex-col items-center justify-center text-center rounded-2xl bg-white px-4 py-5 ring-1 ring-inset ring-gray-200 transition-all hover:ring-teal-300 hover:shadow-[0_0_0_2px_rgb(20_184_166/0.3),0_4px_12px_-4px_rgb(20_184_166/0.15)] h-full">
|
|
<div class="flex h-11 w-11 items-center justify-center rounded-xl bg-teal-50 ring-1 ring-teal-200">
|
|
<!-- Scheduled Maintenance Icon - Calendar with wrench -->
|
|
<svg class="h-5 w-5 text-teal-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 012.25-2.25h13.5A2.25 2.25 0 0121 7.5v11.25m-18 0A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75m-18 0v-7.5A2.25 2.25 0 015.25 9h13.5A2.25 2.25 0 0121 11.25v7.5m-9-6h.008v.008H12v-.008zM12 15h.008v.008H12V15zm0 2.25h.008v.008H12v-.008zM9.75 15h.008v.008H9.75V15zm0 2.25h.008v.008H9.75v-.008zM7.5 15h.008v.008H7.5V15zm0 2.25h.008v.008H7.5v-.008zm6.75-4.5h.008v.008h-.008v-.008zm0 2.25h.008v.008h-.008V15zm0 2.25h.008v.008h-.008v-.008zm2.25-4.5h.008v.008H16.5v-.008zm0 2.25h.008v.008H16.5V15z"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="mt-3 text-sm font-medium text-gray-900">Maintenance</div>
|
|
<div class="mt-1 text-xs text-gray-500">Plan & communicate downtime</div>
|
|
</a>
|
|
|
|
<!-- Logs - Amber -->
|
|
<a href="/product/logs-management" class="blog-cta-card group flex flex-col items-center justify-center text-center rounded-2xl bg-white px-4 py-5 ring-1 ring-inset ring-gray-200 transition-all hover:ring-amber-300 hover:shadow-[0_0_0_2px_rgb(245_158_11/0.3),0_4px_12px_-4px_rgb(245_158_11/0.15)] h-full">
|
|
<div class="flex h-11 w-11 items-center justify-center rounded-xl bg-amber-50 ring-1 ring-amber-200">
|
|
<!-- Logs Icon - Stacked horizontal lines -->
|
|
<svg class="h-5 w-5 text-amber-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 12h16.5m-16.5 3.75h16.5M3.75 19.5h16.5M5.625 4.5h12.75a1.875 1.875 0 010 3.75H5.625a1.875 1.875 0 010-3.75z"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="mt-3 text-sm font-medium text-gray-900">Logs</div>
|
|
<div class="mt-1 text-xs text-gray-500">Fastest log ingest and search</div>
|
|
</a>
|
|
|
|
<!-- Metrics - Purple -->
|
|
<a href="/product/metrics" class="blog-cta-card group flex flex-col items-center justify-center text-center rounded-2xl bg-white px-4 py-5 ring-1 ring-inset ring-gray-200 transition-all hover:ring-purple-300 hover:shadow-[0_0_0_2px_rgb(168_85_247/0.3),0_4px_12px_-4px_rgb(168_85_247/0.15)] h-full">
|
|
<div class="flex h-11 w-11 items-center justify-center rounded-xl bg-purple-50 ring-1 ring-purple-200">
|
|
<!-- Metrics Icon - Line chart / heartbeat -->
|
|
<svg class="h-5 w-5 text-purple-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M2 12h3l2-4 3 8 3-6 2 4h7"></path>
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M2 20h20"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="mt-3 text-sm font-medium text-gray-900">Metrics</div>
|
|
<div class="mt-1 text-xs text-gray-500">Performance insights</div>
|
|
</a>
|
|
|
|
<!-- Traces - Yellow -->
|
|
<a href="/product/traces" class="blog-cta-card group flex flex-col items-center justify-center text-center rounded-2xl bg-white px-4 py-5 ring-1 ring-inset ring-gray-200 transition-all hover:ring-yellow-300 hover:shadow-[0_0_0_2px_rgb(234_179_8/0.3),0_4px_12px_-4px_rgb(234_179_8/0.15)] h-full">
|
|
<div class="flex h-11 w-11 items-center justify-center rounded-xl bg-yellow-50 ring-1 ring-yellow-200">
|
|
<!-- Traces Icon - Waterfall / span diagram -->
|
|
<svg class="h-5 w-5 text-yellow-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<rect x="2" y="3" width="20" height="4" rx="0.5"></rect>
|
|
<rect x="2" y="10" width="10" height="4" rx="0.5"></rect>
|
|
<rect x="2" y="17" width="5" height="4" rx="0.5"></rect>
|
|
<rect x="17" y="17" width="5" height="4" rx="0.5"></rect>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="mt-3 text-sm font-medium text-gray-900">Traces</div>
|
|
<div class="mt-1 text-xs text-gray-500">End-to-end distributed tracing</div>
|
|
</a>
|
|
|
|
<!-- Exceptions - Orange -->
|
|
<a href="/product/exceptions" class="blog-cta-card group flex flex-col items-center justify-center text-center rounded-2xl bg-white px-4 py-5 ring-1 ring-inset ring-gray-200 transition-all hover:ring-orange-300 hover:shadow-[0_0_0_2px_rgb(244_63_94/0.3),0_4px_12px_-4px_rgb(244_63_94/0.15)] h-full">
|
|
<div class="flex h-11 w-11 items-center justify-center rounded-xl bg-orange-50 ring-1 ring-orange-200">
|
|
<!-- Exceptions Icon - Bug -->
|
|
<svg class="h-5 w-5 text-orange-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<ellipse cx="12" cy="14" rx="5" ry="6"></ellipse>
|
|
<path stroke-linecap="round" d="M9 8.5C9 6.5 10.5 5 12 5s3 1.5 3 3.5M4 11l3 1m10-1 3 1M4 17l3-1m10 1 3-1M12 8v12M9 14h6"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="mt-3 text-sm font-medium text-gray-900">Exceptions</div>
|
|
<div class="mt-1 text-xs text-gray-500">Catch and fix bugs early</div>
|
|
</a>
|
|
|
|
<!-- Workflows - Sky -->
|
|
<a href="/product/workflows" class="blog-cta-card group flex flex-col items-center justify-center text-center rounded-2xl bg-white px-4 py-5 ring-1 ring-inset ring-gray-200 transition-all hover:ring-sky-300 hover:shadow-[0_0_0_2px_rgb(14_165_233/0.3),0_4px_12px_-4px_rgb(14_165_233/0.15)] h-full">
|
|
<div class="flex h-11 w-11 items-center justify-center rounded-xl bg-sky-50 ring-1 ring-sky-200">
|
|
<!-- Workflows Icon - Flow diagram (rotated 180°) -->
|
|
<svg class="h-5 w-5 text-sky-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24" style="transform: rotate(180deg)">
|
|
<rect x="3" y="3" width="6" height="4" rx="1" stroke-width="1.5"></rect>
|
|
<rect x="15" y="3" width="6" height="4" rx="1" stroke-width="1.5"></rect>
|
|
<rect x="9" y="17" width="6" height="4" rx="1" stroke-width="1.5"></rect>
|
|
<path stroke-linecap="round" d="M6 7v3a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V7M12 12v5"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="mt-3 text-sm font-medium text-gray-900">Workflows</div>
|
|
<div class="mt-1 text-xs text-gray-500">Automate any process</div>
|
|
</a>
|
|
|
|
<!-- Dashboards - Indigo -->
|
|
<a href="/product/dashboards" class="blog-cta-card group flex flex-col items-center justify-center text-center rounded-2xl bg-white px-4 py-5 ring-1 ring-inset ring-gray-200 transition-all hover:ring-indigo-300 hover:shadow-[0_0_0_2px_rgb(99_102_241/0.3),0_4px_12px_-4px_rgb(99_102_241/0.15)] h-full">
|
|
<div class="flex h-11 w-11 items-center justify-center rounded-xl bg-indigo-50 ring-1 ring-indigo-200">
|
|
<!-- Dashboards Icon - Pie chart -->
|
|
<svg class="h-5 w-5 text-indigo-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M10.5 6a7.5 7.5 0 107.5 7.5h-7.5V6z"></path>
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M13.5 10.5H21A7.5 7.5 0 0013.5 3v7.5z"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="mt-3 text-sm font-medium text-gray-900">Dashboards</div>
|
|
<div class="mt-1 text-xs text-gray-500">Visualize all your data</div>
|
|
</a>
|
|
|
|
<!-- Kubernetes - Cyan -->
|
|
<a href="/product/kubernetes" class="blog-cta-card group flex flex-col items-center justify-center text-center rounded-2xl bg-white px-4 py-5 ring-1 ring-inset ring-gray-200 transition-all hover:ring-cyan-300 hover:shadow-[0_0_0_2px_rgb(6_182_212/0.3),0_4px_12px_-4px_rgb(6_182_212/0.15)] h-full">
|
|
<div class="flex h-11 w-11 items-center justify-center rounded-xl bg-cyan-50 ring-1 ring-cyan-200">
|
|
<!-- Kubernetes Icon - Helm wheel -->
|
|
<svg class="h-5 w-5 text-cyan-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<polygon stroke-linecap="round" stroke-linejoin="round" points="12,2.5 19.43,6.08 21.26,14.11 15.95,20.64 8.05,20.56 2.74,14.27 4.57,6.22"></polygon>
|
|
<circle cx="12" cy="12" r="2.2" stroke-linecap="round" stroke-linejoin="round"></circle>
|
|
<line x1="12" y1="9.8" x2="12" y2="4" stroke-linecap="round"></line>
|
|
<line x1="14.12" y1="10.24" x2="17.54" y2="6.64" stroke-linecap="round"></line>
|
|
<line x1="14.14" y1="12.49" x2="19.31" y2="13.67" stroke-linecap="round"></line>
|
|
<line x1="13.12" y1="14.0" x2="15.12" y2="18.82" stroke-linecap="round"></line>
|
|
<line x1="10.88" y1="14.0" x2="8.88" y2="18.76" stroke-linecap="round"></line>
|
|
<line x1="9.86" y1="12.49" x2="4.69" y2="13.79" stroke-linecap="round"></line>
|
|
<line x1="9.88" y1="10.24" x2="6.46" y2="6.53" stroke-linecap="round"></line>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="mt-3 text-sm font-medium text-gray-900">Kubernetes</div>
|
|
<div class="mt-1 text-xs text-gray-500">Monitor K8s clusters</div>
|
|
</a>
|
|
|
|
<!-- Profiles - Rose -->
|
|
<a href="/product/profiles" class="blog-cta-card group flex flex-col items-center justify-center text-center rounded-2xl bg-white px-4 py-5 ring-1 ring-inset ring-gray-200 transition-all hover:ring-rose-300 hover:shadow-[0_0_0_2px_rgb(244_63_94/0.3),0_4px_12px_-4px_rgb(244_63_94/0.15)] h-full">
|
|
<div class="flex h-11 w-11 items-center justify-center rounded-xl bg-rose-50 ring-1 ring-rose-200">
|
|
<!-- Profiles Icon - Flame/fire for flamegraph -->
|
|
<svg class="h-5 w-5 text-rose-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0112 21 8.25 8.25 0 016.038 7.048 8.287 8.287 0 009 9.6a8.983 8.983 0 013.361-6.867 8.21 8.21 0 003 2.48z"></path>
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 00.495-7.467 5.99 5.99 0 00-1.925 3.546 5.974 5.974 0 01-2.133-1.001A3.75 3.75 0 0012 18z"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="mt-3 text-sm font-medium text-gray-900">Profiles</div>
|
|
<div class="mt-1 text-xs text-gray-500">CPU & memory profiling</div>
|
|
</a>
|
|
</div>
|
|
|
|
<!-- AI Agent - Full width featured card -->
|
|
<div class="mt-5">
|
|
<a href="/product/ai-agent" class="blog-cta-card group flex items-center gap-5 rounded-2xl bg-white px-6 py-5 ring-1 ring-inset ring-gray-200 transition-all hover:ring-violet-300 hover:shadow-[0_0_0_2px_rgb(139_92_246/0.3),0_4px_12px_-4px_rgb(139_92_246/0.15)]">
|
|
<div class="flex h-11 w-11 shrink-0 items-center justify-center rounded-xl bg-violet-50 ring-1 ring-violet-200">
|
|
<!-- AI Agent Icon - Sparkles -->
|
|
<svg class="h-5 w-5 text-violet-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M9.813 15.904 9 18.75l-.813-2.846a4.5 4.5 0 0 0-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 0 0 3.09-3.09L9 5.25l.813 2.846a4.5 4.5 0 0 0 3.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 0 0-3.09 3.09ZM18.259 8.715 18 9.75l-.259-1.035a3.375 3.375 0 0 0-2.455-2.456L14.25 6l1.036-.259a3.375 3.375 0 0 0 2.455-2.456L18 2.25l.259 1.035a3.375 3.375 0 0 0 2.456 2.456L21.75 6l-1.035.259a3.375 3.375 0 0 0-2.456 2.456ZM16.894 20.567 16.5 21.75l-.394-1.183a2.25 2.25 0 0 0-1.423-1.423L13.5 18.75l1.183-.394a2.25 2.25 0 0 0 1.423-1.423l.394-1.183.394 1.183a2.25 2.25 0 0 0 1.423 1.423l1.183.394-1.183.394a2.25 2.25 0 0 0-1.423 1.423Z"></path>
|
|
</svg>
|
|
|
|
</div>
|
|
<div class="flex-1 text-left">
|
|
<div class="flex items-center gap-2">
|
|
<span class="text-sm font-medium text-gray-900">AI</span>
|
|
</div>
|
|
<div class="mt-1 text-xs text-gray-500">Detect, diagnose, and resolve incidents with AI-powered root cause analysis and code fixes.</div>
|
|
</div>
|
|
<svg class="h-4 w-4 text-gray-400 transition-transform group-hover:translate-x-0.5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M8.25 4.5l7.5 7.5-7.5 7.5"></path></svg>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="cookie" class="pointer-events-none fixed inset-x-0 bottom-0 px-6 pb-6 cookie-banner" style="display:none;">
|
|
<div class="pointer-events-auto ml-auto max-w-xl rounded-xl bg-white p-6 shadow-lg ring-1 ring-gray-900/10">
|
|
<p class="text-sm leading-6 text-gray-900 my-3">We use cookies to enhance your browsing experience and provide
|
|
personalized content. By clicking "Accept," you consent to the use of cookies.</p>
|
|
|
|
<p class="text-sm leading-6 text-gray-900 my-3">Our product uses both first-party and third-party cookies for session storage and for various other purposes.</p>
|
|
|
|
<p class="text-sm leading-6 text-gray-900 my-3">Please note that disabling certain cookies may affect the functionality and performance of our product.</p>
|
|
|
|
<p class="text-sm leading-6 text-gray-900 my-3">For more information about how we handle your data and cookies, please read our Privacy Policy.</p>
|
|
|
|
<p class="text-sm leading-6 text-gray-900 my-3">By continuing to use our site without changing your cookie settings, you agree to our use of cookies as
|
|
described above. See our <a href="/legal/terms" class="font-semibold text-gray-600">terms</a> and our <a
|
|
href="/legal/privacy" class="font-semibold text-gray-600">privacy policy</a> </p>
|
|
<div class="mt-4 flex items-center gap-x-5">
|
|
<button onclick="acceptCookies()" type="button"
|
|
class="rounded-md bg-gray-900 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-gray-700 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-900">Accept
|
|
all</button>
|
|
<button onclick="rejectCookies()" type="button" class="text-sm font-semibold leading-6 text-gray-900">Reject all</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!--
|
|
The buttons here are the only thing that moves the consent state.
|
|
|
|
They used to write `cookiesAccepted` to localStorage and hide the banner,
|
|
and nothing anywhere read the value: Google Tag Manager, PostHog and the
|
|
attribution capture all ran identically whether the visitor pressed Accept,
|
|
pressed Reject, or never saw the banner. "Reject all" rejected nothing.
|
|
|
|
Both buttons go through window.oneUptimeConsent (defined in
|
|
Common/Server/Views/Partials/AnalyticsConsent.ejs, before the tags load),
|
|
which records the answer under 'cookiesAccepted'.
|
|
|
|
RECORDS IT, AND NOTHING MORE. Measurement is no longer gated on the answer:
|
|
Consent Mode defaults to granted and is not updated on either button,
|
|
attribution is stored on sight, and PostHog loads regardless. So these
|
|
buttons currently change nothing except which of them the banner remembers
|
|
you pressed. That is a deliberate decision documented at the top of
|
|
AnalyticsConsent.ejs and in Docs/analytics/enterprise-conversion-tracking.md
|
|
— but a banner offering a choice it does not honour is the thing to fix
|
|
next, either by re-gating or by removing the buttons.
|
|
|
|
That partial is shared with /accounts and /dashboard, so the answer given
|
|
here is the answer those origins honour too — they are the same origin and
|
|
read the same key.
|
|
-->
|
|
<script>
|
|
function setCookieConsent(granted) {
|
|
/*
|
|
* The AnalyticsConsent partial is included by every page that includes
|
|
* this banner, so the helper is always there. Falling back to the raw
|
|
* write keeps a page that somehow omits it from silently losing the
|
|
* visitor's answer.
|
|
*/
|
|
if (window.oneUptimeConsent) {
|
|
if (granted) {
|
|
window.oneUptimeConsent.grant();
|
|
} else {
|
|
window.oneUptimeConsent.deny();
|
|
}
|
|
} else {
|
|
try {
|
|
localStorage.setItem('cookiesAccepted', granted ? 'true' : 'false');
|
|
} catch (e) {
|
|
// Storage unavailable; the banner still closes for this page.
|
|
}
|
|
}
|
|
|
|
hideBanner();
|
|
}
|
|
|
|
// Function to accept cookies
|
|
function acceptCookies() {
|
|
setCookieConsent(true);
|
|
}
|
|
|
|
// Function to reject cookies
|
|
function rejectCookies() {
|
|
setCookieConsent(false);
|
|
}
|
|
|
|
// Function to hide the banner
|
|
function hideBanner() {
|
|
document.getElementById('cookie').style.display = 'none';
|
|
}
|
|
|
|
// Function to show the banner
|
|
function showBanner() {
|
|
document.getElementById('cookie').style.display = 'block';
|
|
}
|
|
|
|
/*
|
|
* Withdrawing consent has to be as easy as giving it, and the Cookie
|
|
* Policy has always promised a settings link in the footer. Until this
|
|
* existed there was no way to reopen the banner at all: answer it once and
|
|
* the decision was final.
|
|
*/
|
|
window.oneUptimeShowCookieSettings = function () {
|
|
showBanner();
|
|
return false;
|
|
};
|
|
|
|
function checkCookies () {
|
|
/*
|
|
* Shown only while the visitor has not answered. `granted` and
|
|
* `denied` are both answers — re-asking someone who declined is how a
|
|
* consent banner turns into a dark pattern.
|
|
*/
|
|
var state = window.oneUptimeConsent ? window.oneUptimeConsent.state() : 'unset';
|
|
|
|
if (state === 'unset') {
|
|
showBanner();
|
|
} else {
|
|
hideBanner();
|
|
}
|
|
};
|
|
|
|
// Check the user's choice on page load
|
|
window.onload = checkCookies;
|
|
|
|
|
|
</script> <footer class="bg-gradient-to-b from-gray-50 to-white border-t border-gray-200/60" aria-labelledby="footer-heading">
|
|
<h2 id="footer-heading" class="sr-only">Footer</h2>
|
|
|
|
<!-- CTA Section -->
|
|
<div class="border-b border-gray-200/60 bg-gradient-to-r from-gray-50 via-gray-100/30 to-gray-50">
|
|
<div class="mx-auto max-w-7xl px-6 py-14 lg:px-8">
|
|
<div class="flex flex-col lg:flex-row lg:items-center lg:justify-between gap-10">
|
|
<div class="max-w-2xl">
|
|
<div class="flex items-center gap-3 mb-3">
|
|
<div class="flex h-10 w-10 items-center justify-center rounded-xl bg-gray-900 shadow-sm">
|
|
<svg class="h-5 w-5 text-white" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M6.429 9.75L2.25 12l4.179 2.25m0-4.5l5.571 3 5.571-3m-11.142 0L2.25 7.5 12 2.25l9.75 5.25-4.179 2.25m0 0L21.75 12l-4.179 2.25m0 0l4.179 2.25L12 21.75 2.25 16.5l4.179-2.25m11.142 0l-5.571 3-5.571-3" />
|
|
</svg>
|
|
</div>
|
|
<span class="text-sm font-medium text-gray-900">Open Source Observability</span>
|
|
</div>
|
|
<h3 class="text-2xl font-semibold text-gray-900 tracking-tight">Build reliable systems with confidence</h3>
|
|
<p class="mt-3 text-base text-gray-600">Join thousands of developers using OneUptime to monitor, debug, and optimize their infrastructure, stack, and apps.</p>
|
|
</div>
|
|
<div class="flex flex-col sm:flex-row gap-4 sm:items-center">
|
|
<a href="/blog" class="inline-flex items-center justify-center gap-2 rounded-full bg-white px-6 py-3 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-gray-200 hover:bg-gray-50 hover:ring-gray-300 transition-all duration-200">
|
|
<svg class="h-4 w-4 text-gray-500" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6.042A8.967 8.967 0 006 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 016 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 016-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0018 18a8.967 8.967 0 00-6 2.292m0-14.25v14.25" />
|
|
</svg>
|
|
Read Blog
|
|
</a>
|
|
<a href="https://github.com/oneuptime/oneuptime" target="_blank" class="inline-flex items-center justify-center gap-2 rounded-full bg-gray-900 px-6 py-3 text-sm font-semibold text-white shadow-sm hover:bg-gray-900 transition-all duration-200 hover:shadow-md">
|
|
<svg class="h-4 w-4" fill="currentColor" viewBox="0 0 24 24">
|
|
<path fill-rule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" clip-rule="evenodd" />
|
|
</svg>
|
|
Star on GitHub
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Main Footer Content -->
|
|
<div class="mx-auto max-w-7xl px-6 py-16 lg:px-8">
|
|
<div class="xl:grid xl:grid-cols-3 xl:gap-12">
|
|
|
|
<!-- Brand Section -->
|
|
<div class="space-y-6">
|
|
<a href="/" class="inline-block">
|
|
<img class="h-8 w-auto" src="/img/4-gray.svg" alt="OneUptime" width="140" height="32" loading="lazy">
|
|
</a>
|
|
<p class="text-sm text-gray-600 leading-relaxed max-w-xs">
|
|
The complete open-source observability platform. Monitor, debug, and improve your entire stack in one place.
|
|
</p>
|
|
|
|
<!-- Social Links -->
|
|
<div class="flex items-center gap-4">
|
|
<a href="https://github.com/oneuptime/oneuptime" target="_blank"
|
|
class="group flex items-center justify-center w-10 h-10 rounded-full bg-gray-100 text-gray-600 hover:bg-gray-900 hover:text-white transition-all duration-200 hover:scale-105">
|
|
<span class="sr-only">GitHub</span>
|
|
<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
|
<path fill-rule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" clip-rule="evenodd" />
|
|
</svg>
|
|
</a>
|
|
<a href="https://x.com/oneuptimehq" target="_blank"
|
|
class="group flex items-center justify-center w-10 h-10 rounded-full bg-gray-100 text-gray-600 hover:bg-gray-900 hover:text-white transition-all duration-200 hover:scale-105">
|
|
<span class="sr-only">X</span>
|
|
<svg class="h-4 w-4" fill="currentColor" viewBox="0 0 220 200" aria-hidden="true">
|
|
<path d="M173.263 0H206.998L133.297 84.718L220 200H152.112L98.9403 130.082L38.0995 200H4.34432L83.1743 109.385L0 0H69.6111L117.674 63.9077L173.263 0ZM161.423 179.692H180.116L59.4539 19.241H39.3946L161.423 179.692Z"/>
|
|
</svg>
|
|
</a>
|
|
<a href="https://njump.me/npub1kggtaw83q0mctlwvh854xdu3wjmen8tmq9cx9l030x2ylay6wk8qy2f2e6" target="_blank"
|
|
class="group flex items-center justify-center w-10 h-10 rounded-full bg-gray-100 text-gray-600 hover:bg-purple-600 hover:text-white transition-all duration-200 hover:scale-105">
|
|
<span class="sr-only">Nostr</span>
|
|
<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 256 256" aria-hidden="true">
|
|
<path d="M210.8 199.4c0 3.1-2.5 5.7-5.7 5.7h-68c-3.1 0-5.7-2.5-5.7-5.7v-15.5c.3-19 2.3-37.2 6.5-45.5 2.5-5 6.7-7.7 11.5-9.1 9.1-2.7 24.9-.9 31.7-1.2 0 0 20.4.8 20.4-10.7s-9.1-8.6-9.1-8.6c-10 .3-17.7-.4-22.6-2.4-8.3-3.3-8.6-9.2-8.6-11.2-.4-23.1-34.5-25.9-64.5-20.1-32.8 6.2.4 53.3.4 116.1v8.4c0 3.1-2.6 5.6-5.7 5.6H57.7c-3.1 0-5.7-2.5-5.7-5.7v-144c0-3.1 2.5-5.7 5.7-5.7h31.7c3.1 0 5.7 2.5 5.7 5.7 0 4.7 5.2 7.2 9 4.5 11.4-8.2 26-12.5 42.4-12.5 36.6 0 64.4 21.4 64.4 68.7v83.2ZM150 99.3c0-6.7-5.4-12.1-12.1-12.1s-12.1 5.4-12.1 12.1 5.4 12.1 12.1 12.1S150 106 150 99.3Z" />
|
|
</svg>
|
|
</a>
|
|
<a href="https://www.youtube.com/@OneUptimeHQ" target="_blank"
|
|
class="group flex items-center justify-center w-10 h-10 rounded-full bg-gray-100 text-gray-600 hover:bg-red-600 hover:text-white transition-all duration-200 hover:scale-105">
|
|
<span class="sr-only">YouTube</span>
|
|
<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
|
<path fill-rule="evenodd" d="M19.812 5.418c.861.23 1.538.907 1.768 1.768C21.998 8.746 22 12 22 12s0 3.255-.418 4.814a2.504 2.504 0 0 1-1.768 1.768c-1.56.419-7.814.419-7.814.419s-6.255 0-7.814-.419a2.505 2.505 0 0 1-1.768-1.768C2 15.255 2 12 2 12s0-3.255.417-4.814a2.507 2.507 0 0 1 1.768-1.768C5.744 5 11.998 5 11.998 5s6.255 0 7.814.418ZM15.194 12 10 15V9l5.194 3Z" clip-rule="evenodd" />
|
|
</svg>
|
|
</a>
|
|
<a href="https://www.reddit.com/r/oneuptimehq/" target="_blank"
|
|
class="group flex items-center justify-center w-10 h-10 rounded-full bg-gray-100 text-gray-600 hover:bg-orange-600 hover:text-white transition-all duration-200 hover:scale-105">
|
|
<span class="sr-only">Reddit</span>
|
|
<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
|
<path d="M14.238 15.348c.085.084.085.221 0 .306-.465.462-1.194.687-2.231.687l-.008-.002-.008.002c-1.036 0-1.766-.225-2.231-.688-.085-.084-.085-.221 0-.305.084-.084.222-.084.307 0 .379.377 1.008.561 1.924.561l.008.002.008-.002c.915 0 1.544-.184 1.924-.561.085-.084.223-.084.307 0zm-3.44-2.418c0-.507-.414-.919-.922-.919-.509 0-.923.412-.923.919 0 .506.414.918.923.918.508.001.922-.411.922-.918zm13.202-.93c0 6.627-5.373 12-12 12s-12-5.373-12-12 5.373-12 12-12 12 5.373 12 12zm-5-.129c0-.851-.695-1.543-1.55-1.543-.417 0-.795.167-1.074.435-1.056-.695-2.485-1.137-4.066-1.194l.865-2.724 2.343.549-.003.034c0 .696.569 1.262 1.268 1.262.699 0 1.267-.566 1.267-1.262s-.568-1.262-1.267-1.262c-.537 0-.994.335-1.179.804l-2.525-.592c-.11-.027-.223.037-.257.145l-.965 3.038c-1.656.02-3.155.466-4.258 1.181-.277-.255-.644-.415-1.05-.415-.854.001-1.549.693-1.549 1.544 0 .566.311 1.056.768 1.325-.03.164-.05.331-.05.5 0 2.281 2.805 4.137 6.253 4.137s6.253-1.856 6.253-4.137c0-.16-.017-.317-.044-.472.486-.261.82-.766.82-1.353zm-4.872.141c-.509 0-.922.412-.922.919 0 .506.414.918.922.918s.922-.412.922-.918c0-.507-.413-.919-.922-.919z"/>
|
|
</svg>
|
|
</a>
|
|
<a href="https://www.linkedin.com/company/oneuptime" target="_blank"
|
|
class="group flex items-center justify-center w-10 h-10 rounded-full bg-gray-100 text-gray-600 hover:bg-blue-700 hover:text-white transition-all duration-200 hover:scale-105">
|
|
<span class="sr-only">LinkedIn</span>
|
|
<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
|
<path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/>
|
|
</svg>
|
|
</a>
|
|
</div>
|
|
|
|
<!-- Trust Statement -->
|
|
<p class="text-sm text-gray-500 leading-relaxed pt-2">
|
|
Trusted by thousands of teams worldwide - from Fortune 500 enterprises to fast-growing startups.
|
|
</p>
|
|
</div>
|
|
|
|
<!-- Links Grid -->
|
|
<div class="mt-16 grid grid-cols-2 gap-8 xl:col-span-2 xl:mt-0">
|
|
<div class="md:grid md:grid-cols-2 md:gap-8">
|
|
|
|
<!-- Products Column -->
|
|
<div>
|
|
<h3 class="text-sm font-semibold text-gray-900">Products</h3>
|
|
<ul role="list" class="mt-4 space-y-3">
|
|
<li><a href="/product/status-page" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Status Page</a></li>
|
|
<li><a href="/product/incident-management" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Incidents</a></li>
|
|
<li><a href="/product/monitoring" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Monitoring</a></li>
|
|
<li><a href="/product/on-call" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">On-Call</a></li>
|
|
<li><a href="/product/observability" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Observability</a></li>
|
|
<li><a href="/product/topology" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Topology</a></li>
|
|
<li><a href="/product/security-events" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Security Events</a></li>
|
|
<li><a href="/product/logs-management" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Logs</a></li>
|
|
<li><a href="/product/metrics" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Metrics</a></li>
|
|
<li><a href="/product/traces" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Traces</a></li>
|
|
<li><a href="/product/exceptions" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Exceptions</a></li>
|
|
<li><a href="/product/profiles" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Profiles</a></li>
|
|
<li><a href="/product/rum" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Real User Monitoring</a></li>
|
|
<li><a href="/product/kubernetes" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Kubernetes</a></li>
|
|
<li><a href="/product/docker" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Docker</a></li>
|
|
<li><a href="/product/podman" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Podman</a></li>
|
|
<li><a href="/product/host" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Hosts</a></li>
|
|
<li><a href="/product/proxmox" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Proxmox</a></li>
|
|
<li><a href="/product/vmware" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">VMware</a></li>
|
|
<li><a href="/product/ai-observability" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">AI / LLM Observability</a></li>
|
|
<li><a href="/product/ceph" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Ceph</a></li>
|
|
<li><a href="/product/docker-swarm" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Docker Swarm</a></li>
|
|
<li><a href="/product/iot" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">IoT Devices</a></li>
|
|
<li><a href="/product/network-monitoring" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Network Devices</a></li>
|
|
<li><a href="/product/serverless" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Serverless</a></li>
|
|
<li><a href="/product/cloud" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Cloud</a></li>
|
|
<li><a href="/product/workflows" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Workflows</a></li>
|
|
<li><a href="/product/dashboards" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Dashboards</a></li>
|
|
<li><a href="/product/ai-agent" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">AI</a></li>
|
|
</ul>
|
|
</div>
|
|
|
|
<!-- Solutions Column -->
|
|
<div class="mt-10 md:mt-0">
|
|
<h3 class="text-sm font-semibold text-gray-900">Solutions</h3>
|
|
<ul role="list" class="mt-4 space-y-3">
|
|
<li><a href="/enterprise/overview" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Enterprise</a></li>
|
|
<li><a href="/enterprise/self-hosted" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Self-Hosted</a></li>
|
|
<li><a href="/enterprise/demo" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Request Demo</a></li>
|
|
<li><a href="/pricing" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Pricing</a></li>
|
|
<li><a href="/trust" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Trust Center</a></li>
|
|
<li><a href="/legal/data-residency" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Data Residency</a></li>
|
|
</ul>
|
|
|
|
<h3 class="text-sm font-semibold text-gray-900 mt-8">Teams</h3>
|
|
<ul role="list" class="mt-4 space-y-3">
|
|
<li><a href="/solutions/devops" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">DevOps</a></li>
|
|
<li><a href="/solutions/sre" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">SRE</a></li>
|
|
<li><a href="/solutions/platform" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Platform</a></li>
|
|
<li><a href="/solutions/developers" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Developers</a></li>
|
|
</ul>
|
|
|
|
<h3 class="text-sm font-semibold text-gray-900 mt-8">Tools</h3>
|
|
<ul role="list" class="mt-4 space-y-3">
|
|
<li><a href="/tool/mcp-server" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">MCP Server</a></li>
|
|
<li><a href="/tool/cli" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">CLI</a></li>
|
|
</ul>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="md:grid md:grid-cols-2 md:gap-8">
|
|
|
|
<!-- Resources Column -->
|
|
<div>
|
|
<h3 class="text-sm font-semibold text-gray-900">Resources</h3>
|
|
<ul role="list" class="mt-4 space-y-3">
|
|
<li><a href="/docs" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Documentation</a></li>
|
|
<li><a href="/reference" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">API Reference</a></li>
|
|
<li><a href="/blog" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Blog</a></li>
|
|
<li><a href="/books" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Books</a></li>
|
|
<li><a href="/support" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Help & Support</a></li>
|
|
<li><a href="https://github.com/oneuptime/oneuptime" target="_blank" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">GitHub</a></li>
|
|
<li><a href="https://github.com/oneuptime/oneuptime/releases" target="_blank" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Changelog</a></li>
|
|
<li><a href="/oss-friends" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Open Source Friends</a></li>
|
|
</ul>
|
|
|
|
<h3 class="text-sm font-semibold text-gray-900 mt-8">Industries</h3>
|
|
<ul role="list" class="mt-4 space-y-3">
|
|
<li><a href="/industries/fintech" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">FinTech</a></li>
|
|
<li><a href="/industries/saas" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">SaaS</a></li>
|
|
<li><a href="/industries/healthcare" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Healthcare</a></li>
|
|
<li><a href="/industries/ecommerce" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">E-Commerce</a></li>
|
|
<li><a href="/industries/media" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Media</a></li>
|
|
<li><a href="/industries/government" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Government</a></li>
|
|
</ul>
|
|
</div>
|
|
|
|
<!-- Company Column -->
|
|
<div class="mt-10 md:mt-0">
|
|
<h3 class="text-sm font-semibold text-gray-900">Company</h3>
|
|
<ul role="list" class="mt-4 space-y-3">
|
|
<li><a href="/about" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">About Us</a></li>
|
|
<li><a href="https://github.com/OneUptime/interview" target="_blank" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Careers</a></li>
|
|
<li><a href="https://shop.oneuptime.com" target="_blank" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Merch Store</a></li>
|
|
<li><a href="/legal/contact" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Contact</a></li>
|
|
</ul>
|
|
|
|
<h3 class="text-sm font-semibold text-gray-900 mt-8">Legal</h3>
|
|
<ul role="list" class="mt-4 space-y-3">
|
|
<li><a href="/trust" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Trust Center</a></li>
|
|
<li><a href="/legal/terms" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Terms of Service</a></li>
|
|
<li><a href="/legal/privacy" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Privacy Policy</a></li>
|
|
<li><a href="/legal/sla" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">SLA</a></li>
|
|
<li><a href="/legal" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Legal Center</a></li>
|
|
<li><a href="/legal/cookies" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Cookie Policy</a></li>
|
|
<li><a href="#" onclick="return window.oneUptimeShowCookieSettings ? window.oneUptimeShowCookieSettings() : true;" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">Cookie settings</a></li>
|
|
</ul>
|
|
|
|
<h3 class="text-sm font-semibold text-gray-900 mt-8">Compare</h3>
|
|
<ul role="list" class="mt-4 space-y-3">
|
|
<li><a href="/compare/pagerduty" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">vs PagerDuty</a></li>
|
|
<li><a href="/compare/datadog" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">vs Datadog</a></li>
|
|
<li><a href="/compare/grafana" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">vs Grafana</a></li>
|
|
<li><a href="/compare/opsgenie" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">vs Opsgenie</a></li>
|
|
<li><a href="/compare/statuspage.io" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">vs Statuspage</a></li>
|
|
<li><a href="/compare/incident.io" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">vs Incident.io</a></li>
|
|
<li><a href="/compare/newrelic" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">vs New Relic</a></li>
|
|
<li><a href="/compare/better-uptime" class="text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200">vs Better Stack</a></li>
|
|
<li><a href="/compare" class="text-sm font-medium text-gray-900 hover:text-gray-700 transition-colors duration-200">View all comparisons →</a></li>
|
|
</ul>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Bottom Bar -->
|
|
<div class="border-t border-gray-200/60 bg-gray-50/50">
|
|
<div class="mx-auto max-w-7xl px-6 py-6 lg:px-8">
|
|
<div class="flex flex-col md:flex-row md:items-center md:justify-between gap-4">
|
|
<div class="flex flex-col sm:flex-row sm:items-center gap-4 sm:gap-6">
|
|
<p class="text-sm text-gray-500">© 2026 HackerBay, Inc. All rights reserved.</p>
|
|
<div class="flex items-center gap-4">
|
|
<a href="https://github.com/oneuptime/oneuptime" target="_blank" class="inline-flex items-center gap-2 text-sm text-gray-600 hover:text-gray-900 transition-colors duration-200 group">
|
|
<span class="flex items-center justify-center w-6 h-6 rounded-full bg-gray-200 group-hover:bg-gray-900 transition-colors duration-200">
|
|
<svg class="h-3.5 w-3.5 text-gray-600 group-hover:text-white transition-colors duration-200" fill="currentColor" viewBox="0 0 24 24">
|
|
<path fill-rule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" clip-rule="evenodd" />
|
|
</svg>
|
|
</span>
|
|
<span class="font-medium">Open Source</span>
|
|
</a>
|
|
<span class="text-gray-300">|</span>
|
|
<span class="text-sm text-gray-500">Made with care for developers worldwide</span>
|
|
</div>
|
|
</div>
|
|
<div class="flex items-center gap-4">
|
|
<a href="/legal/soc-2" class="text-xs text-gray-400 hover:text-gray-600 transition-colors duration-200">SOC 2</a>
|
|
<a href="/legal/hipaa" class="text-xs text-gray-400 hover:text-gray-600 transition-colors duration-200">HIPAA</a>
|
|
<a href="/legal/gdpr" class="text-xs text-gray-400 hover:text-gray-600 transition-colors duration-200">GDPR</a>
|
|
<a href="/legal/iso-27001" class="text-xs text-gray-400 hover:text-gray-600 transition-colors duration-200">ISO 27001</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</footer>
|
|
|
|
<!-- Validation report modal -->
|
|
|
|
<style>
|
|
.validation-scroll { scrollbar-width: thin; scrollbar-color: #cbd5e1 transparent; scrollbar-gutter: stable; }
|
|
.validation-scroll::-webkit-scrollbar { width: 10px; }
|
|
.validation-scroll::-webkit-scrollbar-track { background: transparent; }
|
|
.validation-scroll::-webkit-scrollbar-thumb { background-color: #cbd5e1; border-radius: 9999px; border: 3px solid #fff; background-clip: content-box; min-height: 40px; }
|
|
.validation-scroll::-webkit-scrollbar-thumb:hover { background-color: #94a3b8; }
|
|
</style>
|
|
<div id="validation-modal" class="fixed inset-0 z-[100] hidden" role="dialog" aria-modal="true" aria-labelledby="validation-modal-title" data-file="2025-09-03-what-are-error-budgets">
|
|
<div id="validation-modal-backdrop" class="absolute inset-0 bg-gray-900/60 backdrop-blur-sm opacity-0 transition-opacity duration-200 ease-out"></div>
|
|
<div class="absolute inset-0 flex items-end sm:items-center justify-center p-0 sm:p-6">
|
|
<div id="validation-modal-panel" class="relative w-full sm:max-w-2xl max-h-[92vh] sm:max-h-[85vh] flex flex-col bg-white rounded-t-2xl sm:rounded-2xl shadow-2xl ring-1 ring-gray-900/5 overflow-hidden translate-y-4 opacity-0 transition-all duration-200 ease-out">
|
|
<!-- Header -->
|
|
<div class="flex items-start gap-4 px-6 py-5 border-b border-gray-100 bg-gradient-to-b from-emerald-50/60 to-white">
|
|
<div class="shrink-0 h-10 w-10 rounded-full bg-emerald-500 flex items-center justify-center ring-4 ring-white shadow-sm">
|
|
<svg class="w-5 h-5 text-white" fill="currentColor" viewBox="0 0 20 20" aria-hidden="true"><path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/></svg>
|
|
</div>
|
|
<div class="flex-1 min-w-0">
|
|
<h2 id="validation-modal-title" class="text-lg font-semibold text-gray-900">Validation report</h2>
|
|
<p class="text-sm text-gray-500">Technically reviewed for accuracy <span class="select-none text-gray-300">•</span> <span class="font-medium text-gray-600">Jun 23, 2026</span></p>
|
|
</div>
|
|
<button type="button" class="validation-close shrink-0 -mr-1 -mt-1 h-9 w-9 inline-flex items-center justify-center rounded-full text-gray-400 hover:text-gray-700 hover:bg-gray-100 transition" aria-label="Close validation report">
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/></svg>
|
|
</button>
|
|
</div>
|
|
<!-- Body -->
|
|
<div class="relative flex-1 min-h-0 flex flex-col">
|
|
<div class="validation-scroll flex-1 min-h-0 overflow-y-auto overscroll-contain px-6 py-6 sm:px-7 sm:py-7">
|
|
<div id="validation-modal-content" class="text-gray-600">
|
|
<div id="validation-modal-loading" class="flex items-center gap-3 text-sm text-gray-500 py-8 justify-center">
|
|
<svg class="w-5 h-5 animate-spin text-emerald-500" fill="none" viewBox="0 0 24 24" aria-hidden="true"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"></path></svg>
|
|
Loading validation report…
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="pointer-events-none absolute inset-x-0 top-0 h-5 bg-gradient-to-b from-white to-transparent" aria-hidden="true"></div>
|
|
<div class="pointer-events-none absolute inset-x-0 bottom-0 h-6 bg-gradient-to-t from-white to-transparent" aria-hidden="true"></div>
|
|
</div>
|
|
<!-- Footer -->
|
|
<div class="relative z-10 px-6 py-4 border-t border-gray-100 bg-white flex items-center justify-between gap-3">
|
|
<span class="inline-flex items-center gap-1.5 text-xs text-gray-400">
|
|
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z"/></svg>
|
|
Automated technical review
|
|
</span>
|
|
<button type="button" class="validation-close px-4 py-2 rounded-full bg-gray-900 text-white text-sm font-medium hover:bg-gray-800 transition">Close</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
(function(){
|
|
// Language name mapping for display
|
|
var langNames = {
|
|
'js': 'JavaScript', 'javascript': 'JavaScript', 'ts': 'TypeScript', 'typescript': 'TypeScript',
|
|
'py': 'Python', 'python': 'Python', 'rb': 'Ruby', 'ruby': 'Ruby',
|
|
'go': 'Go', 'java': 'Java', 'css': 'CSS', 'html': 'HTML', 'xml': 'XML',
|
|
'json': 'JSON', 'yaml': 'YAML', 'yml': 'YAML', 'sql': 'SQL',
|
|
'bash': 'Bash', 'shell': 'Shell', 'sh': 'Shell', 'zsh': 'Shell',
|
|
'dockerfile': 'Dockerfile', 'docker': 'Dockerfile',
|
|
'rust': 'Rust', 'cpp': 'C++', 'c': 'C', 'csharp': 'C#',
|
|
'php': 'PHP', 'graphql': 'GraphQL', 'http': 'HTTP',
|
|
'markdown': 'Markdown', 'md': 'Markdown', 'plaintext': 'Text'
|
|
};
|
|
|
|
// Add copy button and language label to code blocks
|
|
try {
|
|
var codeBlocks = document.querySelectorAll('.blog-body pre');
|
|
codeBlocks.forEach(function(pre) {
|
|
var codeEl = pre.querySelector('code');
|
|
if(!codeEl) return;
|
|
|
|
// Detect language from class
|
|
var lang = '';
|
|
var classes = (codeEl.className || '').split(/\s+/);
|
|
for(var i = 0; i < classes.length; i++){
|
|
var m = classes[i].match(/^(?:language-|hljs-)(.+)$/);
|
|
if(m && m[1] !== 'hljs'){ lang = m[1]; break; }
|
|
}
|
|
if(!lang && codeEl.dataset && codeEl.dataset.highlightedLanguage){
|
|
lang = codeEl.dataset.highlightedLanguage;
|
|
}
|
|
|
|
var displayLang = langNames[lang] || (lang ? lang.charAt(0).toUpperCase() + lang.slice(1) : '');
|
|
|
|
// Create header bar
|
|
var header = document.createElement('div');
|
|
header.className = 'code-block-header';
|
|
|
|
// Language label
|
|
var labelEl = document.createElement('span');
|
|
labelEl.className = 'code-lang-label';
|
|
labelEl.textContent = displayLang;
|
|
header.appendChild(labelEl);
|
|
|
|
// Copy button
|
|
var copyBtn = document.createElement('button');
|
|
copyBtn.className = 'code-copy-btn';
|
|
copyBtn.setAttribute('aria-label', 'Copy code');
|
|
var copyIcon = '<svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg>';
|
|
var checkIcon = '<svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7"/></svg>';
|
|
copyBtn.innerHTML = copyIcon + '<span>Copy</span>';
|
|
copyBtn.addEventListener('click', function(){
|
|
var text = codeEl.textContent || '';
|
|
navigator.clipboard.writeText(text).then(function(){
|
|
copyBtn.classList.add('copied');
|
|
copyBtn.innerHTML = checkIcon + '<span>Copied!</span>';
|
|
setTimeout(function(){
|
|
copyBtn.classList.remove('copied');
|
|
copyBtn.innerHTML = copyIcon + '<span>Copy</span>';
|
|
}, 2000);
|
|
});
|
|
});
|
|
header.appendChild(copyBtn);
|
|
|
|
pre.style.position = 'relative';
|
|
pre.insertBefore(header, pre.firstChild);
|
|
});
|
|
} catch(e) {}
|
|
|
|
// Reading time
|
|
try {
|
|
const container = document.querySelector('.blog-body');
|
|
if(container){
|
|
const text = container.textContent || '';
|
|
const words = text.trim().split(/\s+/).filter(Boolean).length;
|
|
const minutes = Math.max(1, Math.round(words / 200));
|
|
const rt = minutes + ' min read';
|
|
const el = document.getElementById('reading-time');
|
|
if(el){ el.insertAdjacentText('beforeend', rt); }
|
|
const el2 = document.getElementById('reading-time-inline');
|
|
if(el2){ el2.textContent = rt; }
|
|
}
|
|
} catch (e) {}
|
|
|
|
// Reading progress indicator
|
|
try {
|
|
const progressBar = document.getElementById('reading-progress');
|
|
const target = document.querySelector('.blog-body');
|
|
if(progressBar && target){
|
|
let start = 0;
|
|
let end = 0;
|
|
const recalc = () => {
|
|
const rect = target.getBoundingClientRect();
|
|
const scrollTop = window.scrollY || window.pageYOffset;
|
|
start = scrollTop + rect.top - 120;
|
|
end = start + target.offsetHeight;
|
|
};
|
|
const update = () => {
|
|
if(!end){ recalc(); }
|
|
const scrollPos = window.scrollY || window.pageYOffset;
|
|
const distance = end - start;
|
|
if(distance <= 0){ return; }
|
|
const progress = Math.min(1, Math.max(0, (scrollPos - start) / distance));
|
|
progressBar.style.width = (progress * 100).toFixed(2) + '%';
|
|
};
|
|
recalc();
|
|
window.addEventListener('scroll', update, { passive: true });
|
|
window.addEventListener('resize', () => {
|
|
end = 0;
|
|
recalc();
|
|
update();
|
|
});
|
|
update();
|
|
}
|
|
} catch (e) {}
|
|
|
|
// TOC with active state tracking and sticky positioning
|
|
try {
|
|
const container = document.querySelector('.blog-body');
|
|
const contentWrapper = document.getElementById('content-wrapper');
|
|
if(!container){ return; }
|
|
const headings = container.querySelectorAll('h2');
|
|
if(!headings.length){ return; }
|
|
const toc = document.getElementById('toc');
|
|
const floatingToc = document.getElementById('floating-toc');
|
|
if(!toc){ return; }
|
|
const tocLinks = [];
|
|
headings.forEach(h => {
|
|
if(!h.id){
|
|
h.id = h.textContent.toLowerCase().replace(/[^a-z0-9]+/g,'-').replace(/^-+|-+$/g,'');
|
|
}
|
|
const a = document.createElement('a');
|
|
a.href = '#' + h.id;
|
|
a.textContent = h.textContent;
|
|
a.className = h.tagName === 'H3' ? 'toc-h3' : '';
|
|
a.dataset.target = h.id;
|
|
toc.appendChild(a);
|
|
tocLinks.push({ link: a, heading: h });
|
|
});
|
|
|
|
// Track active TOC item and position on scroll
|
|
const updateToc = () => {
|
|
const scrollPos = window.scrollY + 150;
|
|
let activeIndex = 0;
|
|
tocLinks.forEach((item, i) => {
|
|
const rect = item.heading.getBoundingClientRect();
|
|
const top = rect.top + window.scrollY;
|
|
if(scrollPos >= top){
|
|
activeIndex = i;
|
|
}
|
|
});
|
|
tocLinks.forEach((item, i) => {
|
|
if(i === activeIndex){
|
|
item.link.classList.add('toc-active');
|
|
} else {
|
|
item.link.classList.remove('toc-active');
|
|
}
|
|
});
|
|
|
|
// Handle TOC positioning: top (absolute), fixed, or bottom (absolute)
|
|
if(floatingToc && contentWrapper){
|
|
const wrapperRect = contentWrapper.getBoundingClientRect();
|
|
const tocHeight = floatingToc.offsetHeight;
|
|
const viewportHeight = window.innerHeight;
|
|
const fixedTopPosition = (viewportHeight - tocHeight) / 2;
|
|
|
|
// When content top is above the point where TOC would be centered
|
|
const shouldBeFixed = wrapperRect.top < fixedTopPosition && wrapperRect.bottom > (fixedTopPosition + tocHeight);
|
|
|
|
// When content bottom is above where the fixed TOC would end
|
|
const shouldBeBottom = wrapperRect.bottom <= (fixedTopPosition + tocHeight);
|
|
|
|
floatingToc.classList.remove('is-fixed', 'is-bottom');
|
|
|
|
if(shouldBeBottom){
|
|
floatingToc.classList.add('is-bottom');
|
|
} else if(shouldBeFixed){
|
|
floatingToc.classList.add('is-fixed');
|
|
}
|
|
// else: stays at absolute top (default)
|
|
}
|
|
};
|
|
window.addEventListener('scroll', updateToc, { passive: true });
|
|
window.addEventListener('resize', updateToc, { passive: true });
|
|
updateToc();
|
|
} catch (e) {}
|
|
|
|
// Back to top button
|
|
try {
|
|
const backToTopBtn = document.getElementById('back-to-top');
|
|
if(backToTopBtn){
|
|
const toggleVisibility = () => {
|
|
if(window.scrollY > 400){
|
|
backToTopBtn.classList.add('visible');
|
|
} else {
|
|
backToTopBtn.classList.remove('visible');
|
|
}
|
|
};
|
|
window.addEventListener('scroll', toggleVisibility, { passive: true });
|
|
toggleVisibility();
|
|
backToTopBtn.addEventListener('click', () => {
|
|
window.scrollTo({ top: 0, behavior: 'smooth' });
|
|
});
|
|
}
|
|
} catch (e) {}
|
|
|
|
// Stabilize images inside blog body (add width/height if missing & lazy-load non-hero images)
|
|
try {
|
|
const imgs = document.querySelectorAll('.blog-body img');
|
|
imgs.forEach((img, index) => {
|
|
// If width/height already specified, skip dimension inference
|
|
if(!img.hasAttribute('width') || !img.hasAttribute('height')){
|
|
if(img.naturalWidth && img.naturalHeight){
|
|
img.setAttribute('width', img.naturalWidth);
|
|
img.setAttribute('height', img.naturalHeight);
|
|
} else {
|
|
// If not yet loaded, attach a one-time listener
|
|
img.addEventListener('load', function handler(){
|
|
if(!img.hasAttribute('width') && img.naturalWidth){ img.setAttribute('width', img.naturalWidth); }
|
|
if(!img.hasAttribute('height') && img.naturalHeight){ img.setAttribute('height', img.naturalHeight); }
|
|
img.removeEventListener('load', handler);
|
|
});
|
|
}
|
|
}
|
|
// Lazy-load images after the first one (often top/hero) for better LCP while reducing CLS
|
|
if(index > 0 && !img.hasAttribute('loading')){
|
|
img.setAttribute('loading', 'lazy');
|
|
}
|
|
if(!img.hasAttribute('decoding')){
|
|
img.setAttribute('decoding', 'async');
|
|
}
|
|
// Ensure display block for centered images without causing late shifts
|
|
if(!img.className.includes('inline') && !img.className.includes('block')){
|
|
img.classList.add('block');
|
|
}
|
|
});
|
|
} catch(e) {}
|
|
|
|
// Mermaid diagrams
|
|
try {
|
|
const mermaidCodeBlocks = document.querySelectorAll('.blog-body pre code.language-mermaid, .blog-body pre code.mermaid, .blog-body pre code[class*="language-mermaid"], .blog-body pre code[class*="mermaid"]');
|
|
if(mermaidCodeBlocks.length){
|
|
// Dynamically load Mermaid only if needed to avoid extra payload on pages without diagrams
|
|
const script = document.createElement('script');
|
|
script.src = '/oneuptime-assets/mermaid/mermaid.min.js';
|
|
script.async = true;
|
|
script.onload = () => {
|
|
if(!window.mermaid){ return; }
|
|
const prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
window.mermaid.initialize({
|
|
startOnLoad: false,
|
|
securityLevel: 'loose', // Content is trusted (owned blog); allows links & styling
|
|
theme: prefersDark ? 'dark' : 'default'
|
|
});
|
|
mermaidCodeBlocks.forEach((codeEl, i) => {
|
|
// Avoid double-processing
|
|
if(codeEl.dataset.mermaidProcessed){ return; }
|
|
const pre = codeEl.closest('pre');
|
|
if(!pre){ return; }
|
|
const def = codeEl.textContent.trim(); // Use textContent to ignore highlight.js span wrappers
|
|
const container = document.createElement('div');
|
|
container.className = 'mermaid my-6';
|
|
// Provide a deterministic ID (optional)
|
|
container.id = 'mermaid-diagram-' + (i+1);
|
|
container.textContent = def;
|
|
pre.replaceWith(container);
|
|
codeEl.dataset.mermaidProcessed = 'true';
|
|
});
|
|
try { window.mermaid.run && window.mermaid.run(); } catch(_) {}
|
|
};
|
|
document.head.appendChild(script);
|
|
}
|
|
} catch(e) {}
|
|
|
|
// Anchor links on headings
|
|
try {
|
|
var headingsForAnchors = document.querySelectorAll('.blog-body h1, .blog-body h2, .blog-body h3, .blog-body h4');
|
|
headingsForAnchors.forEach(function(h) {
|
|
if(!h.id){
|
|
h.id = h.textContent.toLowerCase().replace(/[^a-z0-9]+/g,'-').replace(/^-+|-+$/g,'');
|
|
}
|
|
h.style.position = 'relative';
|
|
var anchor = document.createElement('a');
|
|
anchor.href = '#' + h.id;
|
|
anchor.className = 'heading-anchor';
|
|
anchor.setAttribute('aria-label', 'Link to ' + h.textContent);
|
|
anchor.innerHTML = '<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"/></svg>';
|
|
h.appendChild(anchor);
|
|
});
|
|
} catch(e) {}
|
|
|
|
// Image lightbox
|
|
try {
|
|
var overlay = document.getElementById('lightbox-overlay');
|
|
var lightboxImg = document.getElementById('lightbox-img');
|
|
if(overlay && lightboxImg) {
|
|
var blogImages = document.querySelectorAll('.blog-body img');
|
|
blogImages.forEach(function(img) {
|
|
img.addEventListener('click', function() {
|
|
lightboxImg.src = img.src;
|
|
lightboxImg.alt = img.alt || '';
|
|
overlay.classList.add('active');
|
|
document.body.style.overflow = 'hidden';
|
|
});
|
|
});
|
|
var closeLightbox = function() {
|
|
overlay.classList.remove('active');
|
|
document.body.style.overflow = '';
|
|
lightboxImg.src = '';
|
|
};
|
|
overlay.addEventListener('click', function(e) {
|
|
if(e.target === overlay || e.target.closest('.blog-lightbox-close')) {
|
|
closeLightbox();
|
|
}
|
|
});
|
|
document.addEventListener('keydown', function(e) {
|
|
if(e.key === 'Escape' && overlay.classList.contains('active')) {
|
|
closeLightbox();
|
|
}
|
|
});
|
|
}
|
|
} catch(e) {}
|
|
|
|
// Collapsible long code blocks (>100 lines)
|
|
try {
|
|
var allPres = document.querySelectorAll('.blog-body pre');
|
|
allPres.forEach(function(pre) {
|
|
var codeEl = pre.querySelector('code');
|
|
if(!codeEl) return;
|
|
var lineCount = (codeEl.textContent || '').split('\n').length;
|
|
if(lineCount > 100) {
|
|
pre.classList.add('collapsible-code');
|
|
pre.classList.add('collapsed');
|
|
var expandBtn = document.createElement('button');
|
|
expandBtn.className = 'code-expand-btn';
|
|
expandBtn.innerHTML = '<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7"/></svg> Show all ' + lineCount + ' lines';
|
|
expandBtn.addEventListener('click', function() {
|
|
if(pre.classList.contains('collapsed')) {
|
|
pre.classList.remove('collapsed');
|
|
expandBtn.innerHTML = '<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M5 15l7-7 7 7"/></svg> Show less';
|
|
} else {
|
|
pre.classList.add('collapsed');
|
|
expandBtn.innerHTML = '<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7"/></svg> Show all ' + lineCount + ' lines';
|
|
pre.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
|
}
|
|
});
|
|
pre.parentNode.insertBefore(expandBtn, pre.nextSibling);
|
|
}
|
|
});
|
|
} catch(e) {}
|
|
|
|
// Time remaining indicator
|
|
try {
|
|
var blogBody = document.querySelector('.blog-body');
|
|
var timeRemainingEl = document.getElementById('time-remaining');
|
|
var timeRemainingText = document.getElementById('time-remaining-text');
|
|
if(blogBody && timeRemainingEl && timeRemainingText) {
|
|
var totalWords = (blogBody.textContent || '').trim().split(/\s+/).filter(Boolean).length;
|
|
var wpm = 200;
|
|
var updateTimeRemaining = function() {
|
|
var rect = blogBody.getBoundingClientRect();
|
|
var scrollTop = window.scrollY || window.pageYOffset;
|
|
var bodyTop = scrollTop + rect.top;
|
|
var bodyHeight = blogBody.offsetHeight;
|
|
var progress = Math.min(1, Math.max(0, (scrollTop - bodyTop + window.innerHeight * 0.5) / bodyHeight));
|
|
var wordsRemaining = Math.max(0, Math.round(totalWords * (1 - progress)));
|
|
var minsRemaining = Math.max(0, Math.ceil(wordsRemaining / wpm));
|
|
|
|
if(progress > 0.02 && progress < 0.95) {
|
|
timeRemainingEl.classList.add('visible');
|
|
if(minsRemaining <= 1) {
|
|
timeRemainingText.textContent = 'Less than 1 min left';
|
|
} else {
|
|
timeRemainingText.textContent = minsRemaining + ' min remaining';
|
|
}
|
|
} else {
|
|
timeRemainingEl.classList.remove('visible');
|
|
}
|
|
};
|
|
window.addEventListener('scroll', updateTimeRemaining, { passive: true });
|
|
updateTimeRemaining();
|
|
}
|
|
} catch(e) {}
|
|
|
|
// Copy link buttons
|
|
try {
|
|
var copyLinkBtns = document.querySelectorAll('.copy-link-btn');
|
|
copyLinkBtns.forEach(function(btn) {
|
|
btn.addEventListener('click', function() {
|
|
var url = btn.dataset.url || window.location.href;
|
|
navigator.clipboard.writeText(url).then(function() {
|
|
var icon = btn.querySelector('.copy-link-icon');
|
|
var check = btn.querySelector('.copy-link-check');
|
|
if(icon) icon.classList.add('hidden');
|
|
if(check) check.classList.remove('hidden');
|
|
setTimeout(function() {
|
|
if(icon) icon.classList.remove('hidden');
|
|
if(check) check.classList.add('hidden');
|
|
}, 2000);
|
|
});
|
|
});
|
|
});
|
|
} catch(e) {}
|
|
|
|
// Validation report modal: open from the footer badge, lazily load the report on first open.
|
|
try {
|
|
var validationModal = document.getElementById('validation-modal');
|
|
var validationOpenBtn = document.getElementById('validation-open');
|
|
if (validationModal && validationOpenBtn) {
|
|
var validationBackdrop = document.getElementById('validation-modal-backdrop');
|
|
var validationPanelEl = document.getElementById('validation-modal-panel');
|
|
var validationContent = document.getElementById('validation-modal-content');
|
|
var validationLoaded = false;
|
|
var lastFocused = null;
|
|
|
|
var loadReport = function() {
|
|
if (validationLoaded) { return; }
|
|
validationLoaded = true;
|
|
var file = validationModal.dataset.file;
|
|
fetch('/blog/post/' + encodeURIComponent(file) + '/validation-summary')
|
|
.then(function(resp) {
|
|
if (!resp.ok) { throw new Error('Not available'); }
|
|
return resp.text();
|
|
})
|
|
.then(function(html) {
|
|
if (validationContent) { validationContent.innerHTML = html; }
|
|
})
|
|
.catch(function() {
|
|
validationLoaded = false;
|
|
if (validationContent) {
|
|
validationContent.innerHTML = '<div class="text-sm text-gray-500 py-6 text-center">The validation report is not available for this post.</div>';
|
|
}
|
|
});
|
|
};
|
|
|
|
var openModal = function() {
|
|
lastFocused = document.activeElement;
|
|
validationModal.classList.remove('hidden');
|
|
document.body.style.overflow = 'hidden';
|
|
// next frame so the transition runs
|
|
requestAnimationFrame(function() {
|
|
if (validationBackdrop) { validationBackdrop.classList.remove('opacity-0'); }
|
|
if (validationPanelEl) { validationPanelEl.classList.remove('opacity-0', 'translate-y-4'); }
|
|
});
|
|
var closeBtn = validationModal.querySelector('.validation-close');
|
|
if (closeBtn) { closeBtn.focus(); }
|
|
loadReport();
|
|
};
|
|
|
|
var closeModal = function() {
|
|
if (validationBackdrop) { validationBackdrop.classList.add('opacity-0'); }
|
|
if (validationPanelEl) { validationPanelEl.classList.add('opacity-0', 'translate-y-4'); }
|
|
document.body.style.overflow = '';
|
|
setTimeout(function() { validationModal.classList.add('hidden'); }, 200);
|
|
if (lastFocused && lastFocused.focus) { lastFocused.focus(); }
|
|
};
|
|
|
|
validationOpenBtn.addEventListener('click', openModal);
|
|
validationModal.querySelectorAll('.validation-close').forEach(function(btn) {
|
|
btn.addEventListener('click', closeModal);
|
|
});
|
|
if (validationBackdrop) { validationBackdrop.addEventListener('click', closeModal); }
|
|
document.addEventListener('keydown', function(e) {
|
|
if (e.key === 'Escape' && !validationModal.classList.contains('hidden')) {
|
|
closeModal();
|
|
}
|
|
});
|
|
}
|
|
} catch(e) {}
|
|
})();
|
|
</script>
|
|
<!--
|
|
CTA tracking is centralized in Home/Views/head-basic.ejs.
|
|
Keep this partial as a no-op while existing templates still include it so a
|
|
single click produces one dataLayer event instead of duplicate gtag and
|
|
dataLayer pushes.
|
|
-->
|
|
<script type="module" src="https://static.cloudflareinsights.com/beacon.min.js/v31edd6df95cf4e85bb4c19e7a9bdbcba1788362987495" integrity="sha512-iIg7k2xntmwu6/uSb5tpc/hySgZc4eoL31yB29W6tJFo2akwjPWcEqnCEdJvGexCL0KEQwVYv5BlowfhVz26hg==" data-cf-beacon='{"version":"2024.11.0","token":"8bb453bcc3d9486d99f39189bcc11e9d","r":1,"spa":2}' crossorigin="anonymous"></script>
|
|
</body>
|
|
|
|
</html> |