I see the some version of "Is Angular still worth picking?" every so often, and for years my answer came with a lot of qualifiers. It depends on your team. It depends on how long the app has to live. It depends on how much you like RxJS.
That question feels different now. A meaningful amount of code is being written by agents, and the things that make a framework pleasant to type by hand are not the same things that make it safe to generate. I've been thinking about which of Angular's tradeoffs got better in that world and which ones got worse. The short version is that Angular became the safest mainstream option for agentic engineering and vibe coding, and it got there by doing what it always did rather than by chasing the moment.
Where Angular Actually Sat
Let's be honest about the starting point, because the AI part of this only makes sense if we are.
Angular was not the framework people reached for on a weekend. React won mindshare years ago and never really gave it back. Stack Overflow's 2025 survey put React at 44.7% among professional developers, Angular at 18.2%, Vue at 17.6%. State of JS 2025 noted that for all the talk of churn, the usage rankings barely moved. Angular has not been the dominant choice for a long time, but it has stayed a substantial and durable one.
The reasons are not mysterious. The AngularJS to Angular 2 rewrite burned a lot of goodwill and it took a decade for people to stop bringing it up. NgModules meant that adding a component involved editing a second file for no benefit you could explain to a newcomer. RxJS was everywhere, including in places where a plain value would have done, and the learning curve was steep enough that "I have to learn Angular and also learn reactive programming" was a real barrier. Templates had their own dialect. The CLI generated a lot of files. Builds got slow as apps got big, which I measured on a large real app recently and found was mostly the type-checker's fault, not the bundler's.
Underneath all of that was a coherent bet: optimize for large teams and long timelines, even when that costs you the first-week experience. Angular chose the boring, consistent, verbose thing on purpose. If you were one person shipping a prototype, you paid the cost and got very little of the benefit, and you noticed.
The last few years cleaned up a lot of the surface complaints. Standalone components killed NgModules. Signals gave you reactivity without needing to know what a switchMap is. Built-in control flow replaced the structural directives. Zoneless went stable. angular.dev is genuinely good documentation. Angular v22 deprecated the Webpack builder in favor of the stable esbuild and Vite builder. The framework people complain about is often the one they last used in 2019.
But cleaning up the surface didn't change the underlying bet, and that bet is the part that got interesting.
The Thing Angular Was Always Good At
Angular's actual differentiator was never templates or DI syntax. It was how much of your application Angular tries to verify before it will build.
Strict template type-checking is the big one. Angular generates a type-check block for every template, so {{ user.nmae }} is a build error, a value bound to an input() of the wrong type is a build error, and a directive you forgot to import is a build error. Not a blank spot on the page in staging. A failed build.
This is not free. When I benchmarked a real Angular app with hundreds of components four different ways, the whole-program type-check on its own was about 15 seconds, roughly as long as an entire type-check-free build. That cost is the price of the guarantee, and for most of Angular's life it was a cost people resented without ever really crediting the thing they were buying.
Dependency injection does something similar for wiring. It's declared, typed, and resolvable statically, which means a missing provider is a known failure with a known message instead of an undefined value that surfaces three components deep. HttpClient is typed. The Router is typed. The CLI generates code that already fits the shape the compiler expects.
The production-ready Signal Forms API is the clearest recent expression of that philosophy. Validation is declared as data, in one place, against a typed model:
import { Component, signal } from '@angular/core';
import { form, FormField, required, email, minLength } from '@angular/forms/signals';
interface LoginData {
email: string;
password: string;
}
@Component({
selector: 'app-login',
imports: [FormField],
template: `
<input type="email" [formField]="loginForm.email" />
<input type="password" [formField]="loginForm.password" />
`,
})
export class LoginComponent {
loginModel = signal<LoginData>({ email: '', password: '' });
loginForm = form(this.loginModel, (schemaPath) => {
required(schemaPath.email, { message: 'Email is required' });
email(schemaPath.email, { message: 'Enter a valid email address' });
required(schemaPath.password, { message: 'Password is required' });
minLength(schemaPath.password, 8, { message: 'Minimum 8 characters' });
});
}
schemaPath.email isn't a string key that gets looked up at runtime. Rename the field on LoginData and this stops compiling. There's also validateStandardSchema, which takes a Zod or Valibot schema directly, so if you already validate the same payload on the server you can share the schema instead of writing the rules twice.
That's the pattern across the whole framework: say what's true, let the compiler check it, fail at build time.
Why That Matters More With Agents
An agent writing code needs two things you don't think about when you're writing it yourself: a narrow space of correct answers, and a fast way to find out it was wrong.
Angular gives it both, and not by accident. A framework built so that a large team can safely change code it didn't write, and get told immediately when it gets that wrong, is already most of the way to a framework an agent can work in. The audience changed. The requirement didn't.
The narrow space comes from having a much smaller set of officially supported choices. One router. One DI system. One HTTP client. One project layout that ng generate produces. When a model writes an Angular component it isn't choosing between four routers and three data-fetching libraries that are all correct and all well represented in its training data. Ecosystem fragmentation is great for developers who have opinions and rough on a generator that has to guess which stack this particular repo committed to. Angular's rigidity used to be the complaint. With an agent driving, it's leverage.
The fast feedback comes from the type-checker. An agent that hallucinates an input name, binds the wrong type, or forgets to add a component to imports finds out from ng build, in a message that names the file and line. That's a loop it can close by itself. The failure mode I actually worry about with generated code is the plausible-looking thing that runs and is subtly wrong, and template type-checking eats a whole category of exactly that. That 15-second cost buys an automated reviewer that never gets tired.
Angular's decade of changing conventions creates the opposite problem: its training data contains several incompatible eras. Ask for a component and you'll still get NgModule declarations, constructor injection, *ngIf, and a manual subscribe in ngOnInit, all of which work and none of which is how you'd write it today. More than with other frameworks I use, I have to tell the model which era of Angular to target. That's a real tax, and it's the tax Angular is now paying down with tooling rather than hoping models catch up.
Vibe Coders Building Safely
Everything above assumes you're reading the code. Plenty of people aren't right now, at least not closely, and I don't think that's automatically a bad way to work. It does change what you should want from a framework.
If you aren't reading closely, the question stops being how nice the code is to write. It becomes what the framework refuses to let through. The bug you can't catch by skimming is the one that only shows up on a page you didn't click, and Angular turns a lot of those into a failed build instead. A failed build is hard to ignore.
So the advice is boring: run the build, and run it often. It's the cheapest review you have. Angular publishes a setup for AI editors that points your agent at the current docs and lets it read its own build errors, and it's worth the few minutes it takes.
Set that up, because the model's idea of Angular is a few years out of date. It will write things the old way, that code still works, and nothing warns you. You find out much later, when you add something modern and the two styles don't fit together. Tell it which version you're on, and ask for signals and standalone components by name.
A passing build means your code holds together, not that it does what you wanted. The compiler catches the typo, never the wrong feature. Building the right thing is still your job.
That's a trade I'd take. Every framework lets you vibe. Angular is the one checking your work while you do it.
What the Roadmap Says
The Angular roadmap is unusually direct about this. It lists three goals for the framework, and the first one is improving the AI experience for developers. Then developer experience, then performance.
Most of that already exists. The editor setup I mentioned above is built on an MCP server that ships in the CLI and a set of official agent skills, and there's an AI tutor and WebMCP to experiment with alongside them. The roadmap also commits to evaluating code generation quality and changing the framework itself where that improves it. "We'll change APIs so models generate better code" is a different posture than "we'll write better docs."
The performance work matters for the same loop. The team is prototyping compatibility with Microsoft's TypeScript port to Go, which the roadmap describes as a 5 to 10 times speedup for typical TypeScript compilation. Angular's compiler wraps the TypeScript program directly, so when the solution lands for template type-checking, the expensive guarantee gets a lot cheaper. Even a fraction of that number changes how often you're willing to run a full check.
So Should You Choose Angular?
If you're building something that has to survive team turnover, if you want validation rules in one typed place instead of scattered through components, if you'd rather a mistake in a template be a failed build than a support ticket, Angular's tradeoffs make more sense today than they did five years ago. You didn't have to change your mind about anything. The cost of ceremony went down when signals and standalone components landed, and the value of enforced correctness went up when a machine started writing the first draft.
If you're already fast in another ecosystem and you read everything you ship, none of this is an argument to switch. It never was.
"AI likes it" is a depressing pitch for a framework, and it isn't the pitch. Angular spent a decade making the compiler prove things about your code and took real criticism for what that cost. That was a deliberate bet on correctness over convenience, made by people who were solving for large teams and long-lived code, not for agents. It's the same bet either way. Angular was built for codebases where no one person could review every change, and agent-generated code is that same problem arriving faster.
So if you're going to let a machine write most of it, write it somewhere that argues back. That's the case for Angular right now. Not that it makes you faster, but that it makes being fast less dangerous.
If you enjoyed this post, click the ❤️ so other people will see it. Follow AnalogJS and Brandon Roberts on Bluesky!



Top comments (0)