Skip to content

Instantly share code, notes, and snippets.

@the-code-rider
Created January 6, 2026 10:38
Show Gist options
  • Select an option

  • Save the-code-rider/0e19f59df01f627b0d7ded787849bfb0 to your computer and use it in GitHub Desktop.

Select an option

Save the-code-rider/0e19f59df01f627b0d7ded787849bfb0 to your computer and use it in GitHub Desktop.
display network request as a heads up display
(() => {
// --- Guard (so you can re-run safely) ---
if (window.__NET_HUD__) {
window.__NET_HUD__.destroy();
console.log("[net-hud] removed existing HUD");
}
// --- Config ---
const CFG = {
maxItems: 200,
bodyPreviewChars: 1200,
hudWidth: 520,
hudMaxHeight: 420
};
// --- State ---
const state = {
enabled: true,
minimized: false,
filter: "",
items: [],
expandedId: null,
seq: 0,
origFetch: window.fetch,
origXHROpen: XMLHttpRequest.prototype.open,
origXHRSend: XMLHttpRequest.prototype.send
};
const nowISO = () => new Date().toISOString();
const ms = (t0) => Math.max(0, Math.round(performance.now() - t0));
const clampStr = (s, n) => (s && s.length > n ? s.slice(0, n) + "…" : s);
function safeStringify(obj) {
try { return JSON.stringify(obj, null, 2); } catch { return String(obj); }
}
function toHeaderObject(headers) {
try {
if (!headers) return null;
if (typeof headers.forEach === "function") {
const o = {};
headers.forEach((v, k) => (o[k] = v));
return o;
}
if (Array.isArray(headers)) return Object.fromEntries(headers);
if (typeof headers === "object") return headers;
return null;
} catch {
return null;
}
}
function pushItem(item) {
state.items.unshift(item);
if (state.items.length > CFG.maxItems) state.items.length = CFG.maxItems;
render();
}
function matchesFilter(item) {
const f = state.filter.trim().toLowerCase();
if (!f) return true;
return (
(item.url || "").toLowerCase().includes(f) ||
(item.method || "").toLowerCase().includes(f) ||
String(item.status || "").includes(f)
);
}
// --- HUD UI ---
const root = document.createElement("div");
root.id = "__net_hud__";
root.style.cssText = `
position: fixed;
top: 12px;
right: 12px;
width: ${CFG.hudWidth}px;
max-width: calc(100vw - 24px);
z-index: 2147483647;
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
font-size: 12px;
color: #eaeaea;
background: rgba(10, 10, 12, 0.88);
border: 1px solid rgba(255,255,255,0.14);
border-radius: 12px;
box-shadow: 0 18px 60px rgba(0,0,0,0.5);
overflow: hidden;
backdrop-filter: blur(8px);
`;
const header = document.createElement("div");
header.style.cssText = `
display: flex;
gap: 8px;
align-items: center;
padding: 10px 10px 8px 10px;
border-bottom: 1px solid rgba(255,255,255,0.10);
user-select: none;
cursor: default;
`;
const title = document.createElement("div");
title.textContent = "NET HUD";
title.style.cssText = `font-weight: 700; letter-spacing: 0.4px;`;
const pill = document.createElement("div");
pill.style.cssText = `
margin-left: 6px;
padding: 2px 8px;
border-radius: 999px;
font-size: 11px;
border: 1px solid rgba(255,255,255,0.14);
color: rgba(255,255,255,0.85);
`;
const spacer = document.createElement("div");
spacer.style.flex = "1";
const filter = document.createElement("input");
filter.placeholder = "filter (url / method / status)…";
filter.style.cssText = `
flex: 1;
min-width: 140px;
padding: 6px 8px;
border-radius: 10px;
border: 1px solid rgba(255,255,255,0.14);
outline: none;
background: rgba(255,255,255,0.06);
color: #fff;
`;
filter.addEventListener("input", () => {
state.filter = filter.value || "";
render();
});
function mkBtn(label, onClick) {
const b = document.createElement("button");
b.textContent = label;
b.style.cssText = `
padding: 6px 8px;
border-radius: 10px;
border: 1px solid rgba(255,255,255,0.14);
background: rgba(255,255,255,0.06);
color: rgba(255,255,255,0.92);
cursor: pointer;
`;
b.onmouseenter = () => (b.style.background = "rgba(255,255,255,0.10)");
b.onmouseleave = () => (b.style.background = "rgba(255,255,255,0.06)");
b.onclick = onClick;
return b;
}
const btnPause = mkBtn("Pause", () => {
state.enabled = !state.enabled;
btnPause.textContent = state.enabled ? "Pause" : "Resume";
render();
});
const btnClear = mkBtn("Clear", () => {
state.items = [];
state.expandedId = null;
render();
});
const btnCopy = mkBtn("Copy JSON", async () => {
const payload = state.items.slice().reverse(); // oldest->newest
const text = safeStringify(payload);
try {
await navigator.clipboard.writeText(text);
btnCopy.textContent = "Copied";
setTimeout(() => (btnCopy.textContent = "Copy JSON"), 700);
} catch {
console.log(text);
btnCopy.textContent = "Logged";
setTimeout(() => (btnCopy.textContent = "Copy JSON"), 700);
}
});
const btnMin = mkBtn("Min", () => {
state.minimized = !state.minimized;
btnMin.textContent = state.minimized ? "Max" : "Min";
render();
});
const btnClose = mkBtn("×", () => window.__NET_HUD__.destroy());
btnClose.style.padding = "6px 10px";
btnClose.style.fontWeight = "800";
header.appendChild(title);
header.appendChild(pill);
header.appendChild(spacer);
header.appendChild(filter);
header.appendChild(btnPause);
header.appendChild(btnClear);
header.appendChild(btnCopy);
header.appendChild(btnMin);
header.appendChild(btnClose);
const body = document.createElement("div");
body.style.cssText = `
max-height: ${CFG.hudMaxHeight}px;
overflow: auto;
`;
const details = document.createElement("div");
details.style.cssText = `
display: none;
padding: 10px;
border-top: 1px solid rgba(255,255,255,0.10);
background: rgba(255,255,255,0.03);
white-space: pre-wrap;
word-break: break-word;
`;
root.appendChild(header);
root.appendChild(body);
root.appendChild(details);
document.documentElement.appendChild(root);
function statusBadgeColor(status) {
if (status == null) return "rgba(255,255,255,0.10)";
if (status >= 200 && status < 300) return "rgba(60, 200, 120, 0.28)";
if (status >= 300 && status < 400) return "rgba(120, 180, 240, 0.26)";
if (status >= 400 && status < 500) return "rgba(240, 180, 80, 0.26)";
return "rgba(240, 90, 90, 0.26)";
}
function render() {
pill.textContent = `${state.enabled ? "live" : "paused"} • ${state.items.length}/${CFG.maxItems}`;
if (state.minimized) {
body.style.display = "none";
details.style.display = "none";
filter.style.display = "none";
return;
} else {
body.style.display = "block";
filter.style.display = "block";
}
// list
body.innerHTML = "";
const visible = state.items.filter(matchesFilter);
visible.slice(0, CFG.maxItems).forEach(item => {
const row = document.createElement("div");
row.style.cssText = `
display: grid;
grid-template-columns: 54px 1fr 52px 52px;
gap: 8px;
align-items: center;
padding: 8px 10px;
border-bottom: 1px solid rgba(255,255,255,0.06);
cursor: pointer;
`;
row.onmouseenter = () => (row.style.background = "rgba(255,255,255,0.05)");
row.onmouseleave = () => (row.style.background = "transparent");
const method = document.createElement("div");
method.textContent = (item.method || "GET").toUpperCase();
method.style.cssText = `opacity: 0.92; font-weight: 700;`;
const url = document.createElement("div");
url.textContent = item.url || "(unknown url)";
url.style.cssText = `opacity: 0.92; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;`;
const status = document.createElement("div");
status.textContent = item.status == null ? "—" : String(item.status);
status.style.cssText = `
text-align: center;
padding: 2px 6px;
border-radius: 999px;
background: ${statusBadgeColor(item.status)};
border: 1px solid rgba(255,255,255,0.10);
`;
const dur = document.createElement("div");
dur.textContent = item.durationMs != null ? `${item.durationMs}ms` : "—";
dur.style.cssText = `text-align: right; opacity: 0.85;`;
row.appendChild(method);
row.appendChild(url);
row.appendChild(status);
row.appendChild(dur);
row.onclick = () => {
state.expandedId = state.expandedId === item.id ? null : item.id;
renderDetails();
};
body.appendChild(row);
});
renderDetails();
}
function renderDetails() {
const item = state.items.find(x => x.id === state.expandedId);
if (!item) {
details.style.display = "none";
details.textContent = "";
return;
}
details.style.display = "block";
const parts = [];
parts.push(`[${item.ts}] ${item.method} ${item.url}`);
if (item.status != null) parts.push(`status: ${item.status}`);
if (item.durationMs != null) parts.push(`duration: ${item.durationMs}ms`);
if (item.type) parts.push(`type: ${item.type}`);
if (item.error) parts.push(`error: ${item.error}`);
parts.push("");
if (item.requestHeaders) {
parts.push("request headers:");
parts.push(safeStringify(item.requestHeaders));
parts.push("");
}
if (item.responseHeaders) {
parts.push("response headers:");
parts.push(safeStringify(item.responseHeaders));
parts.push("");
}
if (item.requestBodyPreview) {
parts.push("request body (preview):");
parts.push(item.requestBodyPreview);
parts.push("");
}
if (item.responseBodyPreview) {
parts.push("response body (preview):");
parts.push(item.responseBodyPreview);
parts.push("");
}
details.textContent = parts.join("\n");
}
render();
// --- Hooks: fetch ---
window.fetch = async (...args) => {
const id = `f_${++state.seq}`;
const t0 = performance.now();
let url = "";
let method = "GET";
let reqHeaders = null;
let reqBodyPreview = null;
try {
const [input, init] = args;
url = typeof input === "string" ? input : input?.url || "";
method = (init?.method || (typeof input !== "string" && input?.method) || "GET").toUpperCase();
reqHeaders = toHeaderObject(init?.headers) || toHeaderObject((typeof input !== "string" && input?.headers) ? input.headers : null);
if (init?.body != null) reqBodyPreview = clampStr(String(init.body), CFG.bodyPreviewChars);
} catch {}
if (state.enabled) {
pushItem({
id,
ts: nowISO(),
type: "fetch",
phase: "start",
url,
method,
requestHeaders: reqHeaders,
requestBodyPreview: reqBodyPreview
});
}
try {
const res = await state.origFetch(...args);
const durationMs = ms(t0);
let responseHeaders = null;
let responseBodyPreview = null;
try {
responseHeaders = toHeaderObject(res.headers);
// Best-effort body preview (may fail for opaque/cors/stream)
const ct = res.headers?.get?.("content-type") || "";
if (!/image|audio|video|font|octet-stream/i.test(ct)) {
const text = await res.clone().text();
responseBodyPreview = clampStr(text, CFG.bodyPreviewChars);
}
} catch {}
if (state.enabled) {
pushItem({
id,
ts: nowISO(),
type: "fetch",
phase: "done",
url,
method,
status: res.status,
durationMs,
responseHeaders,
responseBodyPreview
});
}
return res;
} catch (err) {
if (state.enabled) {
pushItem({
id,
ts: nowISO(),
type: "fetch",
phase: "error",
url,
method,
durationMs: ms(t0),
error: String(err?.message || err)
});
}
throw err;
}
};
// --- Hooks: XHR ---
XMLHttpRequest.prototype.open = function (method, url) {
this.__netHudMeta = {
id: `x_${++state.seq}`,
t0: performance.now(),
method: String(method || "GET").toUpperCase(),
url: String(url || "")
};
return state.origXHROpen.apply(this, arguments);
};
XMLHttpRequest.prototype.send = function (body) {
const meta = this.__netHudMeta || {
id: `x_${++state.seq}`,
t0: performance.now(),
method: "GET",
url: "(unknown)"
};
const reqBodyPreview = body != null ? clampStr(String(body), CFG.bodyPreviewChars) : null;
if (state.enabled) {
pushItem({
id: meta.id,
ts: nowISO(),
type: "xhr",
phase: "start",
url: meta.url,
method: meta.method,
requestBodyPreview: reqBodyPreview
});
}
this.addEventListener("loadend", () => {
if (!state.enabled) return;
let responseBodyPreview = null;
try {
const ct = this.getResponseHeader?.("content-type") || "";
if (!/image|audio|video|font|octet-stream/i.test(ct)) {
responseBodyPreview = clampStr(String(this.responseText || ""), CFG.bodyPreviewChars);
}
} catch {}
pushItem({
id: meta.id,
ts: nowISO(),
type: "xhr",
phase: "done",
url: meta.url,
method: meta.method,
status: this.status,
durationMs: ms(meta.t0),
responseBodyPreview
});
});
return state.origXHRSend.apply(this, arguments);
};
// --- Drag to move (HUD) ---
let drag = null;
header.addEventListener("mousedown", (e) => {
// avoid dragging when clicking buttons/input
const tag = (e.target?.tagName || "").toLowerCase();
if (tag === "button" || tag === "input") return;
drag = {
startX: e.clientX,
startY: e.clientY,
rect: root.getBoundingClientRect()
};
e.preventDefault();
});
window.addEventListener("mousemove", (e) => {
if (!drag) return;
const dx = e.clientX - drag.startX;
const dy = e.clientY - drag.startY;
// switch to left/top positioning when dragged
root.style.right = "auto";
root.style.bottom = "auto";
root.style.left = Math.max(8, drag.rect.left + dx) + "px";
root.style.top = Math.max(8, drag.rect.top + dy) + "px";
});
window.addEventListener("mouseup", () => (drag = null));
// --- Public control surface ---
window.__NET_HUD__ = {
state,
export() {
return state.items.slice().reverse();
},
destroy() {
// restore originals
window.fetch = state.origFetch;
XMLHttpRequest.prototype.open = state.origXHROpen;
XMLHttpRequest.prototype.send = state.origXHRSend;
// remove UI
root.remove();
delete window.__NET_HUD__;
console.log("[net-hud] destroyed and hooks restored");
}
};
console.log("[net-hud] running. Controls: __NET_HUD__.export(), __NET_HUD__.destroy()");
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment