Files
oneuptime/Home/Views/product-compare.ejs
Jamie Mallers 62f6900dd2 Merge origin/master - resolve conflict in product-compare.ejs
Keep both:
- Updated meta description from master
- FAQ schema for rich snippets from this branch
2026-02-08 15:20:49 +00:00

582 lines
38 KiB
Plaintext

<!DOCTYPE html>
<html lang="en" id="home">
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<head>
<title><%= productConfig.productName %> Alternative - OneUptime | Open Source | 2026 Comparison</title>
<meta name="description"
content="Compare <%= productConfig.productName %> vs OneUptime. Free open-source alternative with unlimited monitors, status pages & on-call. See pricing, features & migration guide.">
<!-- FAQ Schema for rich snippets -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
<% for(var faqIdx=0; faqIdx < productConfig.faq.length; faqIdx++) { %>
{
"@type": "Question",
"name": "<%= productConfig.faq[faqIdx].question.replace(/"/g, '\\"') %>",
"acceptedAnswer": {
"@type": "Answer",
"text": "<%= productConfig.faq[faqIdx].answer.replace(/"/g, '\\"') %>"
}
}<%= faqIdx < productConfig.faq.length - 1 ? ',' : '' %>
<% } %>
]
}
</script>
<%- include('head', {
enableGoogleTagManager: typeof enableGoogleTagManager !== 'undefined' ? enableGoogleTagManager : false
}) -%>
<style>
/* Card Glow Styles - Matching Home page */
.compare-card {
position: relative;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.compare-card:hover {
transform: translateY(-2px);
}
/* Glow colors */
.glow-emerald:hover { box-shadow: 0 0 0 1px rgb(16 185 129 / 0.2), 0 4px 16px -4px rgb(16 185 129 / 0.15), 0 0 24px -8px rgb(16 185 129 / 0.1); }
.glow-blue:hover { box-shadow: 0 0 0 1px rgb(59 130 246 / 0.2), 0 4px 16px -4px rgb(59 130 246 / 0.15), 0 0 24px -8px rgb(59 130 246 / 0.1); }
.glow-rose:hover { box-shadow: 0 0 0 1px rgb(244 63 94 / 0.2), 0 4px 16px -4px rgb(244 63 94 / 0.15), 0 0 24px -8px rgb(244 63 94 / 0.1); }
.glow-stone:hover { box-shadow: 0 0 0 1px rgb(120 113 108 / 0.2), 0 4px 16px -4px rgb(120 113 108 / 0.15), 0 0 24px -8px rgb(120 113 108 / 0.1); }
.glow-amber:hover { box-shadow: 0 0 0 1px rgb(245 158 11 / 0.2), 0 4px 16px -4px rgb(245 158 11 / 0.15), 0 0 24px -8px rgb(245 158 11 / 0.1); }
.glow-purple:hover { box-shadow: 0 0 0 1px rgb(168 85 247 / 0.2), 0 4px 16px -4px rgb(168 85 247 / 0.15), 0 0 24px -8px rgb(168 85 247 / 0.1); }
</style>
</head>
<body>
<%- include('nav') -%>
<main id="main-content">
<!-- Hero Section -->
<div class="relative isolate bg-white overflow-hidden" id="compare-hero">
<!-- Grid background -->
<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_60%_50%_at_50%_0%,#000_70%,transparent_110%)]"></div>
<!-- Cursor glow -->
<div id="hero-grid-glow" class="absolute inset-0 -z-9 pointer-events-none" style="opacity: 0; transition: opacity 0.3s ease-out; background: linear-gradient(to right, rgba(59, 130, 246, 0.3) 1px, transparent 1px), linear-gradient(to bottom, rgba(59, 130, 246, 0.3) 1px, transparent 1px); background-size: 4rem 4rem; -webkit-mask-image: radial-gradient(circle 250px at var(--mouse-x, 50%) var(--mouse-y, 50%), black 0%, transparent 100%); mask-image: radial-gradient(circle 250px at var(--mouse-x, 50%) var(--mouse-y, 50%), black 0%, transparent 100%);"></div>
<div class="py-24 sm:py-32 lg:py-40">
<div class="mx-auto max-w-7xl px-6 lg:px-8">
<div class="mx-auto max-w-3xl text-center">
<!-- 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 Alternative</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>
<!-- Headline -->
<h1 class="text-4xl font-semibold tracking-tight text-gray-900 sm:text-5xl lg:text-6xl lg:leading-[1.1]">
The Open-Source <br class="hidden sm:block" /><%= productConfig.productName %> Alternative
</h1>
<!-- Subheadline -->
<p class="mt-6 text-lg leading-8 text-gray-600 max-w-2xl mx-auto">
<%= productConfig.tagline %>
</p>
<!-- CTAs -->
<div class="mt-10 flex flex-col sm:flex-row items-center justify-center 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-3 text-sm font-medium text-white shadow-sm transition-all hover:bg-gray-800">
Start free — no credit card
<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-3 text-sm font-medium text-gray-700 shadow-sm ring-1 ring-inset ring-gray-300 transition-all hover:bg-gray-50">
See it in action
</a>
</div>
<!-- Trust signal -->
<p class="mt-6 text-sm text-gray-500">
Self-host for free or use our cloud. No vendor lock-in.
</p>
</div>
</div>
</div>
</div>
<!-- Overview Section -->
<section class="py-24 sm:py-32 bg-gray-50">
<div class="mx-auto max-w-7xl px-6 lg:px-8">
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 lg:gap-16">
<!-- Competitor -->
<div class="rounded-2xl bg-white p-8 ring-1 ring-gray-200">
<div class="flex items-center gap-4 mb-6">
<div class="flex h-12 w-12 items-center justify-center rounded-xl bg-gray-100">
<img src="<%= productConfig.iconUrl %>" alt="<%= productConfig.productName %>" class="h-8 w-8 object-contain">
</div>
<div>
<h3 class="text-xl font-semibold text-gray-900"><%= productConfig.productName %></h3>
</div>
</div>
<p class="text-gray-600 leading-relaxed"><%= productConfig.productDescription %></p>
<div class="mt-6 pt-6 border-t border-gray-100">
<p class="text-sm text-gray-500"><%= productConfig.competitorFocus %></p>
</div>
</div>
<!-- OneUptime -->
<div class="rounded-2xl bg-gray-900 p-8 text-white">
<div class="flex items-center gap-4 mb-6">
<div class="h-12 w-12 rounded-xl bg-white overflow-hidden">
<img src="/img/OneUptimePNG/2.png" alt="OneUptime" class="h-full w-full object-contain">
</div>
<div>
<h3 class="text-xl font-semibold">OneUptime</h3>
</div>
</div>
<p class="text-gray-300 leading-relaxed"><%= productConfig.oneUptimeDescription %></p>
<div class="mt-6 pt-6 border-t border-white/10">
<p class="text-sm text-gray-400"><%= productConfig.oneuptimeFocus %></p>
</div>
</div>
</div>
</div>
</section>
<!-- Platform Section - Dark -->
<section class="relative py-24 sm:py-32 bg-gray-900 overflow-hidden">
<!-- Mouse glow -->
<div id="platform-mouse-glow" class="pointer-events-none absolute w-[600px] h-[600px] rounded-full opacity-0 transition-opacity duration-300" style="background: radial-gradient(circle at center, rgba(255, 255, 255, 0.08) 0%, rgba(255, 255, 255, 0.03) 30%, transparent 60%); transform: translate(-50%, -50%);"></div>
<div class="relative mx-auto max-w-7xl px-6 lg:px-8">
<!-- Header -->
<div class="text-center mb-16">
<div class="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-white/5 border border-white/10 mb-8">
<svg class="w-4 h-4 text-gray-400" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6A2.25 2.25 0 016 3.75h2.25A2.25 2.25 0 0110.5 6v2.25a2.25 2.25 0 01-2.25 2.25H6a2.25 2.25 0 01-2.25-2.25V6zM3.75 15.75A2.25 2.25 0 016 13.5h2.25a2.25 2.25 0 012.25 2.25V18a2.25 2.25 0 01-2.25 2.25H6A2.25 2.25 0 013.75 18v-2.25zM13.5 6a2.25 2.25 0 012.25-2.25H18A2.25 2.25 0 0120.25 6v2.25A2.25 2.25 0 0118 10.5h-2.25a2.25 2.25 0 01-2.25-2.25V6zM13.5 15.75a2.25 2.25 0 012.25-2.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-2.25A2.25 2.25 0 0113.5 18v-2.25z" />
</svg>
<span class="text-sm text-gray-400">Complete Platform</span>
</div>
<h2 class="text-4xl sm:text-5xl font-semibold tracking-tight leading-[1.1]">
<span class="text-gray-400 block">Everything you need.</span>
<span class="text-white block">One unified platform.</span>
</h2>
<p class="mt-6 text-lg text-gray-400 max-w-2xl mx-auto leading-relaxed">
While <%= productConfig.productName %> focuses on specific capabilities, OneUptime provides a complete observability solution.
</p>
</div>
<!-- Feature Grid -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<!-- Monitoring -->
<a href="/product/uptime-monitoring" class="group p-6 rounded-2xl bg-white/[0.03] border border-white/[0.06] transition-all duration-300 hover:bg-white/[0.06] hover:border-white/[0.12]">
<div class="flex h-10 w-10 items-center justify-center rounded-lg bg-blue-500/20 mb-4">
<svg class="h-5 w-5 text-blue-400" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<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" />
</svg>
</div>
<h3 class="text-lg font-semibold text-white mb-2">Monitoring</h3>
<p class="text-sm text-gray-400 leading-relaxed">HTTP, TCP, UDP, DNS. Global probe network. 1-second checks.</p>
</a>
<!-- Status Pages -->
<a href="/product/status-page" class="group p-6 rounded-2xl bg-white/[0.03] border border-white/[0.06] transition-all duration-300 hover:bg-white/[0.06] hover:border-white/[0.12]">
<div class="flex h-10 w-10 items-center justify-center rounded-lg bg-emerald-500/20 mb-4">
<svg class="h-5 w-5 text-emerald-400" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<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" />
</svg>
</div>
<h3 class="text-lg font-semibold text-white mb-2">Status Pages</h3>
<p class="text-sm text-gray-400 leading-relaxed">Public & private. Unlimited subscribers. Custom domains.</p>
</a>
<!-- On-Call -->
<a href="/product/on-call" class="group p-6 rounded-2xl bg-white/[0.03] border border-white/[0.06] transition-all duration-300 hover:bg-white/[0.06] hover:border-white/[0.12]">
<div class="flex h-10 w-10 items-center justify-center rounded-lg bg-amber-500/20 mb-4">
<svg class="h-5 w-5 text-amber-400" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0" />
</svg>
</div>
<h3 class="text-lg font-semibold text-white mb-2">On-Call</h3>
<p class="text-sm text-gray-400 leading-relaxed">Rotations, escalations. SMS, call, email, Slack, Teams.</p>
</a>
<!-- Incidents -->
<a href="/product/incident-management" class="group p-6 rounded-2xl bg-white/[0.03] border border-white/[0.06] transition-all duration-300 hover:bg-white/[0.06] hover:border-white/[0.12]">
<div class="flex h-10 w-10 items-center justify-center rounded-lg bg-rose-500/20 mb-4">
<svg class="h-5 w-5 text-rose-400" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<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" />
</svg>
</div>
<h3 class="text-lg font-semibold text-white mb-2">Incidents</h3>
<p class="text-sm text-gray-400 leading-relaxed">Full workflow. Timelines. Postmortems. Collaboration.</p>
</a>
</div>
<!-- Additional capabilities row -->
<div class="mt-4 grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-4">
<a href="/product/logs-management" class="p-4 rounded-xl bg-white/[0.02] border border-white/[0.04] text-center transition-all hover:bg-white/[0.04]">
<span class="text-sm text-gray-400">Logs</span>
</a>
<a href="/product/metrics" class="p-4 rounded-xl bg-white/[0.02] border border-white/[0.04] text-center transition-all hover:bg-white/[0.04]">
<span class="text-sm text-gray-400">Metrics</span>
</a>
<a href="/product/traces" class="p-4 rounded-xl bg-white/[0.02] border border-white/[0.04] text-center transition-all hover:bg-white/[0.04]">
<span class="text-sm text-gray-400">Traces</span>
</a>
<a href="/product/workflows" class="p-4 rounded-xl bg-white/[0.02] border border-white/[0.04] text-center transition-all hover:bg-white/[0.04]">
<span class="text-sm text-gray-400">Workflows</span>
</a>
<a href="/product/dashboards" class="p-4 rounded-xl bg-white/[0.02] border border-white/[0.04] text-center transition-all hover:bg-white/[0.04]">
<span class="text-sm text-gray-400">Dashboards</span>
</a>
<a href="/product/copilot" class="p-4 rounded-xl bg-white/[0.02] border border-white/[0.04] text-center transition-all hover:bg-white/[0.04]">
<span class="text-sm text-gray-400">AI Copilot</span>
</a>
</div>
</div>
</section>
<!-- Key Differences -->
<section class="py-24 sm:py-32 bg-white">
<div class="mx-auto max-w-7xl px-6 lg:px-8">
<div class="text-center mb-16">
<div class="inline-flex items-center gap-2 rounded-full bg-gray-900 px-4 py-1.5 text-sm text-white mb-6">
<svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M9.813 15.904L9 18.75l-.813-2.846a4.5 4.5 0 00-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 003.09-3.09L9 5.25l.813 2.846a4.5 4.5 0 003.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 00-3.09 3.09zM18.259 8.715L18 9.75l-.259-1.035a3.375 3.375 0 00-2.455-2.456L14.25 6l1.036-.259a3.375 3.375 0 002.455-2.456L18 2.25l.259 1.035a3.375 3.375 0 002.456 2.456L21.75 6l-1.035.259a3.375 3.375 0 00-2.456 2.456zM16.894 20.567L16.5 21.75l-.394-1.183a2.25 2.25 0 00-1.423-1.423L13.5 18.75l1.183-.394a2.25 2.25 0 001.423-1.423l.394-1.183.394 1.183a2.25 2.25 0 001.423 1.423l1.183.394-1.183.394a2.25 2.25 0 00-1.423 1.423z" />
</svg>
<span>Key Advantages</span>
</div>
<h2 class="text-4xl font-semibold tracking-tight text-gray-900 sm:text-5xl">
Why teams choose OneUptime
</h2>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<% for(var k=0; k<productConfig.keyDifferences.length; k++) { %>
<div class="compare-card rounded-2xl bg-white p-6 ring-1 ring-gray-200 <%= k % 6 === 0 ? 'glow-blue' : k % 6 === 1 ? 'glow-emerald' : k % 6 === 2 ? 'glow-amber' : k % 6 === 3 ? 'glow-rose' : k % 6 === 4 ? 'glow-purple' : 'glow-stone' %>">
<div class="flex h-10 w-10 items-center justify-center rounded-lg <%= k % 6 === 0 ? 'bg-blue-100' : k % 6 === 1 ? 'bg-emerald-100' : k % 6 === 2 ? 'bg-amber-100' : k % 6 === 3 ? 'bg-rose-100' : k % 6 === 4 ? 'bg-purple-100' : 'bg-stone-100' %> mb-4">
<% if(productConfig.keyDifferences[k].icon === "monitoring" || productConfig.keyDifferences[k].icon === "unlimited") { %>
<svg class="h-5 w-5 <%= k % 6 === 0 ? 'text-blue-600' : k % 6 === 1 ? 'text-emerald-600' : k % 6 === 2 ? 'text-amber-600' : k % 6 === 3 ? 'text-rose-600' : k % 6 === 4 ? 'text-purple-600' : 'text-stone-600' %>" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<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" />
</svg>
<% } else if(productConfig.keyDifferences[k].icon === "status-page") { %>
<svg class="h-5 w-5 <%= k % 6 === 0 ? 'text-blue-600' : k % 6 === 1 ? 'text-emerald-600' : k % 6 === 2 ? 'text-amber-600' : k % 6 === 3 ? 'text-rose-600' : k % 6 === 4 ? 'text-purple-600' : 'text-stone-600' %>" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<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" />
</svg>
<% } else if(productConfig.keyDifferences[k].icon === "on-call") { %>
<svg class="h-5 w-5 <%= k % 6 === 0 ? 'text-blue-600' : k % 6 === 1 ? 'text-emerald-600' : k % 6 === 2 ? 'text-amber-600' : k % 6 === 3 ? 'text-rose-600' : k % 6 === 4 ? 'text-purple-600' : 'text-stone-600' %>" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0" />
</svg>
<% } else if(productConfig.keyDifferences[k].icon === "incident") { %>
<svg class="h-5 w-5 <%= k % 6 === 0 ? 'text-blue-600' : k % 6 === 1 ? 'text-emerald-600' : k % 6 === 2 ? 'text-amber-600' : k % 6 === 3 ? 'text-rose-600' : k % 6 === 4 ? 'text-purple-600' : 'text-stone-600' %>" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<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" />
</svg>
<% } else if(productConfig.keyDifferences[k].icon === "unified") { %>
<svg class="h-5 w-5 <%= k % 6 === 0 ? 'text-blue-600' : k % 6 === 1 ? 'text-emerald-600' : k % 6 === 2 ? 'text-amber-600' : k % 6 === 3 ? 'text-rose-600' : k % 6 === 4 ? 'text-purple-600' : 'text-stone-600' %>" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6A2.25 2.25 0 016 3.75h2.25A2.25 2.25 0 0110.5 6v2.25a2.25 2.25 0 01-2.25 2.25H6a2.25 2.25 0 01-2.25-2.25V6zM3.75 15.75A2.25 2.25 0 016 13.5h2.25a2.25 2.25 0 012.25 2.25V18a2.25 2.25 0 01-2.25 2.25H6A2.25 2.25 0 013.75 18v-2.25zM13.5 6a2.25 2.25 0 012.25-2.25H18A2.25 2.25 0 0120.25 6v2.25A2.25 2.25 0 0118 10.5h-2.25a2.25 2.25 0 01-2.25-2.25V6zM13.5 15.75a2.25 2.25 0 012.25-2.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-2.25A2.25 2.25 0 0113.5 18v-2.25z" />
</svg>
<% } else if(productConfig.keyDifferences[k].icon === "open-source") { %>
<svg class="h-5 w-5 <%= k % 6 === 0 ? 'text-blue-600' : k % 6 === 1 ? 'text-emerald-600' : k % 6 === 2 ? 'text-amber-600' : k % 6 === 3 ? 'text-rose-600' : k % 6 === 4 ? 'text-purple-600' : 'text-stone-600' %>" viewBox="0 0 24 24" fill="currentColor">
<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>
<% } else { %>
<svg class="h-5 w-5 <%= k % 6 === 0 ? 'text-blue-600' : k % 6 === 1 ? 'text-emerald-600' : k % 6 === 2 ? 'text-amber-600' : k % 6 === 3 ? 'text-rose-600' : k % 6 === 4 ? 'text-purple-600' : 'text-stone-600' %>" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M9.813 15.904L9 18.75l-.813-2.846a4.5 4.5 0 00-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 003.09-3.09L9 5.25l.813 2.846a4.5 4.5 0 003.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 00-3.09 3.09z" />
</svg>
<% } %>
</div>
<h3 class="text-lg font-semibold text-gray-900 mb-2"><%= productConfig.keyDifferences[k].title %></h3>
<p class="text-sm text-gray-600 leading-relaxed"><%= productConfig.keyDifferences[k].description %></p>
</div>
<% } %>
</div>
</div>
</section>
<!-- Feature Comparison Table -->
<section class="py-24 sm:py-32 bg-gray-50">
<div class="mx-auto max-w-7xl px-6 lg:px-8">
<div class="text-center mb-16">
<h2 class="text-3xl font-semibold tracking-tight text-gray-900 sm:text-4xl">
Feature comparison
</h2>
<p class="mt-4 text-lg text-gray-600">
A detailed look at capabilities
</p>
</div>
<!-- Desktop Table -->
<div class="hidden lg:block">
<div class="rounded-2xl bg-white ring-1 ring-gray-200 overflow-hidden">
<table class="w-full">
<thead>
<tr class="border-b border-gray-200">
<th scope="col" class="w-1/2 px-8 py-5 text-left text-sm font-semibold text-gray-900 bg-gray-50">Feature</th>
<th scope="col" class="w-1/4 px-8 py-5 text-center text-sm font-semibold text-gray-900 bg-gray-50"><%= productConfig.productName %></th>
<th scope="col" class="w-1/4 px-8 py-5 text-center text-sm font-semibold text-white bg-gray-900">OneUptime</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-100">
<% for(var i=0; i<productConfig.items.length; i++) {%>
<tr class="bg-gray-50/50">
<td colspan="3" class="px-8 py-4">
<span class="text-sm font-semibold text-gray-900"><%= productConfig.items[i].name %></span>
</td>
</tr>
<% for(var j=0; j<productConfig.items[i].data.length; j++) {%>
<tr class="hover:bg-gray-50/50 transition-colors">
<td class="px-8 py-4">
<p class="font-medium text-gray-900 text-sm"><%= productConfig.items[i].data[j].title %></p>
<p class="text-sm text-gray-500"><%= productConfig.items[i].data[j].description %></p>
</td>
<td class="px-8 py-4 text-center">
<% if(productConfig.items[i].data[j].productColumn === "tick"){ %>
<svg class="h-5 w-5 text-gray-600 mx-auto" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z" clip-rule="evenodd" />
</svg>
<% } else if(productConfig.items[i].data[j].productColumn === ""){ %>
<svg class="h-5 w-5 text-gray-300 mx-auto" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M4 10a.75.75 0 01.75-.75h10.5a.75.75 0 010 1.5H4.75A.75.75 0 014 10z" clip-rule="evenodd" />
</svg>
<% } else { %>
<span class="inline-flex items-center rounded-full bg-gray-100 px-2.5 py-0.5 text-xs text-gray-700"><%= productConfig.items[i].data[j].productColumn %></span>
<% } %>
</td>
<td class="px-8 py-4 text-center bg-gray-900/[0.02]">
<% if(productConfig.items[i].data[j].oneuptimeColumn === "tick"){ %>
<svg class="h-5 w-5 text-emerald-600 mx-auto" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z" clip-rule="evenodd" />
</svg>
<% } else if(productConfig.items[i].data[j].oneuptimeColumn === ""){ %>
<svg class="h-5 w-5 text-gray-300 mx-auto" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M4 10a.75.75 0 01.75-.75h10.5a.75.75 0 010 1.5H4.75A.75.75 0 014 10z" clip-rule="evenodd" />
</svg>
<% } else { %>
<span class="inline-flex items-center rounded-full bg-gray-900 px-2.5 py-0.5 text-xs font-medium text-white"><%= productConfig.items[i].data[j].oneuptimeColumn %></span>
<% } %>
</td>
</tr>
<% } %>
<% } %>
</tbody>
</table>
</div>
</div>
<!-- Mobile View -->
<div class="lg:hidden space-y-6">
<% for(var i=0; i<productConfig.items.length; i++) {%>
<div class="rounded-2xl bg-white ring-1 ring-gray-200 overflow-hidden">
<div class="px-6 py-4 bg-gray-50 border-b border-gray-200">
<h3 class="text-sm font-semibold text-gray-900"><%= productConfig.items[i].name %></h3>
</div>
<div class="divide-y divide-gray-100">
<% for(var j=0; j<productConfig.items[i].data.length; j++) {%>
<div class="p-4">
<p class="font-medium text-gray-900 text-sm mb-3"><%= productConfig.items[i].data[j].title %></p>
<div class="grid grid-cols-2 gap-4">
<div class="text-center p-3 rounded-lg bg-gray-50">
<p class="text-xs text-gray-500 mb-1"><%= productConfig.productName %></p>
<% if(productConfig.items[i].data[j].productColumn === "tick"){ %>
<svg class="h-5 w-5 text-gray-600 mx-auto" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z" clip-rule="evenodd" />
</svg>
<% } else if(productConfig.items[i].data[j].productColumn === ""){ %>
<svg class="h-5 w-5 text-gray-300 mx-auto" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M4 10a.75.75 0 01.75-.75h10.5a.75.75 0 010 1.5H4.75A.75.75 0 014 10z" clip-rule="evenodd" />
</svg>
<% } else { %>
<span class="text-xs text-gray-700"><%= productConfig.items[i].data[j].productColumn %></span>
<% } %>
</div>
<div class="text-center p-3 rounded-lg bg-gray-900">
<p class="text-xs text-gray-400 mb-1">OneUptime</p>
<% if(productConfig.items[i].data[j].oneuptimeColumn === "tick"){ %>
<svg class="h-5 w-5 text-emerald-400 mx-auto" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z" clip-rule="evenodd" />
</svg>
<% } else if(productConfig.items[i].data[j].oneuptimeColumn === ""){ %>
<svg class="h-5 w-5 text-gray-500 mx-auto" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M4 10a.75.75 0 01.75-.75h10.5a.75.75 0 010 1.5H4.75A.75.75 0 014 10z" clip-rule="evenodd" />
</svg>
<% } else { %>
<span class="text-xs text-white"><%= productConfig.items[i].data[j].oneuptimeColumn %></span>
<% } %>
</div>
</div>
</div>
<% } %>
</div>
</div>
<% } %>
</div>
</div>
</section>
<!-- Open Source Section -->
<section class="relative py-24 sm:py-32 bg-gray-900 overflow-hidden">
<div class="relative mx-auto max-w-7xl px-6 lg:px-8">
<div class="text-center">
<div class="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-white/5 border border-white/10 mb-8">
<svg class="w-4 h-4 text-gray-400" viewBox="0 0 24 24" fill="currentColor">
<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>
<span class="text-sm text-gray-400">Open Source</span>
</div>
<h2 class="text-4xl sm:text-5xl font-semibold tracking-tight leading-[1.1]">
<span class="text-gray-400 block">Proudly</span>
<span class="text-white block">open-source</span>
</h2>
<p class="mt-6 text-lg text-gray-400 max-w-2xl mx-auto leading-relaxed">
Full transparency, complete control. Audit the code, self-host on your infrastructure, zero vendor lock-in.
</p>
<div class="mt-12 grid grid-cols-1 sm:grid-cols-3 gap-4 max-w-3xl mx-auto">
<div class="p-6 rounded-2xl bg-white/[0.03] border border-white/[0.06]">
<div class="text-3xl font-semibold text-white mb-1">Apache 2.0</div>
<div class="text-sm text-gray-400">License</div>
</div>
<div class="p-6 rounded-2xl bg-white/[0.03] border border-white/[0.06]">
<div class="text-3xl font-semibold text-white mb-1">Self-Host</div>
<div class="text-sm text-gray-400">Your infrastructure</div>
</div>
<div class="p-6 rounded-2xl bg-white/[0.03] border border-white/[0.06]">
<div class="text-3xl font-semibold text-white mb-1">No Lock-in</div>
<div class="text-sm text-gray-400">Full control</div>
</div>
</div>
<div class="mt-10">
<a href="https://github.com/oneuptime/oneuptime" target="_blank" class="group inline-flex items-center gap-2.5 px-7 py-3.5 rounded-full font-medium text-sm transition-all duration-300 bg-white/[0.08] border border-white/[0.1] text-white hover:bg-white/[0.15]">
<svg class="w-5 h-5" viewBox="0 0 24 24" fill="currentColor">
<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>
<span>Star on GitHub</span>
<svg class="w-4 h-4 group-hover:translate-x-0.5 transition-transform" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M13.5 4.5 21 12m0 0-7.5 7.5M21 12H3" />
</svg>
</a>
</div>
</div>
</div>
</section>
<!-- FAQ Section -->
<section class="py-24 sm:py-32 bg-white">
<div class="mx-auto max-w-3xl px-6 lg:px-8">
<div class="text-center mb-16">
<h2 class="text-3xl font-semibold tracking-tight text-gray-900 sm:text-4xl">
Frequently asked questions
</h2>
</div>
<div class="space-y-4">
<% for(var i=0; i < productConfig.faq.length; i++) { %>
<details class="group rounded-2xl bg-gray-50 ring-1 ring-gray-200">
<summary class="flex cursor-pointer items-center justify-between px-6 py-5 hover:bg-gray-100 transition-colors rounded-2xl">
<h3 class="text-base font-medium text-gray-900 pr-4"><%= productConfig.faq[i].question %></h3>
<svg class="h-5 w-5 flex-shrink-0 text-gray-400 group-open:rotate-180 transition-transform" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 8.25l-7.5 7.5-7.5-7.5" />
</svg>
</summary>
<div class="px-6 pb-6">
<p class="text-gray-600 leading-relaxed"><%= productConfig.faq[i].answer %></p>
</div>
</details>
<% } %>
</div>
</div>
</section>
<!-- CTA Section -->
<%- include('cta') -%>
</main>
<%- include('footer') -%>
<script>
// Hero grid glow
(function() {
const heroSection = document.getElementById('compare-hero');
const gridGlowEffect = document.getElementById('hero-grid-glow');
if (!heroSection || !gridGlowEffect) return;
let isHovering = false;
let animationFrame = null;
let currentX = 0, currentY = 0, targetX = 0, targetY = 0;
function lerp(start, end, factor) { return start + (end - start) * factor; }
function animate() {
if (!isHovering) return;
currentX = lerp(currentX, targetX, 0.12);
currentY = lerp(currentY, targetY, 0.12);
gridGlowEffect.style.setProperty('--mouse-x', currentX + 'px');
gridGlowEffect.style.setProperty('--mouse-y', currentY + 'px');
animationFrame = requestAnimationFrame(animate);
}
heroSection.addEventListener('mouseenter', function() {
isHovering = true;
gridGlowEffect.style.opacity = '1';
animate();
});
heroSection.addEventListener('mousemove', function(e) {
const rect = heroSection.getBoundingClientRect();
targetX = e.clientX - rect.left;
targetY = e.clientY - rect.top;
if (!isHovering) { currentX = targetX; currentY = targetY; }
});
heroSection.addEventListener('mouseleave', function() {
isHovering = false;
gridGlowEffect.style.opacity = '0';
if (animationFrame) { cancelAnimationFrame(animationFrame); animationFrame = null; }
});
})();
// Platform section mouse glow
(function() {
const section = document.querySelector('section.bg-gray-900');
const glow = document.getElementById('platform-mouse-glow');
if (!section || !glow) return;
let rafId = null;
let targetX = 0, targetY = 0, currentX = 0, currentY = 0;
function lerp(start, end, factor) { return start + (end - start) * factor; }
function animate() {
currentX = lerp(currentX, targetX, 0.15);
currentY = lerp(currentY, targetY, 0.15);
glow.style.left = currentX + 'px';
glow.style.top = currentY + 'px';
if (Math.abs(targetX - currentX) > 0.1 || Math.abs(targetY - currentY) > 0.1) {
rafId = requestAnimationFrame(animate);
} else { rafId = null; }
}
section.addEventListener('mousemove', function(e) {
const rect = section.getBoundingClientRect();
targetX = e.clientX - rect.left;
targetY = e.clientY - rect.top;
if (!rafId) { rafId = requestAnimationFrame(animate); }
});
section.addEventListener('mouseenter', function() { glow.style.opacity = '1'; });
section.addEventListener('mouseleave', function() {
glow.style.opacity = '0';
if (rafId) { cancelAnimationFrame(rafId); rafId = null; }
});
})();
</script>
</body>
</html>