pingql/apps/web/src/views/landing.ejs

731 lines
44 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en" class="dark scroll-smooth">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PingQL - Uptime monitoring that thinks like a developer</title>
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<meta name="description" content="Monitor uptime with a MongoDB-style query language. Inspect JSON, HTML, headers, certs, and more.">
<link rel="stylesheet" href="/assets/tailwind.css?v=<%= it.cssHash %>">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
html { scroll-behavior: smooth; }
body { background: #0a0a0a; }
/* Grid background */
.grid-bg {
background-image:
linear-gradient(rgba(59, 130, 246, 0.03) 1px, transparent 1px),
linear-gradient(90deg, rgba(59, 130, 246, 0.03) 1px, transparent 1px);
background-size: 64px 64px;
}
/* Hero glow */
.hero-glow {
background: radial-gradient(ellipse 60% 40% at 50% 0%, rgba(59, 130, 246, 0.12) 0%, transparent 70%);
}
/* Terminal window */
.terminal {
background: #131316;
border: 1px solid #232329;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 0 80px rgba(59, 130, 246, 0.08), 0 25px 60px rgba(0,0,0,0.6);
}
.terminal-bar {
background: #191920;
border-bottom: 1px solid #232329;
padding: 12px 16px;
display: flex;
align-items: center;
gap: 8px;
}
.terminal-dot {
width: 12px; height: 12px; border-radius: 50%;
}
.terminal-body {
padding: 20px 24px;
font-family: 'JetBrains Mono', monospace;
font-size: 13px;
line-height: 1.7;
overflow-x: auto;
}
/* Syntax highlighting */
.syn-key { color: #93c5fd; }
.syn-str { color: #86efac; }
.syn-num { color: #fbbf24; }
.syn-op { color: #c084fc; }
.syn-brace { color: #6b7280; }
.syn-comment { color: #4b5563; font-style: italic; }
/* Fade-in animation */
@keyframes fade-up {
from { opacity: 0; transform: translateY(24px); }
to { opacity: 1; transform: translateY(0); }
}
.fade-up {
animation: fade-up 0.7s ease-out both;
}
.fade-up-delay-1 { animation-delay: 0.1s; }
.fade-up-delay-2 { animation-delay: 0.2s; }
.fade-up-delay-3 { animation-delay: 0.3s; }
.fade-up-delay-4 { animation-delay: 0.4s; }
/* Glow card */
.glow-card {
background: #141418;
border: 1px solid #232329;
transition: border-color 0.3s, box-shadow 0.3s, transform 0.3s;
}
.glow-card:hover {
border-color: #3b82f650;
box-shadow: 0 0 30px rgba(59, 130, 246, 0.1), 0 8px 24px rgba(0, 0, 0, 0.4);
transform: translateY(-2px);
}
/* Comparison bar */
.ping-bar {
height: 6px;
border-radius: 3px;
}
/* Pulse animation */
@keyframes pulse-dot {
0%, 100% { opacity: 1; }
50% { opacity: 0.4; }
}
.pulse-dot {
animation: pulse-dot 2s ease-in-out infinite;
}
/* Typing cursor */
@keyframes blink {
0%, 50% { opacity: 1; }
51%, 100% { opacity: 0; }
}
.cursor {
display: inline-block;
width: 8px;
height: 18px;
background: #3b82f6;
animation: blink 1s step-end infinite;
vertical-align: text-bottom;
margin-left: 2px;
}
/* Pricing card tiers */
.pricing-free {
background: #141418;
border: 1px solid #232329;
}
.pricing-pro {
background: #151720;
border: 1px solid #3b82f650;
box-shadow: 0 0 40px rgba(59, 130, 246, 0.1), 0 0 80px rgba(59, 130, 246, 0.05);
}
.pricing-lifetime {
background: #18170f;
border: 1px solid #eab30840;
box-shadow: 0 0 30px rgba(234, 179, 8, 0.06);
}
/* Status page showcase bar tooltips */
.demo-bar { position: relative; }
.demo-bar .demo-tip {
display: none;
position: absolute;
bottom: calc(100% + 8px);
left: 50%;
transform: translateX(-50%);
background: #1a1a1f;
border: 1px solid #2a2a30;
border-radius: 6px;
padding: 8px 10px;
font-size: 11px;
line-height: 1.5;
color: #94a3b8;
white-space: nowrap;
z-index: 10;
box-shadow: 0 8px 24px rgba(0,0,0,0.4);
pointer-events: none;
}
.demo-bar:hover .demo-tip { display: block; }
.demo-tip .tip-head { color: #64748b; font-size: 10px; margin-bottom: 4px; }
.demo-tip .tip-row { display: flex; justify-content: space-between; gap: 12px; }
.demo-tip .tip-row span:last-child { color: #e2e8f0; font-weight: 600; font-variant-numeric: tabular-nums; }
.demo-tip .tip-good { color: #10b981; }
.demo-tip .tip-warn { color: #f59e0b; }
.demo-tip .tip-bad { color: #ef4444; }
</style>
</head>
<body class="bg-[#0a0a0a] text-gray-100 font-sans antialiased grid-bg">
<!-- ─── DEV WARNING ─── -->
<div class="fixed top-0 left-0 right-0 z-[60] bg-yellow-500/10 border-b border-yellow-500/20 text-center py-1.5 px-4">
<p class="text-xs text-yellow-400">PingQL is in active development. Please don't rely on the service until this notice is removed.</p>
</div>
<!-- ─── HEADER ─── -->
<header class="fixed top-[34px] left-0 right-0 z-50 border-b border-border-subtle bg-[#0a0a0a]/70 backdrop-blur-md">
<div class="max-w-6xl mx-auto px-6 py-4 flex items-center justify-between">
<a href="/" class="font-mono text-lg font-bold tracking-tight group">Ping<span class="text-blue-400 transition-all group-hover:drop-shadow-[0_0_8px_rgba(59,130,246,0.4)]">QL</span></a>
<nav class="hidden md:flex items-center gap-7 text-sm text-gray-400">
<a href="/docs" class="hover:text-gray-200 transition-colors">Docs</a>
<a href="/privacy" class="hover:text-gray-200 transition-colors">Privacy</a>
<a href="#pricing" class="hover:text-gray-200 transition-colors">Pricing</a>
</nav>
<div class="flex items-center gap-3">
<a href="/dashboard" class="text-sm text-gray-400 hover:text-gray-200 transition-colors">Sign in</a>
<a href="/dashboard" class="text-sm text-white px-4 py-2 rounded-lg font-medium transition-all" style="background:#2563eb;box-shadow:0 1px 3px rgba(0,0,0,0.3),0 0 12px rgba(59,130,246,0.15)">Get started</a>
</div>
</div>
</header>
<!-- ─── HERO ─── -->
<section class="relative min-h-screen flex items-center hero-glow pt-16">
<div class="max-w-6xl mx-auto px-6 py-12 w-full">
<div class="grid lg:grid-cols-2 gap-16 items-center">
<!-- Left -->
<div class="fade-up">
<div class="inline-flex items-center gap-2 px-3 py-1 rounded-full border border-border-subtle text-xs text-gray-400 mb-6 font-mono">
<span class="w-2 h-2 rounded-full bg-green-500 pulse-dot" style="box-shadow:0 0 8px rgba(34,197,94,0.4)"></span>
All systems operational
</div>
<h1 class="text-4xl sm:text-5xl lg:text-6xl font-bold tracking-tight leading-[1.1] mb-6">
Uptime monitoring<br>that <span class="text-brand">thinks like<br>a developer</span>
</h1>
<p class="text-lg text-gray-400 max-w-lg mb-8 leading-relaxed">
Go beyond simple pings. Write queries against status codes, JSON bodies, HTML selectors, headers, and cert expiry.
</p>
<div class="flex flex-wrap gap-4">
<a href="/dashboard" class="inline-flex items-center gap-2 px-6 py-3 text-white font-medium rounded-lg transition-all text-sm" style="background:#2563eb;box-shadow:0 1px 3px rgba(0,0,0,0.3),0 0 12px rgba(59,130,246,0.15)">
Get Started Free
<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 7l5 5m0 0l-5 5m5-5H6"/></svg>
</a>
<a href="/docs" class="inline-flex items-center gap-2 px-6 py-3 border border-border-subtle hover:border-border-strong text-gray-300 font-medium rounded-lg transition-colors text-sm">
Read the Docs
</a>
</div>
</div>
<!-- Right: terminal -->
<div class="fade-up fade-up-delay-2">
<div class="terminal">
<div class="terminal-bar">
<div class="terminal-dot bg-[#ff5f57]"></div>
<div class="terminal-dot bg-[#ffbd2e]"></div>
<div class="terminal-dot bg-[#28c840]"></div>
<span class="ml-3 text-xs text-gray-500 font-mono">query.json</span>
</div>
<div class="terminal-body">
<pre><span class="syn-brace">{</span>
<span class="syn-key">"$and"</span><span class="syn-brace">:</span> <span class="syn-brace">[</span>
<span class="syn-brace">{</span> <span class="syn-key">"status"</span><span class="syn-brace">:</span> <span class="syn-brace">{</span> <span class="syn-op">"$lt"</span><span class="syn-brace">:</span> <span class="syn-num">400</span> <span class="syn-brace">}</span> <span class="syn-brace">}</span>,
<span class="syn-brace">{</span> <span class="syn-op">"$json"</span><span class="syn-brace">:</span> <span class="syn-brace">{</span> <span class="syn-str">"$.db.status"</span><span class="syn-brace">:</span> <span class="syn-brace">{</span> <span class="syn-op">"$eq"</span><span class="syn-brace">:</span> <span class="syn-str">"ok"</span> <span class="syn-brace">}</span> <span class="syn-brace">}</span> <span class="syn-brace">}</span>,
<span class="syn-brace">{</span> <span class="syn-op">"$certExpiry"</span><span class="syn-brace">:</span> <span class="syn-brace">{</span> <span class="syn-op">"$gt"</span><span class="syn-brace">:</span> <span class="syn-num">14</span> <span class="syn-brace">}</span> <span class="syn-brace">}</span>
<span class="syn-brace">]</span>
<span class="syn-brace">}</span></pre>
<div class="mt-4 pt-4 border-t border-border-subtle text-xs text-gray-500">
<span class="syn-comment">// status &lt; 400 AND $.db.status = "ok" AND $certExpiry &gt; 14 days</span>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- ─── NOT JUST PING ─── -->
<section class="py-24 px-6">
<div class="max-w-5xl mx-auto">
<div class="text-center mb-16">
<h2 class="text-3xl sm:text-4xl font-bold tracking-tight mb-4">Not just ping</h2>
<p class="text-gray-400 max-w-2xl mx-auto text-lg">
Most monitoring tools ping a URL and check if it returns 200. That tells you almost nothing.
PingQL lets you query the <em>entire</em> response.
</p>
</div>
<!-- Comparison -->
<div class="grid md:grid-cols-2 gap-8 max-w-3xl mx-auto">
<!-- Others -->
<div class="rounded-xl border border-border-subtle bg-surface-solid p-6">
<div class="text-sm text-gray-500 uppercase tracking-wider mb-4 font-mono">Others</div>
<div class="space-y-4">
<div class="flex items-center gap-3">
<span class="w-3 h-3 rounded-full bg-green-500 shrink-0"></span>
<span class="text-gray-400 text-sm">GET /api/health → 200</span>
<span class="ml-auto text-green-500 text-xs font-mono">UP</span>
</div>
<div class="flex items-center gap-3">
<span class="w-3 h-3 rounded-full bg-red-500 shrink-0"></span>
<span class="text-gray-400 text-sm">GET /api/health → 500</span>
<span class="ml-auto text-red-500 text-xs font-mono">DOWN</span>
</div>
<div class="mt-4 pt-4 border-t border-border-subtle text-xs text-gray-500">
That's it. That's all you get.
</div>
</div>
</div>
<!-- PingQL -->
<div class="rounded-xl border border-blue-500/30 bg-surface-solid p-6 shadow-glow-sm">
<div class="text-sm text-brand uppercase tracking-wider mb-4 font-mono">PingQL</div>
<div class="space-y-3 text-sm font-mono">
<div class="flex items-center gap-2">
<span class="text-green-400">✓</span>
<span class="text-gray-300">Status code assertions</span>
</div>
<div class="flex items-center gap-2">
<span class="text-green-400">✓</span>
<span class="text-gray-300">JSON body inspection</span>
</div>
<div class="flex items-center gap-2">
<span class="text-green-400">✓</span>
<span class="text-gray-300">HTML / CSS selector matching</span>
</div>
<div class="flex items-center gap-2">
<span class="text-green-400">✓</span>
<span class="text-gray-300">Response time thresholds</span>
</div>
<div class="flex items-center gap-2">
<span class="text-green-400">✓</span>
<span class="text-gray-300">SSL cert expiry checks</span>
</div>
<div class="flex items-center gap-2">
<span class="text-green-400">✓</span>
<span class="text-gray-300">Header & regex matching</span>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- ─── FEATURES ─── -->
<section class="py-24 px-6">
<div class="max-w-6xl mx-auto">
<div class="text-center mb-16">
<h2 class="text-3xl sm:text-4xl font-bold tracking-tight mb-4">Everything you need</h2>
<p class="text-gray-400 text-lg">Powerful primitives, zero bloat.</p>
</div>
<div class="grid sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
<div class="glow-card rounded-xl p-6">
<div class="w-10 h-10 rounded-lg bg-blue-500/10 border border-blue-500/20 flex items-center justify-center mb-4">
<svg class="w-5 h-5 text-brand" 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"/></svg>
</div>
<h3 class="font-semibold text-white mb-2">Query language</h3>
<p class="text-sm text-gray-400 leading-relaxed">Set your own definition of "up". Query status codes, JSON fields, headers, HTML, and latency with MongoDB-like operators.</p>
</div>
<div class="glow-card rounded-xl p-6">
<div class="w-10 h-10 rounded-lg bg-blue-500/10 border border-blue-500/20 flex items-center justify-center mb-4">
<svg class="w-5 h-5 text-brand" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M3.75 3v11.25A2.25 2.25 0 006 16.5h2.25M3.75 3h-1.5m1.5 0h16.5m0 0h1.5m-1.5 0v11.25A2.25 2.25 0 0118 16.5h-2.25m-7.5 0h7.5m-7.5 0l-1 3m8.5-3l1 3m0 0l.5 1.5m-.5-1.5h-9.5m0 0l-.5 1.5"/></svg>
</div>
<h3 class="font-semibold text-white mb-2">Public status pages</h3>
<p class="text-sm text-gray-400 leading-relaxed">Live uptime, heartbeat history, incidents, and RSS. Set one up in a minute and give your users somewhere to check.</p>
</div>
<div class="glow-card rounded-xl p-6">
<div class="w-10 h-10 rounded-lg bg-blue-500/10 border border-blue-500/20 flex items-center justify-center mb-4">
<svg class="w-5 h-5 text-brand" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><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="font-semibold text-white mb-2">Webhook notifications</h3>
<p class="text-sm text-gray-400 leading-relaxed">Fires on down, recovery, and cert expiry. HMAC-signed payloads for secure integrations. More providers coming soon.</p>
</div>
<div class="glow-card rounded-xl p-6">
<div class="w-10 h-10 rounded-lg bg-blue-500/10 border border-blue-500/20 flex items-center justify-center mb-4">
<svg class="w-5 h-5 text-brand" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m0-10.036A11.959 11.959 0 013.598 6 11.99 11.99 0 003 9.75c0 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.285zM12 15.75h.007v.008H12v-.008z"/></svg>
</div>
<h3 class="font-semibold text-white mb-2">Incident management</h3>
<p class="text-sm text-gray-400 leading-relaxed">Declare incidents, post updates, track resolution. Visitors see the full timeline on your status page automatically.</p>
</div>
<div class="glow-card rounded-xl p-6">
<div class="w-10 h-10 rounded-lg bg-blue-500/10 border border-blue-500/20 flex items-center justify-center mb-4">
<svg class="w-5 h-5 text-brand" fill="none" stroke="currentColor" stroke-width="1.5" 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.182"/></svg>
</div>
<h3 class="font-semibold text-white mb-2">Retries & smart alerting</h3>
<p class="text-sm text-gray-400 leading-relaxed">Retry before declaring down. Resend alerts for persistent outages. No more false alarms from a single failed request.</p>
</div>
<div class="glow-card rounded-xl p-6">
<div class="w-10 h-10 rounded-lg bg-blue-500/10 border border-blue-500/20 flex items-center justify-center mb-4">
<svg class="w-5 h-5 text-brand" 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"/></svg>
</div>
<h3 class="font-semibold text-white mb-2">SSL cert monitoring</h3>
<p class="text-sm text-gray-400 leading-relaxed">Get alerted days before your cert expires, not after. Per-region checks so regional resolvers are covered too.</p>
</div>
<div class="glow-card rounded-xl p-6">
<div class="w-10 h-10 rounded-lg bg-blue-500/10 border border-blue-500/20 flex items-center justify-center mb-4">
<svg class="w-5 h-5 text-brand" 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"/></svg>
</div>
<h3 class="font-semibold text-white mb-2">Multi-region monitoring</h3>
<p class="text-sm text-gray-400 leading-relaxed">Independent health per region. US West going down doesn't mask EU Central being up. Each region tracks state separately.</p>
</div>
<div class="glow-card rounded-xl p-6">
<div class="w-10 h-10 rounded-lg bg-blue-500/10 border border-blue-500/20 flex items-center justify-center mb-4">
<svg class="w-5 h-5 text-brand" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z"/></svg>
</div>
<h3 class="font-semibold text-white mb-2">JSONPath & CSS selectors</h3>
<p class="text-sm text-gray-400 leading-relaxed">Drill into JSON responses with <code class="text-brand font-mono text-xs">$json</code> or scrape any HTML page with <code class="text-brand font-mono text-xs">$html</code>. No API required.</p>
</div>
<div class="glow-card rounded-xl p-6">
<div class="w-10 h-10 rounded-lg bg-blue-500/10 border border-blue-500/20 flex items-center justify-center mb-4">
<svg class="w-5 h-5 text-brand" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M6 12L3.269 3.126A59.768 59.768 0 0121.485 12 59.77 59.77 0 013.27 20.876L5.999 12zm0 0h7.5"/></svg>
</div>
<h3 class="font-semibold text-white mb-2">Custom HTTP requests</h3>
<p class="text-sm text-gray-400 leading-relaxed">Send GET, POST, PUT, PATCH or HEAD with custom headers and request bodies. Monitor authenticated APIs end-to-end.</p>
</div>
<div class="glow-card rounded-xl p-6">
<div class="w-10 h-10 rounded-lg bg-blue-500/10 border border-blue-500/20 flex items-center justify-center mb-4">
<svg class="w-5 h-5 text-brand" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 5.25a3 3 0 013 3m3 0a6 6 0 01-7.029 5.912c-.563-.097-1.159.026-1.563.43L10.5 17.25H8.25v2.25H6v2.25H2.25v-2.818c0-.597.237-1.17.659-1.591l6.499-6.499c.404-.404.527-1 .43-1.563A6 6 0 1121.75 8.25z"/></svg>
</div>
<h3 class="font-semibold text-white mb-2">Sub-keys & API access</h3>
<p class="text-sm text-gray-400 leading-relaxed">Create scoped sub-keys for CI pipelines, scripts, or teammates. Full REST API, no dashboard required.</p>
</div>
<div class="glow-card rounded-xl p-6">
<div class="w-10 h-10 rounded-lg bg-blue-500/10 border border-blue-500/20 flex items-center justify-center mb-4">
<svg class="w-5 h-5 text-brand" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M16.5 10.5V6.75a4.5 4.5 0 10-9 0v3.75m-.75 11.25h10.5a2.25 2.25 0 002.25-2.25v-6.75a2.25 2.25 0 00-2.25-2.25H6.75a2.25 2.25 0 00-2.25 2.25v6.75a2.25 2.25 0 002.25 2.25z"/></svg>
</div>
<h3 class="font-semibold text-white mb-2">Privacy-first accounts</h3>
<p class="text-sm text-gray-400 leading-relaxed">No email required. No passwords. Just an account key. Emails are hashed if provided, so we literally can't read them.</p>
</div>
<div class="glow-card rounded-xl p-6">
<div class="w-10 h-10 rounded-lg bg-blue-500/10 border border-blue-500/20 flex items-center justify-center mb-4">
<svg class="w-5 h-5 text-brand" fill="none" stroke="currentColor" stroke-width="1.5" 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"/></svg>
</div>
<h3 class="font-semibold text-white mb-2">Pay with crypto</h3>
<p class="text-sm text-gray-400 leading-relaxed">We accept <span class="text-gray-300">Bitcoin, Litecoin, Dogecoin, Bitcoin Cash, Dash,</span> and <span class="text-gray-300">eCash</span>. No card, no name, no billing address.</p>
</div>
</div>
</div>
</section>
<!-- ─── STATUS PAGE SHOWCASE ─── -->
<section class="py-24 px-6">
<div class="max-w-4xl mx-auto">
<div class="text-center mb-12">
<h2 class="text-3xl sm:text-4xl font-bold tracking-tight mb-4">Beautiful status pages, out of the box</h2>
<p class="text-gray-400 text-lg max-w-2xl mx-auto">Give your users a branded status page with live uptime, heartbeat history, and incident timelines. Password protection, custom CSS, RSS feeds, and embeddable badges included.</p>
<p class="mt-4"><a href="https://pages.pingql.com/ping" target="_blank" rel="noopener" class="text-blue-400 hover:text-blue-300 text-sm font-medium">See a live demo &rarr;</a></p>
</div>
<div class="rounded-2xl border border-border-subtle overflow-hidden" style="background:#111114; box-shadow:0 0 60px rgba(59,130,246,0.06), 0 20px 50px rgba(0,0,0,0.5)">
<div style="background:#191920; border-bottom:1px solid #232329; padding:12px 16px; display:flex; align-items:center; gap:8px;">
<div style="width:12px;height:12px;border-radius:50%;background:#ff5f57"></div>
<div style="width:12px;height:12px;border-radius:50%;background:#ffbd2e"></div>
<div style="width:12px;height:12px;border-radius:50%;background:#28c840"></div>
<span class="ml-3 text-xs text-gray-500 font-mono">pages.pingql.com/your-app</span>
</div>
<div class="p-6 sm:p-8">
<div class="text-lg font-semibold text-white mb-4">Acme Corp Status</div>
<div class="rounded-lg px-4 py-3 flex items-center gap-3 mb-6" style="background:rgba(16,185,129,0.1); border:1px solid rgba(16,185,129,0.2)">
<span class="w-3 h-3 rounded-full bg-green-500 pulse-dot" style="box-shadow:0 0 6px rgba(34,197,94,0.4)"></span>
<span class="text-sm font-medium text-green-400">All systems operational</span>
</div>
<div class="space-y-3">
<div class="rounded-lg border border-border-subtle p-4" style="background:#141418">
<div class="flex items-center justify-between mb-3">
<div class="flex items-center gap-2">
<span class="w-2.5 h-2.5 rounded-full bg-green-500"></span>
<span class="text-sm font-medium text-gray-200">Production API</span>
</div>
<div class="flex items-center gap-3 text-xs text-gray-500">
<span>47ms</span>
<span class="font-semibold text-green-400">99.99%</span>
</div>
</div>
<div class="flex gap-[0.1rem] h-5">
<div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-yellow-500/70 demo-bar"><div class="demo-tip"><div class="tip-head">Mar 28, 14:00 - 15:00</div><div class="tip-row"><span>Checks</span><span>120</span></div><div class="tip-row"><span>Successful</span><span>118</span></div><div class="tip-row"><span>Uptime</span><span class="tip-warn">98.33%</span></div><div class="tip-row"><span>Avg ping</span><span>52ms</span></div></div></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div>
</div>
</div>
<div class="rounded-lg border border-border-subtle p-4" style="background:#141418">
<div class="flex items-center justify-between mb-3">
<div class="flex items-center gap-2">
<span class="w-2.5 h-2.5 rounded-full bg-green-500"></span>
<span class="text-sm font-medium text-gray-200">Dashboard</span>
</div>
<div class="flex items-center gap-3 text-xs text-gray-500">
<span>123ms</span>
<span class="font-semibold text-green-400">100%</span>
</div>
</div>
<div class="flex gap-[0.1rem] h-5">
<div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div>
</div>
</div>
<div class="rounded-lg border border-border-subtle p-4" style="background:#141418">
<div class="flex items-center justify-between mb-3">
<div class="flex items-center gap-2">
<span class="w-2.5 h-2.5 rounded-full bg-green-500"></span>
<span class="text-sm font-medium text-gray-200">Payment Gateway</span>
</div>
<div class="flex items-center gap-3 text-xs text-gray-500">
<span>89ms</span>
<span class="font-semibold text-green-400">99.97%</span>
</div>
</div>
<div class="flex gap-[0.1rem] h-5">
<div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-red-500/70 demo-bar"><div class="demo-tip"><div class="tip-head">Mar 22, 03:00 - 04:00</div><div class="tip-row"><span>Checks</span><span>120</span></div><div class="tip-row"><span>Successful</span><span>0</span></div><div class="tip-row"><span>Uptime</span><span class="tip-bad">0.00%</span></div><div class="tip-row"><span>Avg ping</span><span>-</span></div></div></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div><div class="flex-1 rounded-sm bg-green-500/70"></div>
</div>
</div>
</div>
<div class="mt-4 text-center text-xs text-gray-600">Powered by PingQL</div>
</div>
</div>
</div>
</section>
<!-- ─── PRIVACY ─── -->
<section id="privacy" class="py-24 px-6">
<div class="max-w-4xl mx-auto">
<div class="rounded-2xl border border-border-subtle bg-gradient-to-b from-surface-solid to-[#0a0a0a] p-8 sm:p-12" style="box-shadow:0 1px 3px rgba(0,0,0,0.3)">
<div class="flex items-start gap-4 mb-8">
<div class="w-12 h-12 rounded-xl bg-green-500/10 border border-green-500/20 flex items-center justify-center shrink-0">
<svg class="w-6 h-6 text-green-400" 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"/></svg>
</div>
<div>
<h2 class="text-3xl font-bold tracking-tight mb-2">Privacy by design</h2>
<p class="text-gray-400">We built PingQL for developers who care about their data.</p>
</div>
</div>
<div class="grid sm:grid-cols-2 gap-6">
<div class="flex items-start gap-3">
<span class="text-green-400 mt-0.5 shrink-0 font-mono text-sm">$</span>
<div>
<p class="text-white font-medium text-sm">No tracking, no analytics, no ads</p>
<p class="text-gray-500 text-xs mt-1">Zero third-party scripts. Zero cookies.</p>
</div>
</div>
<div class="flex items-start gap-3">
<span class="text-green-400 mt-0.5 shrink-0 font-mono text-sm">$</span>
<div>
<p class="text-white font-medium text-sm">Account keys, not passwords</p>
<p class="text-gray-500 text-xs mt-1">Be completely anonymous. No email required.</p>
</div>
</div>
<div class="flex items-start gap-3">
<span class="text-green-400 mt-0.5 shrink-0 font-mono text-sm">$</span>
<div>
<p class="text-white font-medium text-sm">Emails hashed if provided</p>
<p class="text-gray-500 text-xs mt-1">Optional email for recovery only. We hash it.</p>
</div>
</div>
<div class="flex items-start gap-3">
<span class="text-green-400 mt-0.5 shrink-0 font-mono text-sm">$</span>
<div>
<p class="text-white font-medium text-sm">We never sell data</p>
<p class="text-gray-500 text-xs mt-1">Your monitors, your data. Period.</p>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- ─── API EXAMPLE ─── -->
<section class="py-24 px-6">
<div class="max-w-5xl mx-auto">
<div class="text-center mb-16">
<h2 class="text-3xl sm:text-4xl font-bold tracking-tight mb-4">API-first, always</h2>
<p class="text-gray-400 text-lg max-w-2xl mx-auto">Create monitors, query results, and manage everything from scripts, your terminal, or anywhere with HTTP.</p>
</div>
<div class="grid lg:grid-cols-2 gap-6">
<!-- Create status page -->
<div class="terminal">
<div class="terminal-bar">
<div class="terminal-dot bg-[#ff5f57]"></div>
<div class="terminal-dot bg-[#ffbd2e]"></div>
<div class="terminal-dot bg-[#28c840]"></div>
<span class="ml-3 text-xs text-gray-500 font-mono">Create a status page</span>
</div>
<div class="terminal-body text-xs sm:text-[13px]">
<pre><span class="text-gray-500">$</span> <span class="text-white">curl</span> -X POST https://pingql.com/api/pages \
-H <span class="syn-str">"X-Key: abcd-1234-efgh-5678"</span> \
-d <span class="syn-str">'{
"slug": "my-app",
"title": "My App Status",
"monitors": [
{ "monitor_id": "a1b2c3d4e5f67890" }
]
}'</span>
<span class="syn-brace">{</span>
<span class="syn-key">"id"</span>: <span class="syn-str">"f8c1a2b3-..."</span>,
<span class="syn-key">"slug"</span>: <span class="syn-str">"my-app"</span>,
<span class="syn-key">"title"</span>: <span class="syn-str">"My App Status"</span>,
<span class="syn-key">"theme"</span>: <span class="syn-str">"auto"</span>
<span class="syn-brace">}</span></pre>
</div>
</div>
<!-- Create monitor -->
<div class="terminal">
<div class="terminal-bar">
<div class="terminal-dot bg-[#ff5f57]"></div>
<div class="terminal-dot bg-[#ffbd2e]"></div>
<div class="terminal-dot bg-[#28c840]"></div>
<span class="ml-3 text-xs text-gray-500 font-mono">Create a monitor</span>
</div>
<div class="terminal-body text-xs sm:text-[13px]">
<pre><span class="text-gray-500">$</span> <span class="text-white">curl</span> -X POST https://pingql.com/api/monitors \
-H <span class="syn-str">"X-Key: abcd-1234-efgh-5678"</span> \
-d <span class="syn-str">'{
"name": "Production API",
"url": "https://api.example.com/health",
"interval_s": 60,
"query": {
"status": { "$lt": 400 },
"$json": { "$.ok": { "$eq": true } }
}
}'</span>
<span class="syn-brace">{</span>
<span class="syn-key">"id"</span>: <span class="syn-str">"a1b2c3d4e5f67890"</span>,
<span class="syn-key">"name"</span>: <span class="syn-str">"Production API"</span>,
<span class="syn-key">"url"</span>: <span class="syn-str">"https://api.example.com/health"</span>,
<span class="syn-key">"enabled"</span>: <span class="syn-num">true</span>
<span class="syn-brace">}</span></pre>
</div>
</div>
</div>
</div>
</section>
<!-- ─── PRICING ─── -->
<section id="pricing" class="py-24 px-6">
<div class="max-w-4xl mx-auto text-center">
<h2 class="text-3xl sm:text-4xl font-bold tracking-tight mb-4">Simple pricing</h2>
<p class="text-gray-400 text-lg mb-12">Start for free. No credit card required.</p>
<div class="grid sm:grid-cols-3 gap-6">
<!-- Free -->
<div class="pricing-free rounded-xl p-8 text-left">
<div class="text-xs text-gray-500 uppercase tracking-wider font-mono mb-2">Free</div>
<div class="text-4xl font-bold mb-1">$0</div>
<div class="text-sm text-gray-500 mb-6">forever</div>
<ul class="space-y-3 text-sm text-gray-400">
<li class="flex items-center gap-2">
<svg class="w-4 h-4 text-green-400 shrink-0" 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>
10 monitors
</li>
<li class="flex items-center gap-2">
<svg class="w-4 h-4 text-green-400 shrink-0" 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>
30s check interval
</li>
<li class="flex items-center gap-2">
<svg class="w-4 h-4 text-green-400 shrink-0" 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>
Single region per monitor
</li>
<li class="flex items-center gap-2">
<svg class="w-4 h-4 text-green-400 shrink-0" 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>
Status pages & incidents
</li>
<li class="flex items-center gap-2">
<svg class="w-4 h-4 text-green-400 shrink-0" 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>
Webhook & Email alerts
</li>
</ul>
</div>
<!-- Pro -->
<div class="pricing-pro rounded-xl p-8 text-left">
<div class="text-xs text-blue-400 uppercase tracking-wider font-mono mb-2">Pro</div>
<div class="text-4xl font-bold mb-1">$12<span class="text-lg font-normal text-gray-500">-$48</span></div>
<div class="text-sm text-gray-500 mb-6">per month</div>
<ul class="space-y-3 text-sm text-gray-400">
<li class="flex items-center gap-2">
<svg class="w-4 h-4 text-blue-400 shrink-0" 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>
200800 monitors
</li>
<li class="flex items-center gap-2">
<svg class="w-4 h-4 text-blue-400 shrink-0" 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>
5s check interval
</li>
<li class="flex items-center gap-2">
<svg class="w-4 h-4 text-blue-400 shrink-0" 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>
Multi-region monitoring
</li>
<li class="flex items-center gap-2">
<svg class="w-4 h-4 text-blue-400 shrink-0" 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>
Signal & Telegram alerts
</li>
</ul>
</div>
<!-- Lifetime -->
<div class="pricing-lifetime rounded-xl p-8 text-left relative">
<span class="absolute top-3 right-3 text-[10px] font-semibold px-2 py-0.5 rounded-full bg-yellow-500/15 text-yellow-500 border border-yellow-500/20">Launch Deal</span>
<div class="text-xs text-yellow-500 uppercase tracking-wider font-mono mb-2">Lifetime</div>
<div class="text-4xl font-bold mb-1">$140</div>
<div class="text-sm text-gray-500 mb-6">one-time</div>
<ul class="space-y-3 text-sm text-gray-400">
<li class="flex items-center gap-2">
<svg class="w-4 h-4 text-yellow-500 shrink-0" 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>
Everything in Pro
</li>
<li class="flex items-center gap-2">
<svg class="w-4 h-4 text-yellow-500 shrink-0" 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>
Pay once, use forever
</li>
<li class="flex items-center gap-2">
<svg class="w-4 h-4 text-yellow-500 shrink-0" 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>
All future updates
</li>
</ul>
</div>
</div>
<p class="text-sm text-gray-500 mt-8 max-w-lg mx-auto">Start with Pro and upgrade to Lifetime whenever you're ready. What you've spent on Pro gets credited toward the lifetime price, up to 75% off.</p>
<div class="mt-6">
<a href="/dashboard" class="inline-flex items-center gap-2 px-8 py-3.5 text-white font-medium rounded-lg transition-all text-sm" style="background:#2563eb;box-shadow:0 1px 3px rgba(0,0,0,0.3),0 0 12px rgba(59,130,246,0.15)">
Get Started
<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 7l5 5m0 0l-5 5m5-5H6"/></svg>
</a>
</div>
</div>
</section>
<!-- ─── FOOTER ─── -->
<footer class="border-t border-border-subtle py-16 px-6">
<div class="max-w-5xl mx-auto flex flex-col sm:flex-row items-center justify-between gap-6">
<div class="flex items-center gap-8">
<a href="/" class="text-lg font-bold tracking-tight font-mono">Ping<span class="text-brand">QL</span></a>
<nav class="flex items-center gap-6 text-sm text-gray-500">
<a href="/docs" class="hover:text-gray-300 transition-colors">Docs</a>
<a href="/privacy" class="hover:text-gray-300 transition-colors">Privacy</a>
<a href="/terms" class="hover:text-gray-300 transition-colors">Terms</a>
</nav>
</div>
<div class="text-xs text-gray-600">
&copy; <%= new Date().getFullYear() %> PingQL
</div>
</div>
</footer>
</body>
</html>