Somebody built is-odd-AI. That is the state of the industry in one artifact: a package that checks whether a number is odd, dressed up with artificial intelligence, because the base package — is-odd, which computes n % 2 — still pulls hundreds of thousands of downloads every single day.
Sit with that. We have shipped a decade of web apps that treat the browser as a dumb execution environment, a canvas we bring our own everything to, right down to being afraid to write n % 2 !== 0 without a safety net from npm.
That's the punchline everyone laughs at. But is-odd is a symptom, not the disease.
The disease is that nobody's job is to notice when a dependency became obsolete. This is not a knowledge problem. Most developers know fetch exists, know Intl exists, know that native dialogs shipped years ago.
The problem is that nothing in the workflow ever re-poses the question after install. You run npm audit on a cadence — weekly, on every CI run, whenever a CVE drops. The audit fires reliably for security.
But "is this library still doing something the browser can't?" is a question that basically never gets asked. So the libraries stay, outliving their justification by years.
The disease is that nobody's job is to notice when a dependency became obsolete. So the libraries stay, outliving their justification by years.
The number attached to this negligence is concrete. In a typical mid-sized JavaScript app, you can find somewhere between 60KB and 90KB — minified and gzipped — of dependencies the platform can now handle on its own.
Date and number formatting. HTTP requests. Modals, tooltips, deep cloning, grouping arrays. These were real gaps a few years ago. Most of them aren't gaps anymore.
The reason they stick around isn't laziness, and it isn't technical debt in the usual sense. It's that most teams don't re-audit their dependencies on a Baseline cadence, and many aren't aware of how fast browsers are shipping now.
How fast? Look at the Interop numbers. Interop 2025 reportedly started the year at a 29% pass rate across all engines and finished at 97% in stable releases.
That is the whole story compressed into two figures. The vendors now converge on a set of new features within a single calendar year. The "works in my browser but not yours" problem that drove an entire generation of tooling adoption — jQuery, Autoprefixer, the polyfill-industrial complex — is, for the features that matter, solved.
Which means the cross-browser rationale that justified reaching for a library is often gone before you've even upgraded the library. The platform moved. Your package.json didn't get the memo.
So let's make the audit a real thing rather than a hallway epiphany. The tool that turns "the browser does this now" into a schedulable decision is Baseline.
Baseline, from the WebDX Community Group, tells you in plain terms how safe a feature is across Chrome, Edge, Firefox, and Safari. It has three states, but two of them are the ones you make decisions with.
Newly available means the feature has just landed in all major engines. It works for people on up-to-date browsers, but old devices in the wild may not have it.
Widely available means it's been in all engines for 30 months. At that point you reach for it without much thought.
That 30-month gap is your decision axis. Widely available is usually a delete-today. Newly available is a delete-if-you-check-your-audience.
Before you rip anything out, run three questions on each candidate. Is the replacement Baseline-safe for my actual users, not in the abstract but per my analytics and browserslist? What does the swap actually cost, including a polyfill that might be heavier than the library it replaces? And does the native feature cover my real use case — because axios isn't just fetch, it's interceptors and cancellation and retries, and if you use those, a straight swap leaves you reimplementing them.
Now the highest-leverage cluster: internationalization. This is where the most kilobytes sit on top of features that are already Widely available.
The Intl namespace ships a whole family of formatting tools, and a lot of small, popular libraries became redundant. timeago.js (1KB gzipped) is replaced by Intl.RelativeTimeFormat. pluralize (2.3KB) by Intl.PluralRules. numeral (3.9KB) by Intl.NumberFormat. humanize-duration (6.6KB) by Intl.DurationFormat. List-joining helpers by Intl.ListFormat.
Take timeago.js. It exists to turn a timestamp into "3 hours ago." Intl.RelativeTimeFormat, which is Widely available, does the same: new Intl.RelativeTimeFormat("en", { numeric: "auto" }).format(-1, "day") gives you "yesterday" — the language's own word, not a mechanical "1 day ago."
The one thing the library does that the native call doesn't is pick the unit for you. That's a few lines of arithmetic you write once. These are delete-today candidates, because the replacements are Widely available — no audience check required.
Then there's the fresher end of the platform, where the calls are more interesting because they're recent.
Native dialog is nearly ten years old at this point. showModal() gives you a backdrop, centered positioning, Esc-to-close, and an inert page behind it — the whole modal contract. You can even close it declaratively with a form using method="dialog", no JavaScript at all. Delete-today.
The Custom Highlight API is now supported by all major browsers, which, per CSS-Tricks, lets you style ranges of text via the ::highlight() pseudo-element. Despite "CSS" in the name, JavaScript drives it.
Now the ones you check your audience for.
Gap decorations — styling the gaps between grid and flexbox items without border and pseudo-element hacks — are only in Chrome and Edge starting version 149. Other engines are engaged in standards venues but haven't shipped. This is a progressive enhancement you can start using today only if nothing breaks when it's absent. Not a delete-your-fallback move yet.
sibling-index() is the one to watch: Firefox 154 is reportedly scheduled to ship it on August 18, 2026, making it Baseline Newly available. Newly, not Widely — so it's a delete-if-you-check candidate, and you check your analytics before you lean on it.
The pattern across all of these is the same three questions applied to a different corner of the dependency tree. That's the point. The audit isn't a one-time cleanup; it's a protocol.
So name it and calendar it. The security audit already has a trigger — a CVE, a scheduled scan. The capability audit needs one too.
Tie the cadence to Baseline. Every quarter, or every time you touch package.json in anger, walk the clusters — formatting, requests, UI primitives — and for each library ask the three questions against the current Baseline state on webstatus.dev or the web-features npm package.
Widely available replacements: delete now. Newly available: delete after the audience check. Still Limited: leave it and note the date to look again.
The vendors are converging within the year. Interop 2026 launched in February with 20 focus areas and no sign of winding down. The platform will keep absorbing your dependencies whether or not you notice.
is-odd persists because no recurring moment in anyone's workflow asks it to leave. Make that moment. Put "does the browser do this now?" on the calendar, and 60 to 90KB stops being permanent.