Case Study · Privacy-First Chrome Extension

You forget the subscriptions.
They never forget you.

Every rival subscription tracker starts by asking for your bank login. Catchly refuses to — it watches sign-ups, renewals and price hikes on 24 services you already use, keeps the whole list on your device, and warns you before the card gets charged. No bank connection. No account. Nothing leaves your browser.

See the live site
Muzeeb Urrahaman Solo designer + builder v0.1.0 · Web Store review MV3 · Chrome / Brave / Edge
24
Services auto-detected
0
Bank logins ever required
0
Outbound calls in normal use
18
Working features, not stubs
22
Playwright smoke tests
MIT
Source-available, verifiable
In one line

Catchly is a Chrome extension that spots your recurring charges the moment you sign up, keeps that list on your own device, and warns you before every renewal, free-trial conversion, and price hike — without a bank login or an account.

The subscriptions costing you the most are the ones you've forgotten. The obvious fix — an app that reads your bank feed — means handing a startup your banking credentials and paying it a cut of your "savings." Catchly takes the opposite bet: it never touches your bank. It watches only the 24 subscription sites you already visit, notices when you sign up or hit a renewal page, and does all of the tracking, reminding and math locally in your browser. Nothing about your subscriptions is ever uploaded anywhere.

Problem

  • People lose money to subscriptions they forgot they have — trials that convert, quiet price hikes, apps they stopped opening.
  • The usual fix demands your bank login and takes a cut of "savings."
  • Cancelling is a maze of dark patterns designed to make you give up.

Solution

  • Detects sign-ups on the sites you already use — no bank, no account.
  • Everything lives in your browser's local storage; nothing is uploaded.
  • Warns before renewals, flags price hikes, and guides you to the real cancel page.

Results

  • 18 features shipping as real code, exercised by a 22-test smoke suite.
  • Zero telemetry — no analytics, crash reporter, or usage ping anywhere.
  • v0.1.0 submitted to the Chrome Web Store, live preview at getcatchly.com.
The bet
Why this exists

The bank login is the industry default. Refusing it is the whole product.

Every popular subscription tracker works the same way: connect it to your bank through a data aggregator, let it read every transaction, and let it charge you — often 30–60% of the money it "saves" you. That model is powerful, but it asks you to trust a third party with the keys to your entire financial life, and it quietly reads every purchase you make, not just the subscriptions.

That teardown is the research. I went through the popular trackers, and the pattern was unanimous: every one starts by asking for a bank connection and takes a cut. There was no privacy-first option on the shelf. That gap, not a feature wish, is the decision the whole product is built on: refuse the bank entirely and see how much value survives. Most of it does.

Catchly's bet is that most of the value comes without any of that risk. It never sees your bank. Instead it watches only a narrow, fixed list of 24 subscription sites — the streaming, AI, productivity, news, design and storage services people actually pay for — and detects the subscription right where it happens: at the sign-up or renewal page. The tracking, the reminders and the spend math all run on your device. This isn't a privacy footnote; it is the product.

Privacy is a design constraint, not a marketing line. The extension is limited by Chrome itself to a 24-domain allowlist — it is technically incapable of running on your bank, brokerage, healthcare portal, or any login page. And it makes zero outbound network calls during normal use: no analytics SDK, no telemetry, no error logger. Every claim is checkable in the open-source code.
What it catches
The job, plainly

Nine things Catchly catches for you.

Each one is a specific moment where money slips away silently. Catchly's job is to make that moment visible before the charge lands — in plain language, with a way to act on it.

Auto-detect

Catches sign-ups as they happen

Land on a checkout or sign-up page for a supported service and an in-page toast slides in offering to track it. No copying, no manual entry.

Reminders

Warns you before every renewal

Chrome notifications 1, 3, or 7 days ahead (your choice). The one before the charge, not the statement after it.

Free trial

24-hour warning before a trial converts

The most expensive kind of forgetting — a "free" trial quietly turning into a paid plan — gets its own countdown alert.

Price hike

Flags increases the day they appear

When a renewal page shows a higher price than last time, Catchly surfaces the change (e.g. Netflix $22.99 → $24.99) instead of letting it slide by.

Shadow charge

Finds subscriptions you've stopped using

Haven't opened a service in 30+ days but it's still billing you? A local usage sweep flags it — the classic "still paying for Audible" case.

Cancel guide

Points you to the real cancel page

"Cancel this" deep-links straight to the service's cancellation page and lists the dark-pattern steps in plain English — honest guidance, not fake automation.

Calendar

A 30-day view of what's coming

A renewal calendar with day-by-day dots so the next month is never a surprise, plus a rolling "next 30 days" list.

Insights

Monthly, yearly & annual run-rate

A spend summary that stays honest with mixed currencies — USD, EUR, GBP, CAD, AUD, JPY and INR totals are kept separate, never mashed together.

Badge

Days-to-renewal at a glance

Pin the toolbar icon and its badge counts down to your most urgent renewal, colour-coded safe → soon → urgent → overdue.

How it works
The flow

Detect locally, remember locally, remind locally.

There's no server in the loop. A small script runs only on the 24 allowlisted sites, spots a subscription, and hands it to a background worker that stores it on your device and schedules the reminders. Here's the whole path, start to finish:

1

You visit a supported service

Say netflix.com/signup or spotify.com/premium. A content script — allowed to run only on the 24 listed domains — reads the page.

2

Catchly recognises the charge

It matches the site against a local service catalogue (lib/merchants.js) that knows the brand, typical price, billing cycle and real cancel URL — then slides in an in-page toast offering to track it.

3

You save it in one click

The subscription is written to chrome.storage.local — your browser, your device. Never chrome.storage.sync, never a server. Can't auto-detect a service? Add any name manually in about ten seconds.

4

The background worker does the watching

A service worker schedules Chrome alarms for each renewal, runs a daily shadow-charge sweep, and updates the toolbar badge — all offline, all on-device.

5

You get warned in time

Local Chrome notifications fire before renewals and trial conversions. Open the popup to see the dashboard, the calendar, the price-hike alerts, and a one-click link to cancel.

The permission model

Four permissions, each with one honest reason.

Catchly asks for the minimum it needs and nothing more. There is no <all_urls> — the browser itself blocks it from running anywhere outside the allowlist. Here's exactly what each permission is for:

● storage

Saves your subscription list, settings and usage history to your device.

local only
● alarms

Schedules the renewal, trial and shadow-charge reminders for a future time.

no server timers
● notifications

Shows the desktop reminders — generated locally, never from a remote payload.

on-device
● tabs

Opens the cancel page, and notices when you visit a known service (for shadow charges).

matched locally
Catchly subscriptions dashboard showing tracked services organised by next renewal
The main dashboard — every recurring charge in one place, organised by next renewal, with a monthly / yearly / active-count summary strip that stays currency-aware.
Old way vs Catchly
The difference that matters

Same goal, opposite data path.

Both a bank-linked tracker and Catchly want to answer "what am I paying for?" The difference is where your data goes to get the answer. On the left, the model everyone else uses; on the right, Catchly's:

The bank-linked model
// 1. Hand over your bank credentials
aggregator.link(bankUsername, bankPassword);

// 2. Every transaction is read & uploaded
const all = await server.fetchTransactions();
//    …groceries, rent, everything — not
//    just your subscriptions

// 3. Data lives on their servers
cloud.store(all);            // synced, mineable

// 4. They bill you a cut of "savings"
subscription.charge(0.4 * saved);
How Catchly works
// 1. No login. Nothing to hand over.
//    Runs only on 24 allowlisted sites.

// 2. Detects the sub at the source
const sub = detectOnPage(location.host);

// 3. Saved on YOUR device — never synced
await chrome.storage.local.set({ sub });
// no chrome.storage.sync, no backend

// 4. Free, forever. Zero outbound calls
//    during normal use.
notifications.local(renewalSoon);

The trade-off, stated honestly: because Catchly never reads your bank, it only knows about services it can see you use in the browser — that's why the supported list is explicit and grows over time. In exchange, you never share a banking credential, your subscription list never leaves your device, and there's no percentage-of-savings fee. That's the deal, and it's the point.

The same on-device approach powers every screen in the popup. These are the real listing shots:

The hard parts
The judgment calls

The interesting decisions were about restraint.

Anyone can build a subscription list. The decisions that make Catchly trustworthy were mostly about what to not do — and being honest about the limits. Four real ones:

The content catalogue is the moat. lib/merchants.js maps messy statement descriptors ("GOOGLE *YOUTUBE PREMIUM") to a clean service, with the real cancel URL, default price, billing cycle and brand colour for each. Every new entry takes about five minutes — and that hand-curated knowledge, not the code, is what would be slow for a competitor to copy.
The stack
Under the hood

A Manifest V3 extension, built to be audited.

No framework, no build-time magic to hide behind — plain modules that a reviewer can read top to bottom. Every file has one job:

File / folderWhat it does
manifest.jsonMV3 config. Permissions: storage, alarms, notifications, tabs. host_permissions is a narrow 24-domain allowlist — never <all_urls>.
background.jsThe service worker — schedules alarms, draws the toolbar badge, fires notifications, routes messages, and tracks usage via chrome.tabs.onUpdated.
content.js / .cssRuns only on the 24 allowlisted hosts. Detects a subscription and renders the in-page capture toast.
popup.*The dashboard — four tabs (Subs, Alerts, Insights, Settings), drawers, the renewal calendar, first-run onboarding and the "What's New" popover.
lib/merchants.jsThe content moat. 20+ services with aliases, real cancel URLs & steps, default prices and brand colours.
lib/storage.jsA chrome.storage.local wrapper with a sample-data seeder and schema-versioned migrate-on-read.
worker/A ~60-line Cloudflare Worker — the only backend, used solely for the opt-in Gmail-scan waitlist. KV-backed; stores an email and nothing else.
tests/smoke.spec.jsA Playwright smoke suite — 22 tests across boot, storage, brand-logo loading, worker CORS, onboarding and integration, run against the real unpacked extension.
Try it in two minutes

Load it unpacked, load the sample data, done.

No login, no account, no setup. The fastest way to see everything working:

# 1. Open chrome://extensions, enable Developer mode,
#    click "Load unpacked" and pick this folder.

# 2. Click the Catchly icon → 3-screen onboarding plays.
# 3. Settings → "Load sample data" for a 2-second tour
#    (includes a Netflix price hike + an Audible shadow charge).

# 4. Visit a supported site to see live detection:
netflix.com/signup   # the in-page toast slides in
Results
Where it stands

Shipping, verifiable, and honest about scope.

Catchly v0.1.0 is submitted to the Chrome Web Store with a live preview on getcatchly.com. Everything in the feature list is working code, not placeholder — the smoke suite exercises the critical paths on every run, and because the whole thing is source-available under MIT, every privacy claim can be checked line by line.

The unglamorous states, designed on purpose. First-run popup is a real empty state — an icon, "No subscriptions tracked yet," and a one-line nudge to visit a supported site — not a blank panel. Detection that fails never blocks the page: the in-page toast just doesn't appear. And the insights view stays correct at the edges — mixed currencies (USD, EUR, GBP, INR…) are kept in separate totals, never mashed into one wrong number.
18

features, all functional

Auto-detect, reminders, price-hike & shadow-charge alerts, calendar, insights, guided cancel, import/export, four themes — real code, not stubs.

0

trackers, by design

No analytics SDK, crash reporter, telemetry beacon or usage ping. Zero outbound calls in normal use; one optional, disclosed waitlist call.

24

services, growing weekly

A hand-curated catalogue across streaming, AI, productivity, news, design & storage — each new entry takes about five minutes to add.

Reflection
Reflection

The version I didn't build — and what I'd change.

The obvious build is the one every rival ships: connect to the bank through an aggregator, read every transaction, take a cut of the "savings." I followed that path to its end and killed it — it means holding someone's financial keys and reading purchases that have nothing to do with subscriptions. Refusing it is the product, but I'm honest that it costs real coverage: Catchly only sees the 24 sites on its allowlist, so a subscription bought somewhere off-list is invisible. I took a smaller, honest scope over a broader, creepier one.

What I'd do differently: I hand-curated the 24-domain allowlist, which doesn't scale — every new service is a code change by me. I'd invest earlier in a community-editable detection-rule format so coverage can grow without me in the loop.

What's next
What I'd do next

Ordered by value, not novelty.

The through-line. Every future feature follows one rule: local-first, no data sold, no bank login required. The privacy stance isn't a phase of the product — it's the reason the product exists.
Interview brief
Anticipated questions

The things people probe for.

Isn't this just Rocket Money without the bank feature?
It's the opposite trade. Bank-linked trackers read every transaction you make and typically charge a cut of your "savings." Catchly deliberately never touches your bank — it detects subscriptions at the source (the sign-up and renewal pages you already visit), keeps the list on your device, and is free. You give up some coverage (it only sees services in the browser) in exchange for never sharing a banking credential and never uploading your data.
Do I need to log in or create an account?
No. There's no account, no password, no sign-up, and no bank connection. You install it, open the toolbar icon, and you're in the dashboard. It works entirely offline for the core product.
How does it detect a subscription without reading my private data?
A content script runs only on the 24 subscription domains listed in the manifest, and matches the page against a local catalogue of known services (lib/merchants.js). Chrome enforces that allowlist at the platform level — the extension is technically unable to run on your bank, email, or any site outside the list. Nothing about the visit is transmitted anywhere.
Where does my subscription data actually live?
In chrome.storage.local — your browser, on your device. Never chrome.storage.sync, never a server. You can verify it in DevTools, and you can export the whole thing to a JSON file (and re-import it) whenever you want. Your data, your file.
You say "zero outbound calls." Is that literally true?
In normal use, yes. There's no analytics SDK, crash reporter, telemetry beacon or error logger anywhere in the code, and even brand logos are bundled rather than fetched from a CDN. The single exception fires only if you click "Notify me" on the optional Gmail-scan waitlist — that POSTs your email (and nothing about your subscriptions) to a small Cloudflare Worker, and it's disclosed in the privacy policy.
Why doesn't it just cancel subscriptions for me?
Because honest guidance beats brittle automation. Sites redesign their cancel flows constantly, and per-service auto-clicking breaks weekly — which is why services that promise it quietly use humans and charge a percentage. Catchly deep-links you straight to the real cancel page and lists the dark-pattern steps in plain English, so you keep control and it keeps working.
Can I trust the privacy claims?
You don't have to trust them — the full source is on GitHub under the MIT license, so every claim in the listing is checkable in code. The narrow permission model is right there in manifest.json, and the storage, alarms, notifications and tabs permissions each have a documented, single-purpose justification.