The problem I was scratching
Every time I was debugging a web app, the same friction kept happening: I'd
see a request in Chrome DevTools' Network tab, and to actually test a
variation of it — a different header, a different body, a different query
param — I had to copy it out to Postman or Insomnia, paste it in, re-add
auth headers, and lose all the DevTools context in the process. Small
friction, but it happened a dozen times a day.
So I built Network Sniper, a Chrome extension that puts an editable,
resend-capable request panel directly inside DevTools. Capture a request,
edit it in place, hit resend, and see a diff between the old and new
response — no context switch.
It's local-first by design: no telemetry, no cloud sync, sensitive headers
masked by default. That promise turned out to be more important than I
expected, for reasons I'll get to.
Launch day: smaller than I hoped, which taught me something
I posted a Show HN. It didn't hit the front page — under 10 upvotes, a
handful of comments. In the first few hours I got about 15 installs, then
growth flattened out almost completely. If you're benchmarking your own
launch: don't assume a Show HN that doesn't take off means the product is
bad. It might just mean the post didn't catch the algorithm's attention
that hour. I posted on a Wednesday; in hindsight I'd try a different day
and spend more time on the title.
The bigger lesson came from what happened after launch, not the launch
numbers themselves.
Surprise #1: I accidentally asked for way too much permission
To support resending requests to any API the user is debugging (which by
definition could be any origin — that's the whole point of the tool), my
first shipped version declared:
"host_permissions": ["*://*/*"]
This works, technically. It also means Chrome shows every installer a
scary warning: "Read and change all your data on all websites." For a
tool whose entire pitch is "trustworthy, local-first, minimal," that's a
bad first impression — and it's exactly the kind of thing a careful
reviewer (or a future acquirer, if you're building to eventually sell a
side project) will flag immediately.
The fix was to stop asking for broad access up front, and instead request
permission for a specific origin only when the user actually tries to
resend a request to it:
"optional_host_permissions": ["*://*/*"]
// only requested at the moment of use, scoped to the exact origin
const granted = await chrome.permissions.request({
origins: [targetOriginPattern],
});
Approved origins get cached for the session so the user isn't re-prompted
every time. The install-time warning disappeared completely. Lesson: if
your extension needs broad capability, that doesn't mean it needs broad
permission — request narrowly, and only when the user's action actually
requires it.
Surprise #2: the "zero telemetry" tool had a Google Analytics property
This one stung more. A few days after launch, I was checking install
numbers and ended up looking at a Google Analytics real-time dashboard
that was, unmistakably, tied to my extension's own ID — active users,
country breakdown, the works. For a project whose README and public launch
comment both said "zero telemetry, nothing leaves the browser," that's not
a small inconsistency.
I did a full audit: grep'd the entire codebase and build output for any
analytics SDK, tracking domain, or beacon call. Found nothing in the
runtime code. Loaded the actual packaged extension in a real Chrome
profile, pointed it at a live API, and watched the network traffic for a
sustained window. Zero requests to any analytics domain — every outbound
request went exactly where the user told it to go.
The likely explanation: Chrome Web Store's own Developer Dashboard lets
you optionally link a Google Analytics property to track your store
listing page views — a completely separate thing from the extension's
runtime behavior. It's easy to conflate "traffic to my listing" with
"telemetry from my extension," and I did, for a few uncomfortable hours.
I still added a regression test that scans the entire source tree and
build output for analytics domains and SDK signatures, plus a comment at
the top of the manifest and entry files saying, bluntly, don't add
tracking here. Not because I found a violation, but because "I was pretty
sure it was fine" isn't the bar I want for a tool whose whole pitch is
trust.
Where it stands now
Network Sniper is live, permission-minimal, and — as far as a real,
instrumented live-browser test can show — genuinely telemetry-free. Growth
is slow and mostly self-inflicted right now (a quiet Show HN, a Reddit post
caught by a spam filter I'm still waiting on mods to review), which is its
own lesson: shipping the product is maybe 30% of the work, and I
underestimated the rest.
If you debug APIs and have felt the Postman-copy-paste friction, I'd
genuinely appreciate you trying it and telling me what's missing:
It's free, Manifest V3, and — now provably — doesn't phone home.
Top comments (1)
The optional_host_permissions move is the one more extension authors should know about — I went through the same conversion on a browser extension of my own, and the install-warning difference is night and day. One thing worth adding from that experience: the runtime
permissions.request()call has to happen in a context with user gesture (a click handler, not a background task), and if your resend flow can also be triggered from a keyboard shortcut you'll need a fallback path, because the permission prompt silently no-ops there. Worth a line in your docs before someone files it as a bug.The bundled analytics story is the more interesting one, honestly. Template scaffolds and tutorial code ship with GA snippets far more often than people realize, and the reviewer's "trust me, I didn't write it" doesn't count for anything in the store listing. For anyone auditing their own extension: search the packaged output for
google-analytics,gtag, andgoogletagmanager— and check your dependencies too, since an npm package pulling in an analytics shim is the sneakiest variant.Also agree on the Show HN read: launches are lottery-shaped. What actually moved numbers for my extension wasn't the launch post at all, it was showing up in issue threads where people were already hitting the problem the tool solves. Slower, but the users stick.