<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}Pipey{% endblock %}</title>
<meta name="description" content="Pipey delivers events published over HTTP to connected WebSocket clients in real time.">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@500;600;700&family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css">
<style>
:root{
--bg: #0b0c0e;
--surface: #15171b;
--surface-2: #1c1e23;
--border: #262931;
--border-2: #34373f;
--ink: #f1efe6;
--muted: #9c9a90;
--muted-2: #6b6a62;
--accent: #ffab2e;
--accent-dark: #e6911a;
--accent-soft: #ffab2e22;
--accent-ink: #1a1206;
--live: #57e6a3;
--live-soft: #57e6a31c;
--warn: #ff8a4c;
--warn-soft: #ff8a4c1c;
--error: #ff5f5f;
--error-soft:#ff5f5f1c;
--font-display: "Space Grotesk", system-ui, sans-serif;
--font-body: "Inter", system-ui, -apple-system, sans-serif;
--font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Consolas, monospace;
--radius: 14px;
--radius-sm: 9px;
--shadow-sm: 0 1px 2px rgba(0,0,0,.3), 0 1px 1px rgba(0,0,0,.2);
--shadow-md: 0 4px 10px rgba(0,0,0,.35), 0 12px 28px -10px rgba(0,0,0,.5);
--shadow-lg: 0 6px 16px rgba(0,0,0,.4), 0 24px 48px -16px rgba(0,0,0,.6);
}
*{ margin:0; padding:0; box-sizing:border-box; }
html{ scroll-behavior:smooth; }
body{
font-family:var(--font-body);
background:
radial-gradient(680px 320px at 15% -8%, var(--accent-soft), transparent 65%),
var(--bg);
color:var(--ink);
line-height:1.65;
min-height:100vh;
}
h1,h2,h3{ font-family:var(--font-display); letter-spacing:-0.015em; }
a{ color:var(--accent); text-decoration:none; }
a:hover{ color:var(--accent-dark); }
code, pre{ font-family:var(--font-mono); }
img{ max-width:100%; display:block; }
::selection{ background:var(--accent-soft); color:var(--accent-dark); }
a:focus-visible, button:focus-visible, input:focus-visible, textarea:focus-visible{
outline:2px solid var(--accent);
outline-offset:2px;
}
.sponsor-banner{
position:relative;
display:flex; align-items:center; justify-content:center;
flex-wrap:wrap;
gap:10px 12px;
padding:9px 44px 9px 16px;
background:var(--surface-2);
border-bottom:1px solid var(--border);
color:var(--ink);
font-size:13px;
text-align:center;
}
.sponsor-banner .banner-white-logo{
height:20px;
width:auto;
padding-right: .9em;
flex-shrink:0;
opacity:.9;
}
.sponsor-banner .txt{ color:var(--muted); }
.sponsor-banner .txt strong{ color:var(--ink); }
.sponsor-banner a.sponsor-cta{
display:inline-flex; align-items:center; gap:6px;
background:var(--accent);
color:var(--accent-ink);
font-weight:700;
font-size:12.5px;
padding:5px 13px;
border-radius:7px;
white-space:nowrap;
flex-shrink:0;
transition:background .15s ease, transform .15s ease;
}
.sponsor-banner a.sponsor-cta:hover{ background:var(--accent-dark); color:var(--accent-ink); transform:translateY(-1px); }
.sponsor-banner .close-banner{
position:absolute; right:12px; top:50%; transform:translateY(-50%);
width:26px; height:26px;
display:flex; align-items:center; justify-content:center;
background:transparent;
border:none;
color:var(--muted-2);
cursor:pointer;
border-radius:50%;
font-size:13px;
transition:background .15s ease, color .15s ease;
}
.sponsor-banner .close-banner:hover{ background:var(--border); color:var(--ink); }
.sponsor-banner[hidden]{ display:none; }
@media (max-width:640px){
.sponsor-banner{ font-size:12px; padding:9px 40px 9px 12px; }
.sponsor-banner .banner-white-logo{ display:none; }
}
nav{
position:sticky; top:0; z-index:50;
height:64px;
display:flex;
align-items:center;
justify-content:space-between;
gap:12px;
padding:0 28px;
background:rgba(11,12,14,0.85);
backdrop-filter:blur(8px);
border-bottom:1px solid var(--border);
}
.logo{
display:flex;
align-items:center;
gap:9px;
flex-shrink:0;
transition:opacity .15s ease;
}
.logo:hover{ opacity:.8; }
.logo .banner-black-logo{
height:28px;
width:auto;
}
.links{ display:flex; align-items:center; gap:4px; min-width:0; }
.links a{
display:flex; align-items:center; gap:7px;
color:var(--muted);
font-size:14px;
font-weight:500;
padding:8px 13px;
border-radius:8px;
white-space:nowrap;
transition:background .15s ease, color .15s ease;
}
.links a:hover{ color:var(--ink); background:var(--surface-2); }
.links a.active{ color:var(--accent); background:var(--accent-soft); }
.links i{ width:14px; text-align:center; font-size:12.5px; }
#github-link{ display:flex; align-items:center; gap:8px; }
#stars{
display:inline-flex; align-items:center; gap:5px;
padding:2px 9px;
background:var(--surface-2);
border:1px solid var(--border);
border-radius:999px;
color:var(--ink);
font-family:var(--font-mono);
font-size:11.5px;
font-weight:600;
}
#stars i{ color:var(--accent); font-size:10.5px; width:auto; }
.container{
max-width:920px;
margin:0 auto;
padding:48px 24px 24px;
}
.card{
background:var(--surface);
border:1px solid var(--border);
border-radius:var(--radius);
box-shadow:var(--shadow-sm);
padding:28px;
margin-bottom:18px;
transition:box-shadow .2s ease, transform .2s ease, border-color .2s ease;
}
.eyebrow{
display:inline-flex; align-items:center; gap:7px;
font-family:var(--font-mono);
font-size:12px;
font-weight:500;
color:var(--accent);
letter-spacing:0.02em;
margin-bottom:14px;
}
.eyebrow::before{
content:"";
width:6px; height:6px;
border-radius:50%;
background:var(--live);
box-shadow:0 0 0 3px var(--live-soft);
animation:pulse 2.4s ease-in-out infinite;
}
@keyframes pulse{
0%, 100%{ box-shadow:0 0 0 3px var(--live-soft); }
50%{ box-shadow:0 0 0 6px var(--live-soft); }
}
pre{
background:#08090a;
border:1px solid var(--border);
border-radius:var(--radius-sm);
padding:16px 18px;
overflow-x:auto;
font-size:13px;
color:#e9e9f0;
line-height:1.7;
}
pre code{ background:none; padding:0; color:inherit; }
p code, li code{
font-family:var(--font-mono);
font-size:0.88em;
background:var(--surface-2);
border:1px solid var(--border);
padding:1px 6px;
border-radius:5px;
color:var(--accent-dark);
}
footer{
margin-top:32px;
padding:30px 24px;
text-align:center;
color:var(--muted-2);
font-size:13px;
border-top:1px solid var(--border);
}
@media (prefers-reduced-motion: reduce){
html{ scroll-behavior:auto; }
.eyebrow::before{ animation:none; }
*{ transition-duration:0.01ms !important; animation-duration:0.01ms !important; }
}
@media (max-width:640px){
nav{ padding:0 16px; gap:6px; }
.logo .banner-black-logo{ height:19px; }
.links{ gap:2px; }
.links a{ padding:8px 10px; }
.links span#stars{ display:none; }
.links a span.link-text{ display:none; }
.container{ padding:32px 16px 16px; }
.card{ padding:20px; border-radius:14px; }
}
@media (max-width:400px){
#github-link .link-text{ display:none; }
}
{% block styles %}{% endblock %}
</style>
</head>
<body>
<div id="sponsor-banner" class="sponsor-banner" hidden>
<img src="https://img.ge/i/N1uqc72.png" class="banner-white-logo" alt="Pipey">
<span class="txt">💛 Find Pipey useful? <strong>Sponsor</strong> to help cover hosting and keep it maintained.</span>
<a href="/#sponsor" class="sponsor-cta"><i class="fa-solid fa-heart"></i> Sponsor</a>
<button class="close-banner" id="close-banner" aria-label="Dismiss">
<i class="fa-solid fa-xmark"></i>
</button>
</div>
<nav>
<a href="/" class="logo">
<img src="https://img.ge/i/N1uqc72.png" class="banner-black-logo" alt="Pipey">
</a>
<div class="links">
<a href="/"><i class="fa-solid fa-house"></i><span class="link-text">Home</span></a>
<a href="/client"><i class="fa-solid fa-satellite-dish"></i><span class="link-text">Client</span></a>
<a href="/sdks"><i class="fa-solid fa-code"></i><span class="link-text">SDKs</span></a>
<a href="/docs"><i class="fa-solid fa-book"></i><span class="link-text">Docs</span></a>
<a href="/#sponsor"><i class="fa-solid fa-heart"></i><span class="link-text">Sponsor</span></a>
<a id="github-link" href="https://github.com/anomalous254/pipey" target="_blank" rel="noopener noreferrer">
<i class="fa-brands fa-github"></i>
<span class="link-text">GitHub</span>
<span id="stars">
<i class="fa-solid fa-star"></i>
<span id="star-count">1</span>
</span>
</a>
</div>
</nav>
<div class="container">
{% block content %}{% endblock %}
</div>
<footer>
Pipey. Lightweight HTTP to WebSocket event delivery.
</footer>
{% block scripts %}{% endblock %}
<script>
(async () => {
try {
const response = await fetch("https://api.github.com/repos/anomalous254/pipey");
if (!response.ok) return;
const repo = await response.json();
document.getElementById("star-count").textContent = repo.stargazers_count;
} catch (err) {
console.error(err);
}
})();
(() => {
const banner = document.getElementById("sponsor-banner");
const closeBtn = document.getElementById("close-banner");
try {
if (!localStorage.getItem("pipey_banner_dismissed")) {
banner.hidden = false;
}
} catch (err) {
banner.hidden = false;
}
closeBtn.addEventListener("click", () => {
banner.hidden = true;
try { localStorage.setItem("pipey_banner_dismissed", "1"); } catch (err) {}
});
})();
(() => {
const path = window.location.pathname.replace(/\/$/, "") || "/";
document.querySelectorAll(".links a").forEach((a) => {
const href = a.getAttribute("href");
if (!href || href.startsWith("http") || href.includes("#")) return;
const normalized = href.replace(/\/$/, "") || "/";
if (normalized === path) a.classList.add("active");
});
})();
</script>
</body>
</html>