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

594 lines
33 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);
}
</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 gap-6">
<!-- Feature 1 -->
<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">MongoDB-style queries</h3>
<p class="text-sm text-gray-400 leading-relaxed">Use <code class="text-brand font-mono text-xs">$and</code>, <code class="text-brand font-mono text-xs">$or</code>, <code class="text-brand font-mono text-xs">$lt</code>, <code class="text-brand font-mono text-xs">$regex</code>. A query language you already know.</p>
</div>
<!-- Feature 2 -->
<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">$select</code>. No API required.</p>
</div>
<!-- Feature 3 -->
<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">Built-in <code class="text-brand font-mono text-xs">$certExpiry</code> operator. Get alerted before your cert expires, not after.</p>
</div>
<!-- Feature 4 -->
<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">Dedicated servers in Europe and the US. Ping from the regions that matter to your users, not just one location.</p>
</div>
<!-- Feature 5 -->
<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>
<!-- Feature 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="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>
<!-- Feature 7 -->
<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 13.125C3 12.504 3.504 12 4.125 12h2.25c.621 0 1.125.504 1.125 1.125v6.75C7.5 20.496 6.996 21 6.375 21h-2.25A1.125 1.125 0 013 19.875v-6.75zM9.75 8.625c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125v11.25c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 01-1.125-1.125V8.625zM16.5 4.125c0-.621.504-1.125 1.125-1.125h2.25C20.496 3 21 3.504 21 4.125v15.75c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 01-1.125-1.125V4.125z"/></svg>
</div>
<h3 class="font-semibold text-white mb-2">Live dashboard</h3>
<p class="text-sm text-gray-400 leading-relaxed">Real-time updates via SSE. Latency charts, status history, and uptime stats, all live without a page refresh.</p>
</div>
<!-- Feature 8 -->
<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>
<!-- Feature 9 -->
<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 required.</p>
</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 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: XXXX-XXXX-XXXX-XXXX"</span> \
-d <span class="syn-str">'{
"url": "https://api.example.com/health",
"interval": 60,
"query": {
"status": { "$lt": 400 },
"$json": {
"$.ok": { "$eq": true }
}
}
}'</span>
<span class="text-gray-500">// → 201 Created</span>
<span class="syn-brace">{</span> <span class="syn-key">"id"</span>: <span class="syn-str">"mon_a1b2c3"</span>, <span class="syn-key">"status"</span>: <span class="syn-str">"active"</span> <span class="syn-brace">}</span></pre>
</div>
</div>
<!-- Get results -->
<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">Check results</span>
</div>
<div class="terminal-body text-xs sm:text-[13px]">
<pre><span class="text-gray-500">$</span> <span class="text-white">curl</span> https://pingql.com/api/monitors/mon_a1b2c3 \
-H <span class="syn-str">"X-Key: XXXX-XXXX-XXXX-XXXX"</span>
<span class="syn-brace">{</span>
<span class="syn-key">"id"</span>: <span class="syn-str">"mon_a1b2c3"</span>,
<span class="syn-key">"url"</span>: <span class="syn-str">"https://api.example.com/health"</span>,
<span class="syn-key">"status"</span>: <span class="syn-str">"up"</span>,
<span class="syn-key">"lastCheck"</span>: <span class="syn-str">"2024-01-15T10:30:00Z"</span>,
<span class="syn-key">"responseTime"</span>: <span class="syn-num">142</span>,
<span class="syn-key">"uptime30d"</span>: <span class="syn-num">99.97</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>
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>