What is actually changing in web development
Not predictions. Four shifts I have already had to design around: crawlers that do not run JavaScript, the platform absorbing dependencies, types as theβ¦
I am not going to predict anything. What follows are four shifts that have already changed how I build, in the sense that I have had to go back and modify shipped products because of them.
1. A second audience that does not run your JavaScript
For twenty years the answer to "who reads my page" was people and search engines, and search engines learned to render JavaScript. Now a meaningful share of the traffic that matters is an answer engine reading your page to summarise it β and those crawlers largely do not execute JavaScript at all.
The practical consequence is blunt: if your content only exists after hydration, it does not exist for them. A single-page app with an empty root div is invisible to the fastest-growing channel there is.
This is why I prerender everything now β real HTML per route, written at build time, with the app hydrating over it. Not server rendering, which needs a server. A post-build step that renders each route once and writes the file.
It also changes how I write. The opening sentence of every section has to answer that section's heading, standalone, because an engine lifting one sentence out needs it to make sense with no context. Writing that builds toward a point never gets quoted.
2. The platform is absorbing the dependency list
Intl replaced most of what a date library did at display time and all of what a pluralisation library did. structuredClone replaced a deep-clone helper. crypto.randomUUID replaced a package. Object.groupBy deleted a utility file from four of my projects. Container queries replaced most JavaScript-driven responsive logic. The dialog element replaced a category of modal library, at least for the simple cases.
The habit worth forming is checking the platform first. The list of things that genuinely need a dependency has got shorter every year, and every dependency removed is one fewer thing to keep current, audit and eventually migrate off.
What has not moved: rich text, charting, date arithmetic across timezones. Those are real problems and the platform has not solved them.
3. Types became the primary gate, and gates became the primary discipline
This one is less about TypeScript and more about where correctness gets enforced.
The pattern I trust now is replacing a convention with a constraint. Not "remember to paginate" but a helper whose limit is a required argument. Not "remember to use the translation layer" but a lint rule that fails the build on a hardcoded string. Not "the rebuild should match the design" but a test that parses the design's own manifest.
Each of those started as a note everybody agreed with and nobody followed β not through carelessness, but because a rule you have to remember decays, and the person who forgets is usually the person who wrote it.
The corollary nobody says out loud: watch every gate fail before trusting it. I have shipped a typecheck that exited zero on genuinely broken code because the configuration compiled nothing at all.
4. Constraints came back, and they improved the output
For a decade the answer to a hard problem was a bigger instance or another managed service. That is still available and it is still frequently right. But the free tiers got good enough that an entire product can run on them, and choosing that constraint deliberately changes the engineering in ways I did not anticipate.
A quota makes an unbounded query a production incident instead of a line item, so the read budget stops being a code-review preference and becomes architecture. No server-side compute pushes work into the browser, which is worse for old phones and genuinely better for privacy β the safest place to process someone's health data turns out to be their own device.
I am not claiming constraint is virtue. Plenty of products need a server and should have one. What I am claiming is that the constrained versions of my own products have more careful data layers than the unconstrained ones did, and the constraint is why.
What I think is overrated
Being early. I have adopted things at version 0.x and paid for it in migrations, and I have adopted things two years late and paid nothing. The cost of being late is almost always smaller than it feels.
And framework arguments. I have shipped production work in Angular, React, React Native, Laravel, Flutter and plain JavaScript, and the transfer between them is nearly total once you understand which problems each is solving. The decisions that actually determined how those projects went were about data shape, authorization and where correctness gets enforced β none of which the framework choice touched.
The part I got wrong, and expect to get wrong again
Worth including, because a piece like this is worthless without it.
I spent too long treating accessibility as a pass you do near the end. It is not a pass; it is a set of decisions made while building, and retrofitting means auditing every component for focus handling, keyboard interaction and relationships that should have been there from the first version. The work is the same size either way β it is just far more unpleasant, and far more likely to be cut, when it arrives as a task at the end of a schedule.
The same has been true of internationalisation. I have built the mechanism late twice, and both times the cost was not the mechanism β it was extracting several hundred strings from components that had grown around them.
The pattern is identical in both cases: the cheap moment is the first one, and the thing that makes it feel expensive then is that its value is invisible until much later. That is exactly the shape of decision I expect to keep getting wrong, so the only defence I have found is to make the cheap version mandatory from the start even when it looks like ceremony.
What I would tell someone starting a project this year
Decide where correctness is enforced before you decide what framework enforces it. Every project of mine that went well had that answered early β the database refuses, the types refuse, the build refuses β and every one that went badly had it answered by convention and good intentions.
Make your content readable without JavaScript, because a growing share of your most valuable audience will never run it.
And pick your constraints on purpose. The ones I chose β no servers, no recurring cost, one codebase across surfaces β have shaped my architecture more than any framework I have used, and mostly for the better. Half-choosing them would have given me the awkwardness with none of the benefit, which is the one outcome genuinely worth avoiding.
The one I would bet on
That the gap between "it builds" and "it works" keeps getting more expensive, and the teams that do well are the ones who close it with mechanisms rather than with care. Care does not survive a deadline. A gate does.
https://aoneahsan.com/blog/future-of-web-development-2026