Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 4 additions & 23 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# GoReleaser — cross-platform tarballs + an auto-updated Homebrew tap. No apt/deb, no rpm.
# Zero-dependency single binary; scp-and-run remains the primary path, brew is an extra.
# GoReleaser — cross-platform tarballs. No apt/deb, no rpm, no brew tap (dropped:
# not worth the token upkeep for a secondary channel — scp-and-run is the primary path).
# Zero-dependency single binary.
version: 2

project_name: pingping
Expand Down Expand Up @@ -34,31 +35,11 @@ checksum:
name_template: "SHA256SUMS"


# Homebrew: pushed to githubflyideas/homebrew-tap → `brew install githubflyideas/tap/pingping`.
brews:
- name: pingping
repository:
owner: githubflyideas
name: homebrew-tap
token: "{{ .Env.TAP_TOKEN }}"
directory: Formula
homepage: https://github.com/githubflyideas/pingping
description: Single-binary link quality oscilloscope (modern SmokePing alternative).
license: Apache-2.0
install: |
bin.install "pingping"
test: |
system "#{bin}/pingping", "-version"

release:
github:
owner: githubflyideas
name: pingping
header: |
## Install

**Homebrew** (macOS/Linux):
```bash
brew install githubflyideas/tap/pingping
```
**Or just scp and run** — download a tarball below, extract, `./pingping`. Zero dependencies.
scp a tarball below, extract, `./pingping`. Zero dependencies.
20 changes: 0 additions & 20 deletions config.example.jsonc

This file was deleted.

Binary file removed docs/hero.png
Binary file not shown.
Binary file removed docs/hero1.png
Binary file not shown.
Binary file removed docs/hero4.png
Binary file not shown.
Binary file removed docs/hero5.png
Binary file not shown.
Binary file removed docs/hero7.png
Binary file not shown.
167 changes: 99 additions & 68 deletions static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,77 +6,102 @@
<link rel="icon" href="data:,">
<title>pingping — link quality oscilloscope</title>
<style>
/* Terminal — a trading-desk screen at 2am. Amber trace (the classic financial-
terminal color) over a slate-blue cloud that sinks to navy at the edges. */
:root {
--bg:#0a0c0e; --panel:#101613; --screen:#060808; --line:#1e242a;
--phos:#7ce38b; --amber:#e8b44a; --alert:#ff5c57; --ink:#c7d0c9; --dim:#5c6b60;
--grid-axis:#2a332c; --grid-split:#10281a;
--smoke:rgba(124,227,139,.16); --lossbar:rgba(255,92,87,.55); --glow:6;
--smoke-hot:#d8ffe2; --smoke-mid:#7ce38b; --smoke-cool:#8a7a3a;
--bg:#0e1013; --panel:#171a1f; --screen:#0a0c0e; --line:#2a2f37;
--phos:#f0a838; --amber:#e8c468; --alert:#ef4a5a; --ink:#c4cad2; --dim:#747f8a;
--grid-axis:#323944; --grid-split:#181c22;
--smoke:rgba(90,140,200,.20); --lossbar:rgba(239,74,90,.65); --glow:5;
--smoke-hot:#3a5a86; --smoke-mid:#2a4166; --smoke-cool:#182838;
--shadow:0 1px 2px rgba(0,0,0,.45); --shadow-lg:0 12px 32px rgba(0,0,0,.45);
--mono: ui-monospace,"SF Mono","Cascadia Mono",Consolas,"Noto Sans Mono",monospace;
--sans: system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
--fs-micro:10px; --fs-small:11px; --fs-body:13px; --fs-lead:15px;
--fs-title:19px; --fs-metric:30px;
}
/* Daylight: warm paper — the trace printed on lab graph paper */
html[data-theme="daylight"] {
--bg:#f4f1e8; --panel:#faf8f1; --screen:#fffef9; --line:#e0dbc9;
--phos:#177245; --amber:#986a00; --alert:#c23a32; --ink:#2b2f28; --dim:#8b8a7a;
--grid-axis:#cfc9b4; --grid-split:#ebe6d4;
--smoke:rgba(23,114,69,.20); --lossbar:rgba(194,58,50,.5); --glow:0;
--smoke-hot:#0e5e37; --smoke-mid:#2f9e63; --smoke-cool:#b08a2e;
}
/* Arctic: cool morning light — teal trace on frosted glass */
html[data-theme="arctic"] {
--bg:#edf1f5; --panel:#f6f9fb; --screen:#fbfdfe; --line:#d7e0e8;
--phos:#0b7285; --amber:#b45309; --alert:#d1433f; --ink:#24313d; --dim:#7f8f9d;
--grid-axis:#c3d0db; --grid-split:#e3ebf2;
--smoke:rgba(11,114,133,.18); --lossbar:rgba(209,67,63,.5); --glow:0;
--smoke-hot:#064a57; --smoke-mid:#1596ad; --smoke-cool:#b3722f;


/* Newsprint — a broadsheet market page. Near-black ink trace, cloud runs from
saturated brick to the warm grey of old halftone printing. */
html[data-theme="newsprint"] {
--bg:#efe9dc; --panel:#f8f4ea; --screen:#fdfbf5; --line:#d8cfb8;
--phos:#1a1a18; --amber:#9c3b2e; --alert:#b8241f; --ink:#3d3a33; --dim:#8c8672;
--grid-axis:#c9bfa4; --grid-split:#e5ddc9;
--smoke:rgba(156,59,46,.22); --lossbar:rgba(184,36,31,.55); --glow:0;
--smoke-hot:#c85a3e; --smoke-mid:#d69878; --smoke-cool:#ddd0bc;
--shadow:0 1px 3px rgba(80,70,40,.12); --shadow-lg:0 12px 30px rgba(80,70,40,.16);
}
/* Nord — the arctic palette that ships in half the terminals on earth.
Desaturated blue-greys with a single frost accent; nothing shouts. */
html[data-theme="nord"] {
--bg:#2e3440; --panel:#3b4252; --screen:#292e39; --line:#434c5e;
--phos:#88c0d0; --amber:#ebcb8b; --alert:#bf616a; --ink:#e5e9f0; --dim:#7b88a1;
--grid-axis:#4c566a; --grid-split:#373e4c;
--smoke:rgba(136,192,208,.18); --lossbar:rgba(191,97,106,.55); --glow:5;
--smoke-hot:#eceff4; --smoke-mid:#88c0d0; --smoke-cool:#5e81ac;
--shadow:0 1px 2px rgba(0,0,0,.35); --shadow-lg:0 10px 30px rgba(0,0,0,.30);

/* Ukiyo — Hokusai's indigo woodblock prints. Deep aizuri trace on washi paper,
the cloud runs from Prussian blue to a pale moss highlight. */
html[data-theme="ukiyo"] {
--bg:#eef0e6; --panel:#f7f8f0; --screen:#fdfdf7; --line:#d4d8c4;
--phos:#1b3a6b; --amber:#c17817; --alert:#c1362f; --ink:#324158; --dim:#8593a0;
--grid-axis:#c3cab0; --grid-split:#e2e4d4;
--smoke:rgba(27,58,107,.22); --lossbar:rgba(193,54,47,.5); --glow:0;
--smoke-hot:#4a76ae; --smoke-mid:#88a8cc; --smoke-cool:#d4dcc4;
--shadow:0 1px 3px rgba(40,60,40,.10); --shadow-lg:0 12px 30px rgba(40,60,40,.14);
}
/* Solarized Light — Ethan Schoonover's palette, tuned for long reading sessions.
Warm paper base, muted cyan trace, red reserved strictly for loss. */
html[data-theme="solarized"] {
--bg:#fdf6e3; --panel:#fffbf0; --screen:#fffdf6; --line:#e5ddc8;
--phos:#2aa198; --amber:#b58900; --alert:#dc322f; --ink:#586e75; --dim:#93a1a1;
--grid-axis:#d6cfba; --grid-split:#efe8d5;
--smoke:rgba(42,161,152,.22); --lossbar:rgba(220,50,47,.45); --glow:0;
--smoke-hot:#0f5f5a; --smoke-mid:#2aa198; --smoke-cool:#93a1a1;
--shadow:0 1px 3px rgba(101,123,131,.12); --shadow-lg:0 10px 28px rgba(101,123,131,.16);

/* Memphis — Ettore Sottsass's 1980s Milan collective. Coral trace with real
confidence against soft lavender-grey, teal cloud instead of the expected pink. */
html[data-theme="memphis"] {
--bg:#e8e4ec; --panel:#f5f2f8; --screen:#fbf9fc; --line:#d2c8dc;
--phos:#e3462f; --amber:#0e9488; --alert:#c1362f; --ink:#463b4f; --dim:#8f849a;
--grid-axis:#c9bcd4; --grid-split:#e9e2ee;
--smoke:rgba(14,148,136,.24); --lossbar:rgba(193,54,47,.5); --glow:0;
--smoke-hot:#054841; --smoke-mid:#1fa89a; --smoke-cool:#c4e2da;
--shadow:0 1px 3px rgba(60,50,70,.12); --shadow-lg:0 12px 30px rgba(60,50,70,.16);
}
/* Amber CRT — a DEC VT220 in a dim room. One hue, three intensities, that is it. */
html[data-theme="amber"] {
--bg:#100c04; --panel:#1a1409; --screen:#0a0702; --line:#3a2c14;
--phos:#ffb000; --amber:#ffcc55; --alert:#ff5f2e; --ink:#f0c674; --dim:#8a6d3a;
--grid-axis:#463a1c; --grid-split:#221a0c;
--smoke:rgba(255,176,0,.16); --lossbar:rgba(255,95,46,.5); --glow:8;
--smoke-hot:#fff3d0; --smoke-mid:#ffb000; --smoke-cool:#7a5410;
--shadow:0 1px 2px rgba(0,0,0,.6); --shadow-lg:0 10px 30px rgba(0,0,0,.55);

/* Phosphor — classic P1 green CRT, the mirror image of an amber tube: green
trace, the cloud a warm amber-to-rust decay instead of the usual green fade. */
html[data-theme="phosphor"] {
--bg:#0a0f0a; --panel:#131a12; --screen:#070b06; --line:#233024;
--phos:#5eeb8a; --amber:#8ff0ab; --alert:#ff5f4a; --ink:#b8ceb8; --dim:#6f8570;
--grid-axis:#2c3c2c; --grid-split:#141c14;
--smoke:rgba(230,150,50,.20); --lossbar:rgba(255,95,74,.6); --glow:6;
--smoke-hot:#c47a20; --smoke-mid:#8a5010; --smoke-cool:#3a2c10;
--shadow:0 1px 2px rgba(0,0,0,.6); --shadow-lg:0 12px 32px rgba(0,0,0,.55);
}

* { box-sizing:border-box; margin:0; }
body { background:var(--bg); color:var(--ink); font-family:var(--mono); padding:18px 22px; }
body { background:var(--bg); color:var(--ink); font-family:var(--sans);
font-size:var(--fs-body); line-height:1.5; padding:20px 24px;
-webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility; }
header { display:flex; align-items:baseline; gap:14px; margin-bottom:14px; flex-wrap:wrap; }
.mark { color:var(--phos); font-weight:700; font-size:20px; letter-spacing:.05em; }
.tag { color:var(--dim); font-size:12px; }
.mark { color:var(--phos); font-family:var(--mono); font-weight:700;
font-size:26px; letter-spacing:.03em; display:flex; align-items:center; gap:9px; }
.tag { color:var(--dim); font-size:var(--fs-small); font-weight:400; letter-spacing:.01em; }
.row { display:flex; gap:12px; align-items:flex-start; margin-bottom:14px; flex-wrap:wrap; }
.pills { display:flex; gap:8px; flex-wrap:wrap; }
.pill { font-family:var(--mono); font-size:13px; background:var(--panel); color:var(--ink);
border:1px solid var(--line); border-radius:4px; padding:7px 14px; cursor:pointer;
display:flex; align-items:center; gap:8px; }
.pill.on { border-color:var(--phos); color:var(--phos); }
.pill { font-family:var(--sans); font-size:var(--fs-body); font-weight:500;
background:var(--panel); color:var(--ink);
border:1px solid var(--line); border-radius:6px; padding:7px 14px; cursor:pointer;
display:flex; align-items:center; gap:8px; transition:border-color .12s, color .12s; }
.pill.on { border-color:var(--phos); color:var(--phos); font-weight:600; }
.led { width:8px; height:8px; border-radius:50%; background:var(--phos); box-shadow:0 0 6px var(--phos); }
.led.bad { background:var(--alert); box-shadow:0 0 6px var(--alert); }
/* Brand dot: alternates the two colours already used for host status (green =
healthy, red = down), so the same signal that reads "up/down" on a target row
reads "alive" at the letterhead — a small mnemonic, not a new colour language. */
.brand-led { width:11px; height:11px; border-radius:50%; flex:none;
animation: brand-blink 2.4s ease-in-out infinite; }
@keyframes brand-blink {
0%, 45% { background:var(--phos); box-shadow:0 0 8px var(--phos); }
50%, 95% { background:var(--alert); box-shadow:0 0 8px var(--alert); }
100% { background:var(--phos); box-shadow:0 0 8px var(--phos); }
}
@media (prefers-reduced-motion: reduce) { .brand-led { animation:none; background:var(--phos); } }
.rng { display:flex; background:var(--panel); border:1px solid var(--line); border-radius:4px; overflow:hidden; }
.rng span { color:var(--dim); font-size:11px; padding:8px 10px 0 12px; letter-spacing:.1em; }
.rng button { font-family:var(--mono); font-size:12px; background:none; border:0; color:var(--dim);
padding:8px 14px; cursor:pointer; }
.rng button.on { background:#1a2018; color:var(--amber); }
.rng span { color:var(--dim); font-family:var(--sans); font-size:var(--fs-micro);
font-weight:600; padding:9px 10px 0 12px; letter-spacing:.14em; }
.rng button { font-family:var(--mono); font-size:var(--fs-small); background:none; border:0;
color:var(--dim); padding:8px 13px; cursor:pointer; transition:color .12s; }
.rng button:hover { color:var(--ink); }
.rng button.on { background:color-mix(in srgb, var(--amber) 15%, transparent);
color:var(--amber); font-weight:700; }
.scope { background:var(--panel); border:1px solid var(--line); border-radius:6px; padding:14px; }
.crt { position:relative; }
#chart { height:420px; background:var(--screen); border-radius:4px; }
Expand All @@ -87,21 +112,26 @@
radial-gradient(120% 90% at 50% 42%, transparent 55%, rgba(0,0,0,.38) 100%);
}
.readouts { display:flex; gap:34px; margin-top:12px; flex-wrap:wrap; align-items:flex-end; }
.ro .v { font-size:24px; color:var(--phos); }
.ro .v { font-family:var(--mono); font-size:var(--fs-metric); font-weight:600;
color:var(--phos); line-height:1.1; font-variant-numeric:tabular-nums; }
.ro .v.bad { color:var(--alert); }
.ro .l { font-size:10px; color:var(--dim); letter-spacing:.12em; margin-top:2px; }
.ro .l { font-family:var(--sans); font-size:var(--fs-micro); font-weight:600;
color:var(--dim); letter-spacing:.13em; margin-top:4px; text-transform:uppercase; }
.sp { flex:1; }
footer { margin-top:12px; color:var(--dim); font-size:12px; display:flex; gap:10px; flex-wrap:wrap; }
#conclusion { color:var(--ink); }
.legend { color:var(--dim); }
footer { margin-top:14px; color:var(--dim); font-size:var(--fs-small);
display:flex; gap:14px; flex-wrap:wrap; align-items:baseline; }
#conclusion { color:var(--ink); font-family:var(--mono); font-weight:600;
font-size:var(--fs-body); }
.legend { color:var(--dim); font-family:var(--sans); font-size:var(--fs-small); }
.promos { display:grid; grid-template-columns:1fr 1fr; gap:14px; margin-top:16px; }
@media (max-width:720px) { .promos { grid-template-columns:1fr; } }
.promo { background:var(--panel); border:1px solid var(--line); border-radius:12px; padding:14px 16px;
box-shadow:var(--shadow); text-decoration:none; display:block; }
.promo.sponsor { border-style:dashed; }
.promo.sponsor:hover { border-color:var(--phos); }
.promo-h { font-family:var(--mono); font-size:10px; letter-spacing:.16em; color:var(--dim); margin-bottom:6px; }
.promo-b { color:var(--ink); font-size:13px; }
.promo-h { font-family:var(--sans); font-size:var(--fs-micro); font-weight:700;
letter-spacing:.16em; color:var(--dim); margin-bottom:7px; text-transform:uppercase; }
.promo-b { color:var(--ink); font-size:var(--fs-body); }
.share .promo-b { display:flex; gap:14px; align-items:center; flex-wrap:wrap; }
.share a { color:var(--phos); text-decoration:none; font-weight:600; }
.share a:hover { text-decoration:underline; }
Expand All @@ -111,8 +141,8 @@
</head>
<body>
<header>
<div class="mark">pingping </div>
<div class="tag">One binary. One graph. Zero guesswork.</div>
<div class="mark">pingping <span class="brand-led"></span></div>
<div class="tag">One binary. One graph. One metric: Latency.</div>
<button class="pill" id="themeBtn" title="switch theme" style="margin-left:auto">◐ <span id="themeName">dark</span></button>
</header>

Expand Down Expand Up @@ -168,6 +198,7 @@
<div class="promo-h">LIKE PINGPING? <span id="ver" style="color:var(--phos)"></span></div>
<div class="promo-b">
<a href="https://github.com/githubflyideas/pingping" target="_blank" rel="noopener">★ Star on GitHub</a>
<a href="https://github.com/githubflyideas/fogping" target="_blank" rel="noopener">Powered by Fogping</a>
<span class="share-links" id="shareLinks"></span>
</div>
</div>
Expand All @@ -177,7 +208,7 @@
<script>
const $ = id => document.getElementById(id);
const cssv = n => getComputedStyle(document.documentElement).getPropertyValue(n).trim();
const THEMES = ['dark', 'daylight', 'arctic', 'nord', 'solarized', 'amber'];
const THEMES = ['dark', 'newsprint', 'ukiyo', 'memphis', 'phosphor'];
let theme = localStorage.getItem('pp_theme') || 'dark';
if (!THEMES.includes(theme)) theme = 'dark';
function applyTheme() {
Expand Down Expand Up @@ -394,7 +425,7 @@

(function buildShare() {
const url = 'https://github.com/githubflyideas/pingping';
const text = 'pingping — a single-binary link quality oscilloscope. One binary. One graph. Zero guesswork.';
const text = 'pingping — a single-binary link quality oscilloscope. One binary. One graph. One metric: Latency.';
const links = {
X: `https://twitter.com/intent/tweet?text=${encodeURIComponent(text)}&url=${encodeURIComponent(url)}`,
Facebook: `https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(url)}`,
Expand Down
Loading
Loading