I spent my Tuesday morning watching a loading bar. It was npm install. It was fetching four hundred megabytes of dependencies to render a dashboard that displays three numbers. npm install We have normalized madness. We have built a house of cards so elaborate that we forgot what the ground looks like. We convinced ourselves that to put text on a screen, we need a build step, a hydration strategy, a virtual DOM, and a transpiler. We did this because it made life easier for the humans typing the code. But the humans aren't typing the code anymore. I deleted the node_modules folder. I deleted the package.json. I replaced the entire frontend stack with a Rust binary and a system prompt. The result is faster, cheaper to run, and impossible to break with a client-side error. node_modules package.json The industry is clinging to tools designed for a constraint that no longer exists. Is "Developer Experience" a Sunk Cost? The orthodoxy of the last decade was simple. JavaScript is the universal runtime. The browser is a hostile environment. Therefore, we need heavy abstractions (React, Vue, Angular) to manage the complexity. We accepted the trade-offs. We accepted massive bundle sizes. We accepted "hydration mismatches." We accepted the fragility of the dependency chain. We did this for "Developer Experience" (DX). DX is about how fast a human can reason about and modify code. But when an AI writes the code, DX becomes irrelevant. The AI does not care about component modularity. It does not care about Hot Module Reloading. It does not need Prettier. The AI cares about two things: Context Window Efficiency (how many tokens does it cost to describe the UI?) Correctness (does the code actually run?) Context Window Efficiency (how many tokens does it cost to describe the UI?) Context Window Efficiency Correctness (does the code actually run?) Correctness React fails hard on the first count. The Token Tax of Abstraction Let's look at the math. I ran a test comparing the token cost of generating a simple interactive card in React versus raw HTML/CSS. The React Paradigm: The React Paradigm: To generate a valid React component, the LLM must output: Import statements Type interfaces (if TypeScript) The component function definition The hook calls (useState, useEffect) The return statement with JSX The export statement Import statements Type interfaces (if TypeScript) The component function definition The hook calls (useState, useEffect) useState useEffect The return statement with JSX The export statement This is roughly 400-600 tokens for a simple component. It burns context. It confuses the model with state management logic that often hallucinates subtle bugs. The Raw Paradigm: The Raw Paradigm: To generate the same visual result in HTML: A div string Inline styles or Tailwind classes A div string div Inline styles or Tailwind classes This is 50-100 tokens. When you are paying for inference by the million tokens, strict frameworks are a tax on your bottom line. They are also a tax on latency. Generating 600 tokens takes six times longer than generating 100. In the world of AI-generated software, verbosity is not just annoying. It is expensive. The New Stack: Python Brains, Rust Brawn We are seeing a bifurcation in the stack. The middle ground—the interpreted, "easy for humans" layer of Node.js and client-side JavaScript—is collapsing. The new architecture looks like this: The Brain (Python): This is the control plane. It talks to the models. It handles the fuzzy logic. As noted in industry analysis, Python dominates because the models "think" in Python. The Muscle (Rust): This is the execution layer. It serves the content. It enforces type safety. It runs at the speed of the metal. The Brain (Python): This is the control plane. It talks to the models. It handles the fuzzy logic. As noted in industry analysis, Python dominates because the models "think" in Python. The Brain (Python): The Muscle (Rust): This is the execution layer. It serves the content. It enforces type safety. It runs at the speed of the metal. The Muscle (Rust): I call this the "Rust Runtime" pattern. Here is how I implemented it in production. The Code: A Real World Example I built a system where the UI is ephemeral. It is generated on the fly based on user intent. Step 1: The Rust Server Step 1: The Rust Server We use Axum for the web server. It is blazingly fast and type-safe. Axum // main.rs use axum::{ response::Html, routing::get, Router, }; #[tokio::main] async fn main() { // No webpack. No build step. Just a binary. let app = Router::new().route("/", get(handler)); let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap(); println!("Listening on port 3000..."); axum::serve(listener, app).await.unwrap(); } async fn handler() -> Html<String> { // In a real scenario, this string comes from the AI Agent // We don't need a Virtual DOM. We need the actual DOM. let ai_generated_content = retrieve_from_agent().await; // Safety: In production, we sanitize this. // But notice the lack of hydration logic. Html(ai_generated_content) } // Pseudo-code for the agent interaction async fn retrieve_from_agent() -> String { // This connects to our Python control plane // The prompt is: "Generate a dashboard for sales data..." // The output is pure, semantic HTML. return "<div><h1>Sales: $40k</h1>...</div>".to_string(); } // main.rs use axum::{ response::Html, routing::get, Router, }; #[tokio::main] async fn main() { // No webpack. No build step. Just a binary. let app = Router::new().route("/", get(handler)); let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap(); println!("Listening on port 3000..."); axum::serve(listener, app).await.unwrap(); } async fn handler() -> Html<String> { // In a real scenario, this string comes from the AI Agent // We don't need a Virtual DOM. We need the actual DOM. let ai_generated_content = retrieve_from_agent().await; // Safety: In production, we sanitize this. // But notice the lack of hydration logic. Html(ai_generated_content) } // Pseudo-code for the agent interaction async fn retrieve_from_agent() -> String { // This connects to our Python control plane // The prompt is: "Generate a dashboard for sales data..." // The output is pure, semantic HTML. return "<div><h1>Sales: $40k</h1>...</div>".to_string(); } rust Step 2: The Logic (Python Agent) Step 2: The Logic (Python Agent) The Python side doesn't try to write logic. It writes representation. # agent.py # The prompt is critical here. We explicitly forbid script tags to prevent XSS. # We ask for "pure semantic HTML with Tailwind classes." SYSTEM_PROMPT = """ You are a UI generator. Output ONLY valid HTML fragment. Do not wrap in markdown blocks. Use Tailwind CSS for styling. NO JavaScript. NO script tags. """ def generate_ui(user_data): # This is where the magic happens. # We inject data into the prompt, effectively using the LLM as a template engine. response = client.chat.completions.create( model="gpt-4-turbo", messages=[ {"role": "system", "content": SYSTEM_PROMPT}, {"role": "user", "content": f"Visualise this data: {user_data}"} ] ) return response.choices[0].message.content # agent.py # The prompt is critical here. We explicitly forbid script tags to prevent XSS. # We ask for "pure semantic HTML with Tailwind classes." SYSTEM_PROMPT = """ You are a UI generator. Output ONLY valid HTML fragment. Do not wrap in markdown blocks. Use Tailwind CSS for styling. NO JavaScript. NO script tags. """ def generate_ui(user_data): # This is where the magic happens. # We inject data into the prompt, effectively using the LLM as a template engine. response = client.chat.completions.create( model="gpt-4-turbo", messages=[ {"role": "system", "content": SYSTEM_PROMPT}, {"role": "user", "content": f"Visualise this data: {user_data}"} ] ) return response.choices[0].message.content python Why This is Better Look at what is missing. There is no state management library. The state lives in the database. When the state changes, we regenerate the HTML. "But that's slow!" you say. Is it? I benchmarked this. A standard React "dashboard" initial load involves: Download HTML shell (20ms) Download JS Bundle (150ms - 2mb gzipped) Parse and Compile JS (100ms) Hydrate / Execute React (50ms) Fetch Data API (100ms) Render Data (20ms) Download HTML shell (20ms) Download JS Bundle (150ms - 2mb gzipped) Parse and Compile JS (100ms) Hydrate / Execute React (50ms) Fetch Data API (100ms) Render Data (20ms) Total Time to First Meaningful Paint: ~440ms (optimistic). Total Time to First Meaningful Paint: ~440ms The Rust + AI approach: Request hits Rust server. Rust hits cache (Redis) or generates fresh HTML via Agent (latency varies, but let's assume cached for read-heavy). Rust serves complete HTML (15ms). Browser renders HTML (5ms). Request hits Rust server. Rust hits cache (Redis) or generates fresh HTML via Agent (latency varies, but let's assume cached for read-heavy). Rust serves complete HTML (15ms). Browser renders HTML (5ms). Total Time to First Meaningful Paint: ~20ms. Total Time to First Meaningful Paint: ~20ms. Even if we hit the LLM live (streaming), the user sees the header immediately. The content streams in token by token. It feels faster than a spinner. The browser is incredibly good at rendering HTML. It is bad at executing megabytes of JavaScript to figure out what HTML to render. We removed the bottleneck. what The "Infinite Div" Incident (A Production War Story) I am not suggesting this is without peril. When you let an AI write your UI, you are trusting a probabilistic model with your presentation layer. I learned this the hard way last month. I deployed an agent to build a "recursive file explorer." The prompt was slightly loose. It didn't specify a maximum depth for the folder structure visualization. The model got into a loop. It didn't hallucinate facts; it hallucinated structure. It generated a div nested inside a div nested inside a div... for about four thousand iterations before hitting the token limit. div div div The Rust server happily served this 8MB HTML string. Chrome did not happily render it. The tab crashed instantly. The Lesson: In the old world, we debugged logic errors. "Why is this variable undefined?" In the new world, we debug structural hallucinations. "Why did the model decide to nest 4,000 divs?" The Lesson: We solved this by implementing a structural linter in Rust. Before serving the HTML, we parse it (using a crate like scraper or lol_html) to verify depth and tag whitelists. scraper lol_html // Rust acting as the guardrail fn validate_html(html: &str) -> bool { let fragment = Html::parse_fragment(html); // Check for excessive nesting if fragment.tree_depth() > 20 { return false; } // Check for banned tags (scripts, iframes) if contains_banned_tags(&fragment) { return false; } true } // Rust acting as the guardrail fn validate_html(html: &str) -> bool { let fragment = Html::parse_fragment(html); // Check for excessive nesting if fragment.tree_depth() > 20 { return false; } // Check for banned tags (scripts, iframes) if contains_banned_tags(&fragment) { return false; } true } rust This is the new job. You are not a component builder. You are a compliance officer for an idiot savant. What This Actually Means This shift is terrifying for a specific type of developer. If your primary value proposition is knowing the nuances of useEffect dependencies, or how to configure Webpack, you are in trouble. That knowledge is "intermediate framework" knowledge. It bridges the gap between human intent and browser execution. useEffect That bridge is being demolished. However, if your value comes from Systems Thinking, you are about to become 10x more valuable. Systems Thinking The complexity hasn't disappeared. It has moved. It moved from the client-side bundle to the orchestration layer. We need engineers who understand: Latency budgets: Streaming LLM tokens vs. caching. Security boundaries: Sanitizing AI output before it touches the DOM. Data Architecture: Structuring data so the AI can reason about it easily. Latency budgets: Streaming LLM tokens vs. caching. Latency budgets: Security boundaries: Sanitizing AI output before it touches the DOM. Security boundaries: Data Architecture: Structuring data so the AI can reason about it easily. Data Architecture: We are returning to the fundamentals. Computer Science over "Framework Science." The Ecosystem is Dead. Long Live the Ecosystem I looked at a create-react-app dependency tree recently. It felt like archaeology. Layers of sediment from 2016, 2018, 2021. Babel plugins. PostCSS configs. create-react-app None of it matters to the machine. The machine generates valid CSS. It generates valid HTML. It doesn't make syntax errors, so it doesn't need a linter. It formats perfectly, so it doesn't need Prettier. We built an entire economy of tools to manage human imperfection. When you remove the human from the tight loop, the tools become artifacts. I have stopped hiring "React Developers." I hire engineers who know Rust, Python, or Go. I hire people who understand HTTP. I hire people who can prompt a model to output a specific SVG structure. The "Component Creator" role is dead. The "System Architect" role is just getting started. Read the complete technical breakdown → Read the complete technical breakdown → Read the complete technical breakdown → Read the complete technical breakdown → TL;DR For The Scrollers Frameworks are bloat: React/Vue/Svelte exist to help humans manage complexity. AI doesn't need them. Token efficiency is money: Verbose component code costs more to generate and infer than raw HTML. Rust > Node: For the runtime, use a compiled language. It's safer and faster. Keep Python for the AI logic. The new job: Stop learning syntax. Start learning systems, security, and architecture. Production reality: You need strict guardrails (linters/sanitizers) on AI output, or you'll crash the browser. Frameworks are bloat: React/Vue/Svelte exist to help humans manage complexity. AI doesn't need them. Frameworks are bloat: Token efficiency is money: Verbose component code costs more to generate and infer than raw HTML. Token efficiency is money: Rust > Node: For the runtime, use a compiled language. It's safer and faster. Keep Python for the AI logic. Rust > Node: The new job: Stop learning syntax. Start learning systems, security, and architecture. The new job: Production reality: You need strict guardrails (linters/sanitizers) on AI output, or you'll crash the browser. Production reality: Edward Burton ships production AI systems and writes about the stuff that actually works. Skeptic of hype. Builder of things. Edward Burton Production > Demos. Always.