The core idea
Separate exploration from hardening.
Instead of using a frontend framework to discover what the application should be, establish the behavior first. Treat the vanilla frontend as a POC and discovery spike against the backend contract, not as a finished product — the framework then becomes a production migration target, and migration is also where the production design system gets applied. Converting a working first-principles prototype into that design system, rather than asking an agent to write directly in the framework from scratch, is what surfaces the framework's own gaps and keeps the agent from misusing its patterns.
At a glance
The AI SDLC as a reference-first workflow
FastAPI owns the domain. The vanilla frontend makes browser behavior explicit. Coding agents then migrate that behavior into a constrained production target — including the production design system itself, which is where framework and component-library deficiencies actually surface.
FastAPI application
DDD / bounded contexts
Explicit API contracts
Business logic
HTML + CSS + Vanilla JS
Minimal dependencies
Explicit browser/API edges
Executable specification
Translate behavior
Apply production design system
Preserve contracts and tests
Surface framework gaps
Same behavioral tests • security analysis • dependency governance • CDN-ready frontend
Framework comparison
Fit for vanilla → framework migration
Architectural assessment for a FastAPI/DDD application using a vanilla reference frontend. Scores are comparative judgments, not benchmark measurements.
| Criterion | Vanilla seed | Next.js | Nuxt | Angular |
|---|---|---|---|---|
| Rapid prototype | ★★★★★ | ★★★ | ★★★★ | ★★ |
| Explicit browser behavior | ★★★★★ | ★★★ | ★★★★ | ★★★ |
| Easy for agent to understand | ★★★★★ | ★★★ | ★★★★ | ★★★★ |
| Migration from vanilla | — | ★★★★ | ★★★★½ | ★★★ |
| Framework security defaults | ★★ | ★★★★ | ★★★★ | ★★★★★ |
| Architectural enforcement | ★ | ★★★ | ★★★★ | ★★★★★ |
| DDD compatibility | ★★★★★ | ★★★★ | ★★★★ | ★★★★★ |
| Minimal-package potential | ★★★★★ | ★★★ | ★★★★ | ★★★★ |
| Static/CDN deployment | ★★★★★ | ★★★★★ | ★★★★★ | ★★★★★ |
| Full-stack capability | — | ★★★★★ | ★★★★★ | ★★★★ |
| Framework complexity | Very low | High | Medium | High |
| Agent migration determinism | — | Medium | High | High |
| Long-term structural consistency | Depends on you | Medium | High | Very high |
These are architectural assessments for this workflow, not measured benchmark scores.
The argument
Start with the domain, not the framework
Modern frontend development often begins with a framework decision: React or Vue, Next.js or Nuxt, Angular, a state manager, a component library, and then another layer of packages around those choices.
For a FastAPI application with well-defined domain boundaries, that can be the wrong place to begin.
Let FastAPI own application behavior
Domain-driven design makes a much simpler starting point possible. FastAPI can own application services, business rules, persistence, integrations, and explicit API contracts. The frontend then becomes a presentation implementation consuming those contracts.
The vanilla frontend is not necessarily throwaway code
A working HTML, CSS, and vanilla JavaScript implementation can capture expected browser behavior, DOM interactions, API calls, accessibility expectations, and regression tests. It becomes a specification that runs.
That changes the coding-agent task. Instead of asking an agent to design and implement an application in a framework at the same time, the agent can be asked to reproduce known behavior while preserving contracts, tests, architectural boundaries, and dependency constraints.
The reference frontend is also a UI/UX handoff artifact
A working vanilla prototype does more than prove the backend contract — it's something a designer or UI/UX engineer can actually pick up and treat as a starting point instead of a description of one. That handoff used to be lossy: a static mockup, or a prototype built in a different tool entirely, still had to be reimplemented from scratch by engineering, so the prototype's only real job was communication, never code.
A running, contract-backed vanilla frontend changes that. Branding, A/B testing different content flows, and optimizing a sales funnel can all happen directly against real, working behavior instead of a description of it. That's the actual handoff point between a POC and discovery spike on the backend and the frontend polish that creates the experience an end user is meant to have.
That first-principles constraint has a second effect worth naming directly: it changes what happens when a coding agent later converts the prototype into a production design system — Tailwind, a component library, whatever the target stack standardizes on. Asked to write directly in that design system from scratch, with no first-principles reference to build against, an agent has no concrete ground truth for what the interface is actually supposed to do, so it improvises within the framework's own idioms — and the result is often technically valid CSS that's still structurally inconsistent and hard to untangle later. Migrating a working vanilla prototype instead gives the agent a known-correct target to reconcile against the design system's real capabilities. That reconciliation is exactly where a design system's own gaps surface, and where the agent is least likely to misuse its patterns, because the migration doesn't get thrown away at the framework boundary the way a design mockup usually would — it's the same deterministic-migration property, applied to CSS instead of behavior.
Coding agents change the economics of framework structure
Framework boilerplate historically represented developer time. In an agent-assisted SDLC, the agent can absorb much of that repetitive translation cost. Framework structure can therefore become useful as a production constraint rather than a tax paid during early experimentation.
Optional detail
Open only what you need
The central argument above stands on its own. The sections below contain implementation details, framework tradeoffs, and DevSecOps considerations for readers who want to go deeper.
01 Next.js — the React product target
Next.js remains a strong destination when React itself provides meaningful product value: its component ecosystem, sophisticated composition, server rendering, static generation, or React Server Components.
Vanilla Next.js
HTML → JSX
DOM events → React events
JavaScript state → React state
fetch() → data fetching
pages → routes / layouts
functions → components / hooks
The architectural concern in a FastAPI application is backend duplication.
Preferred:
FastAPI
↓
API contract
↓
Next presentation
Possible drift:
FastAPI
↕
Next server
↕
React client
If FastAPI owns the domain and application layers, that boundary should remain explicit during migration. Next server capabilities should not quietly become a second implementation of the backend simply because the framework makes them convenient.
02 Nuxt — possibly the most natural migration target
Nuxt becomes particularly interesting when the reference implementation already uses HTML, CSS, JavaScript, and Vite.
HTML → template
CSS → style
JavaScript → script setup
The conceptual translation from ordinary HTML into Vue templates is relatively direct.
PROTOTYPE
HTML
CSS
JavaScript
Vite
↓ agent migration
PRODUCTION
Vue
Nuxt
Vite
Nitro
The architecture becomes more capable without replacing every part of the development toolchain. This smaller conceptual distance may also make automated migrations easier to reason about and review.
03 Angular — the hardening target
Angular presents a different proposition. It is not being selected because it makes initial experimentation faster. It is interesting because a coding agent can translate an already-understood application into a more constrained production representation.
DRAFT
│
▼
HTML / CSS / Vanilla JS
│
▼
Behavior works
│
▼
Contracts stabilize
│
▼
HARDEN
│
┌───────┴────────┐
│ │
Angular DevSecOps
│ │
strict TS SAST
templates SBOM
structure dependency scan
DI security tests
│ │
└───────┬────────┘
▼
RELEASE
Strict TypeScript, dependency injection, structured conventions, template security mechanisms, and recognizable escape hatches become more interesting when an agent is paying much of the boilerplate cost.
04 Make dangerous code obvious
Agent-generated code introduces a useful DevSecOps opportunity: constructs that cross sensitive security boundaries can become explicit review triggers rather than ordinary generated code.
bypassSecurityTrustHtml
bypassSecurityTrustScript
bypassSecurityTrustStyle
bypassSecurityTrustUrl
bypassSecurityTrustResourceUrl
innerHTML
direct DOM manipulation
dynamic template construction
unsafe-inline CSP
new third-party dependency
The presence of one of these constructs does not automatically mean the implementation is wrong. It means the implementation crossed a boundary that warrants additional inspection.
Agent migration
│
▼
Framework build
│
▼
AST / policy analysis
│
▼
Security escape hatch?
│
┌──┴──┐
│ │
NO YES
│ │
▼ ▼
continue review
05 Package count is a security decision
Framework security and software supply-chain security are different problems. A secure framework underneath a large set of unnecessary transitive dependencies does not automatically produce a secure application.
Review:
vulnerability history
maintainer health
transitive dependencies
install scripts
license
actual necessity
The objective is not zero dependencies. The objective is
intentional dependencies. npm install becomes a
small architectural decision instead of the automatic first
response to a missing capability.
06 Test the migration, not the framework
The reference implementation makes it possible to evaluate these frameworks using the actual development methodology rather than generic framework rankings.
Vanilla Reference
│
┌────────────┼────────────┐
▼ ▼ ▼
Next.js Nuxt Angular
│ │ │
└────────────┼────────────┘
▼
Measurements
The same moderately complicated vanilla feature can be migrated into each target using the same rules and behavioral tests. The result provides evidence about which architecture best fits the actual SDLC.
07 Frameworks as compilation targets
There is a larger idea underneath this workflow. Coding agents may change the role of application frameworks.
Human + agent exploration
HTML
CSS
JavaScript
HTTP
FastAPI
↓
behavioral contract
↓
migration agent
↓
┌────────────┬────────────┬────────────┐
│ │ │ │
▼ ▼ ▼ │
Next.js Nuxt Angular │
React Vue strict TS │
RSC Vite structure │
ecosystem Nitro sanitization │
│ │ │ │
└────────────┴─────┬──────┴────────────┘
▼
verification
│
▼
release
Complexity during exploration can obscure the problem because the developer is simultaneously trying to understand the product and satisfy a framework.
Complexity during hardening can be useful when that complexity represents explicit constraints that can be automatically verified.
The 2026 mindset
Prototype for understanding. Migrate for production. Verify the difference.
The best framework may depend not only on what application is being built, but on where in the software-development lifecycle the framework enters the system. HTML, CSS, JavaScript, HTTP, and FastAPI can remain powerful tools for discovering behavior, with branding, A/B testing, and sales-funnel decisions made directly against that proven behavior instead of a static mockup; and Next.js, Nuxt, and Angular can become increasingly constrained migration targets — the same migration step that applies the production design system and surfaces where it falls short.
Dependency-free HTML/CSS article — native browser
<details> elements provide progressive disclosure
without adding a JavaScript package.