Why Custom Software Shouldn't Reinvent What the Browser Already Does
Some custom features are quietly rebuilding things a browser already does natively. Here's where that shows up in a quote, and when it's genuinely worth paying for the custom version.
There's a long-running argument among developers about whether to reach for a library or just "use the platform". Browsers already do a lot: date pickers, file drag-and-drop, form validation, offline caching, print layouts. A lot of software rebuilds these things from scratch anyway, in JavaScript, with a dependency that needs updating forever. You don't see that argument, but you pay for it.
I'm not writing this to relitigate a developer forum debate. I'm writing it because the same pattern shows up in client work, and it's worth knowing about before you sign off a quote.
Where this shows up in a real build
A few places I see it most often:
- Date and time pickers. Browsers have had a native date input for years. It works on mobile, it's accessible by default, and it costs nothing to add. A custom calendar widget can look nicer, but it's also another component to style, test on every device, and fix when it breaks.
- File uploads. Drag-and-drop, multiple file selection and progress feedback are all things the platform handles natively. Plenty of upload components get built as if none of that exists.
- Form validation. Required fields, email formats and number ranges can be checked by the browser before a line of custom code runs. I still see forms where every one of those checks is reimplemented in JavaScript, badly, with none of the built-in accessibility messaging.
- Print layouts. A dedicated print stylesheet can turn an invoice or report into something that prints cleanly, for the cost of a bit of CSS. Instead, some builds generate a PDF via a separate service for every print job, which is slower and costs money every time it runs.
- Offline access. If someone wants an app that works without signal, a progressive web app can cache pages and data for offline use without the cost of a native app build. I cover that properly on the progressive web app side of things, because it's a genuinely different decision to a custom native-feeling component that just pretends to work offline and silently fails.
Why it happens
Usually it's not laziness, it's habit. A developer learns one way of building a date picker early on, reuses it everywhere, and never checks whether the platform caught up. Design tools make it easy to spec a custom-looking component without anyone checking what it would take to build to match it exactly.
AI-generated code makes this worse in a specific way. Ask an AI assistant to "add a file upload" and it will often reach straight for a library and a chunk of custom state management, because that's what most training examples look like, even when three lines of native HTML would do the same job with less code to maintain. If you've had a prototype built this way and you're weighing up whether to take it further, that's exactly the kind of thing I look for when I turn an AI-built prototype into something production-ready: not just whether it works, but whether it's carrying weight it doesn't need to.
What it actually costs you
None of this is really about elegance. It's about what you end up paying for, long after launch.
- More code to maintain. A custom component is something I have to keep working across browser updates. A native feature is maintained by the browser vendor, for free, forever.
- Worse accessibility by default. Native form elements come with screen reader support and keyboard navigation built in. Recreate them badly and you've quietly locked out some users, which can also be a legal problem depending on who you sell to.
- Slower pages. Every library pulled in to replace something native adds to what a browser has to download and run before the page is usable. On a slow connection or an older phone, that's the difference between a page loading in a second and someone giving up.
- More places for bugs to hide. A native date input behaves the same on every device that supports it. A custom one has to be tested on each one separately, and edge cases turn up for years.
When custom is genuinely worth it
This isn't a case for never building anything custom. Plenty of good reasons exist to go beyond what the platform offers:
- A booking calendar that needs to show availability across staff, locations and time zones at once. No native input does that.
- A multi-step form with conditional logic, saved progress and validation rules specific to your business, not just "is this a valid email".
- A branded experience where consistency across every device matters more than using the fastest route to a working feature.
The difference is that these are cases where the business logic is doing something the platform genuinely can't. That's a fair reason to build custom. "It doesn't look quite right" on a native control usually isn't, not on its own.
What to ask before you pay for it
If a quote includes a custom version of something that sounds ordinary, like a date picker, a file upload or a search box, it's worth asking a simple question: what does this do that the built-in version can't? If the honest answer is "nothing, it just looks different", that's a fair trade-off to make consciously, as long as you know you're also signing up to maintain it. If there's no clear answer at all, it's worth a second look. This is the kind of detail that's easy to miss in a brief but makes a real difference to what you end up owning, which is part of why I always talk through the specifics of a brief properly before any work starts.