<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: bunzzeok</title>
    <description>The latest articles on DEV Community by bunzzeok (@bunzzeok).</description>
    <link>https://dev.to/bunzzeok</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1189204%2Fe8f5ef58-e5e6-4fea-a543-880e4c7e07c4.png</url>
      <title>DEV Community: bunzzeok</title>
      <link>https://dev.to/bunzzeok</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bunzzeok"/>
    <language>en</language>
    <item>
      <title>Can a Compiler-First Framework Scale to Real Apps Without Reinventing React?</title>
      <dc:creator>bunzzeok</dc:creator>
      <pubDate>Sat, 22 Aug 2026 11:26:05 +0000</pubDate>
      <link>https://dev.to/bunzzeok/can-a-compiler-first-framework-scale-to-real-apps-without-reinventing-react-g8d</link>
      <guid>https://dev.to/bunzzeok/can-a-compiler-first-framework-scale-to-real-apps-without-reinventing-react-g8d</guid>
      <description>&lt;p&gt;A few weeks ago, I wrote about &lt;strong&gt;Kudzu&lt;/strong&gt;, an open-source compiler-first web framework that lets you write familiar React-shaped TypeScript/TSX without shipping React, a VDOM, or hydration by default.&lt;/p&gt;

&lt;p&gt;The original idea is straightforward:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;write familiar TSX&lt;/li&gt;
&lt;li&gt;analyze components, state, events, lists, effects, and dependencies at build time&lt;/li&gt;
&lt;li&gt;emit complete HTML&lt;/li&gt;
&lt;li&gt;ship only the JavaScript capabilities a page actually needs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That part works.&lt;/p&gt;

&lt;p&gt;But I think the more interesting problem starts after that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Static pages were never the hard part
&lt;/h2&gt;

&lt;p&gt;A compiler can make a static page extremely small.&lt;/p&gt;

&lt;p&gt;That does not automatically make it a serious application framework.&lt;/p&gt;

&lt;p&gt;The real question is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can Kudzu grow into something capable of building large, long-lived applications without eventually recreating the same generic runtime model it was designed to remove?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By “real applications,” I mean things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;shared application state&lt;/li&gt;
&lt;li&gt;async/server data&lt;/li&gt;
&lt;li&gt;loading and error states&lt;/li&gt;
&lt;li&gt;cache invalidation&lt;/li&gt;
&lt;li&gt;optimistic mutations&lt;/li&gt;
&lt;li&gt;complex forms&lt;/li&gt;
&lt;li&gt;nested routing&lt;/li&gt;
&lt;li&gt;authentication and permissions&lt;/li&gt;
&lt;li&gt;realtime updates&lt;/li&gt;
&lt;li&gt;large lists and virtualization&lt;/li&gt;
&lt;li&gt;editors&lt;/li&gt;
&lt;li&gt;charts and maps&lt;/li&gt;
&lt;li&gt;code splitting&lt;/li&gt;
&lt;li&gt;long-lived application state&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If Kudzu cannot handle those well, then it risks ending up as a very good static-site compiler with some interactivity.&lt;/p&gt;

&lt;p&gt;That is not the goal.&lt;/p&gt;

&lt;h2&gt;
  
  
  The goal is not zero JavaScript
&lt;/h2&gt;

&lt;p&gt;This distinction matters.&lt;/p&gt;

&lt;p&gt;I do &lt;strong&gt;not&lt;/strong&gt; think a serious web application should avoid client-side JavaScript at all costs.&lt;/p&gt;

&lt;p&gt;A dashboard may genuinely need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;shared state&lt;/li&gt;
&lt;li&gt;navigation&lt;/li&gt;
&lt;li&gt;server data&lt;/li&gt;
&lt;li&gt;caching&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A chat application may genuinely need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;WebSocket connections&lt;/li&gt;
&lt;li&gt;keyed lists&lt;/li&gt;
&lt;li&gt;lifecycle management&lt;/li&gt;
&lt;li&gt;optimistic updates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An editor may need a substantial JavaScript library.&lt;/p&gt;

&lt;p&gt;That is fine.&lt;/p&gt;

&lt;p&gt;The goal is not:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;zero JavaScript&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The goal is closer to:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;zero JavaScript that exists only because the framework needs it&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A static route might ship almost nothing.&lt;/p&gt;

&lt;p&gt;A complex application route might ship much more.&lt;/p&gt;

&lt;p&gt;But that code should correspond to capabilities the application actually uses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where I do not want Kudzu to go
&lt;/h2&gt;

&lt;p&gt;There are two easy ways to make compatibility grow quickly.&lt;/p&gt;

&lt;p&gt;I think both are dangerous.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Rebuild React underneath Kudzu
&lt;/h3&gt;

&lt;p&gt;The simplest escape hatch would be to add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a generic component tree&lt;/li&gt;
&lt;li&gt;VDOM reconciliation&lt;/li&gt;
&lt;li&gt;hydration&lt;/li&gt;
&lt;li&gt;a generic rerender loop&lt;/li&gt;
&lt;li&gt;a React-compatible fallback runtime&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That would make more React code easier to support.&lt;/p&gt;

&lt;p&gt;But it would also erase much of the reason Kudzu exists.&lt;/p&gt;

&lt;p&gt;The architecture I want to preserve is closer to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;state change
    ↓
known dependency
    ↓
specific DOM / resource / list update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;instead of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;state change
    ↓
component rerender
    ↓
virtual tree
    ↓
diff
    ↓
DOM update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Add endless compiler special cases
&lt;/h3&gt;

&lt;p&gt;The other failure mode is less obvious.&lt;/p&gt;

&lt;p&gt;It looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;React Router special case
→ Zustand special case
→ TanStack Query special case
→ React Hook Form special case
→ MUI special case
→ browser API special case
→ ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That may work for a while.&lt;/p&gt;

&lt;p&gt;But eventually the compiler becomes a catalog of package-specific syntax patterns.&lt;/p&gt;

&lt;p&gt;Then users are no longer writing normal React-shaped code.&lt;/p&gt;

&lt;p&gt;They are writing:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“the specific shape Kudzu happens to understand”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is also a problem, especially for AI-assisted development.&lt;/p&gt;

&lt;p&gt;If an AI agent constantly has to read compiler limitations, rewrite source into special forms, retry builds, and search framework docs, the token savings disappear.&lt;/p&gt;

&lt;h2&gt;
  
  
  The direction I am exploring
&lt;/h2&gt;

&lt;p&gt;The architecture I am currently leaning toward has three layers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;React / npm ecosystem source
            ↓
compatibility / normalization
            ↓
small Kudzu application model
            ↓
compiler
            ↓
HTML + only required runtime capabilities
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important part is the middle.&lt;/p&gt;

&lt;p&gt;Kudzu needs a small set of application capabilities that are powerful enough to build serious applications.&lt;/p&gt;

&lt;p&gt;Not hundreds of framework-specific features.&lt;/p&gt;

&lt;p&gt;Something closer to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;local state&lt;/li&gt;
&lt;li&gt;shared state&lt;/li&gt;
&lt;li&gt;derived values&lt;/li&gt;
&lt;li&gt;events&lt;/li&gt;
&lt;li&gt;async resources&lt;/li&gt;
&lt;li&gt;mutations&lt;/li&gt;
&lt;li&gt;navigation&lt;/li&gt;
&lt;li&gt;keyed/owned DOM ranges&lt;/li&gt;
&lt;li&gt;lifecycle&lt;/li&gt;
&lt;li&gt;external UI instances&lt;/li&gt;
&lt;li&gt;lazy capabilities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The exact list is still something I am working through.&lt;/p&gt;

&lt;p&gt;The goal is that a small number of primitives can be composed into many different applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  What about third-party libraries?
&lt;/h2&gt;

&lt;p&gt;I do not think Kudzu should try to compile the internals of every library.&lt;/p&gt;

&lt;p&gt;Some packages should simply run normally.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Zod&lt;/li&gt;
&lt;li&gt;date-fns&lt;/li&gt;
&lt;li&gt;Dexie&lt;/li&gt;
&lt;li&gt;Three.js&lt;/li&gt;
&lt;li&gt;MapLibre&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a library already owns a canvas, WebGL context, or DOM subtree, Kudzu may only need to manage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mount
update
dispose
lifetime
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Kudzu
  └─ map container
       └─ MapLibre owns the internals
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No VDOM is required for that.&lt;/p&gt;

&lt;p&gt;The same idea may work for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CodeMirror&lt;/li&gt;
&lt;li&gt;Monaco&lt;/li&gt;
&lt;li&gt;ProseMirror&lt;/li&gt;
&lt;li&gt;Chart.js&lt;/li&gt;
&lt;li&gt;ECharts&lt;/li&gt;
&lt;li&gt;data grids&lt;/li&gt;
&lt;li&gt;media players&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is very different from embedding a React island.&lt;/p&gt;

&lt;p&gt;Kudzu would not try to recreate the package's internal rendering model.&lt;/p&gt;

&lt;p&gt;It would only own the boundary.&lt;/p&gt;

&lt;h2&gt;
  
  
  React ecosystem compatibility still matters
&lt;/h2&gt;

&lt;p&gt;I do want practical React migration compatibility.&lt;/p&gt;

&lt;p&gt;But I think there is an important distinction between:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;React runtime compatibility&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;and:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;React source compatibility&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The long-term goal is closer to:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;maximize React ecosystem source compatibility while minimizing React runtime compatibility&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That means different packages may need different strategies.&lt;/p&gt;

&lt;h3&gt;
  
  
  Native
&lt;/h3&gt;

&lt;p&gt;Normal JavaScript/TypeScript packages can run as-is.&lt;/p&gt;

&lt;h3&gt;
  
  
  Compiled
&lt;/h3&gt;

&lt;p&gt;Some familiar React-shaped patterns can be understood and compiled away.&lt;/p&gt;

&lt;h3&gt;
  
  
  Normalized
&lt;/h3&gt;

&lt;p&gt;Some source can be transformed into simpler HTML/JavaScript/Web API code before it reaches the core compiler.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/users"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Users&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;could conceptually become:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/users"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Users&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Adapter
&lt;/h3&gt;

&lt;p&gt;Some libraries may need package-specific migration logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  External owned UI
&lt;/h3&gt;

&lt;p&gt;Some complex UI libraries can own a bounded DOM/canvas area.&lt;/p&gt;

&lt;h3&gt;
  
  
  Partial or unsupported
&lt;/h3&gt;

&lt;p&gt;Some React libraries may rely deeply on React reconciliation or component-tree semantics.&lt;/p&gt;

&lt;p&gt;I think it is better to explicitly say “unsupported” than silently fall back to a React runtime.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance so far
&lt;/h2&gt;

&lt;p&gt;There are two sets of performance evidence I have been using.&lt;/p&gt;

&lt;p&gt;The public cross-framework benchmark currently uses an earlier Kudzu version, so I do not treat it as a current-version benchmark.&lt;/p&gt;

&lt;p&gt;Still, it is useful for understanding the architecture.&lt;/p&gt;

&lt;p&gt;On a commerce fixture under Slow 4G + 4× CPU throttling, the published results included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kudzu first interactive listing: &lt;strong&gt;450ms&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Astro: &lt;strong&gt;2.22s&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;TanStack Start: &lt;strong&gt;2.90s&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;React Router: &lt;strong&gt;2.96s&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Next.js App Router: &lt;strong&gt;3.54s&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Kudzu did not win everything.&lt;/p&gt;

&lt;p&gt;The 3-step form benchmark exposed a clear weakness in cross-page state propagation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;TanStack: &lt;strong&gt;191ms&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Astro: &lt;strong&gt;196ms&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;React Router: &lt;strong&gt;395ms&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Next.js: &lt;strong&gt;365ms&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Kudzu: &lt;strong&gt;700ms&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I think that loss is useful.&lt;/p&gt;

&lt;p&gt;It shows exactly the kind of application-level problem that matters more than shaving another few hundred bytes off a bundle.&lt;/p&gt;

&lt;p&gt;Kudzu's own maintained performance evidence also showed a stateful capability bundle substantially smaller than React/Vue/Svelte in that specific fixture, and large generated-route builds scaling competitively into the thousands of routes.&lt;/p&gt;

&lt;p&gt;I do not consider any of those numbers universal proof.&lt;/p&gt;

&lt;p&gt;They are fixture-specific.&lt;/p&gt;

&lt;p&gt;The part I care about most now is whether those characteristics survive as application complexity increases.&lt;/p&gt;

&lt;h2&gt;
  
  
  The next test should not be another blog
&lt;/h2&gt;

&lt;p&gt;I think the next serious test for Kudzu needs to be an actual application.&lt;/p&gt;

&lt;p&gt;Something like a small Linear / GitHub Issues / Jira-style app with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;login&lt;/li&gt;
&lt;li&gt;workspaces&lt;/li&gt;
&lt;li&gt;shared state&lt;/li&gt;
&lt;li&gt;nested routing&lt;/li&gt;
&lt;li&gt;server data&lt;/li&gt;
&lt;li&gt;loading/error states&lt;/li&gt;
&lt;li&gt;caching&lt;/li&gt;
&lt;li&gt;mutations&lt;/li&gt;
&lt;li&gt;optimistic updates&lt;/li&gt;
&lt;li&gt;forms&lt;/li&gt;
&lt;li&gt;modals&lt;/li&gt;
&lt;li&gt;search/filtering&lt;/li&gt;
&lt;li&gt;realtime updates&lt;/li&gt;
&lt;li&gt;a large list&lt;/li&gt;
&lt;li&gt;lazy-loaded editor or chart&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is not to build another demo that happens to match the compiler.&lt;/p&gt;

&lt;p&gt;The goal is to let the application expose where the compiler model is insufficient.&lt;/p&gt;

&lt;p&gt;Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;application fails
↓
identify the general missing capability
↓
check whether existing primitives can express it
↓
only add a new primitive if the limitation repeats across multiple real apps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is the development loop I want to follow.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI development is part of the design
&lt;/h2&gt;

&lt;p&gt;There is another reason I care about keeping the application model small.&lt;/p&gt;

&lt;p&gt;AI coding agents already understand React-shaped TypeScript/TSX extremely well.&lt;/p&gt;

&lt;p&gt;I do not want Kudzu to replace that with an entirely new DSL or dozens of Kudzu-specific APIs.&lt;/p&gt;

&lt;p&gt;Ideally an AI should be able to write familiar code while the compiler handles things the model should not need to reason about repeatedly.&lt;/p&gt;

&lt;p&gt;That includes things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dependency tracking&lt;/li&gt;
&lt;li&gt;unnecessary rerender semantics&lt;/li&gt;
&lt;li&gt;framework boilerplate&lt;/li&gt;
&lt;li&gt;some migration transformations&lt;/li&gt;
&lt;li&gt;precise diagnostics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The metric I eventually want to measure is not just bundle size.&lt;/p&gt;

&lt;p&gt;It is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;cost per successful task&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For the same feature, using the same coding agent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;how many tokens were used?&lt;/li&gt;
&lt;li&gt;how many files were opened?&lt;/li&gt;
&lt;li&gt;how many build attempts?&lt;/li&gt;
&lt;li&gt;how many compiler failures?&lt;/li&gt;
&lt;li&gt;how many edits?&lt;/li&gt;
&lt;li&gt;how much framework documentation had to be read?&lt;/li&gt;
&lt;li&gt;did the final application actually behave the same?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If Kudzu uses less client JavaScript but makes the AI fight the compiler for twice as long, that is not a win.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Kudzu is now
&lt;/h2&gt;

&lt;p&gt;Kudzu is still experimental.&lt;/p&gt;

&lt;p&gt;The current work is moving increasingly toward application-level behavior rather than only static output.&lt;/p&gt;

&lt;p&gt;But I do not think the large-application question is solved yet.&lt;/p&gt;

&lt;p&gt;That is the part I am trying to figure out now.&lt;/p&gt;

&lt;p&gt;The two constraints I am trying to hold at the same time are:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Do not rebuild React underneath the compiler.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Do not let “minimal runtime” prevent Kudzu from becoming a real application framework.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I think the interesting architecture is somewhere between those two extremes.&lt;/p&gt;

&lt;p&gt;Project:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://kudzujs.cloud" rel="noopener noreferrer"&gt;https://kudzujs.cloud&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GitHub:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/kudzujs/kudzu" rel="noopener noreferrer"&gt;https://github.com/kudzujs/kudzu&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Public benchmark:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/SimYunSup/kudzu-based-bench" rel="noopener noreferrer"&gt;https://github.com/SimYunSup/kudzu-based-bench&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'd be interested in hearing from people who have worked on large React, Vue, Svelte, Solid, or similar applications:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What browser-side capabilities do you consider genuinely unavoidable for serious web applications?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And which ones do you think mostly exist because of the rendering model of the framework you are using?&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
    </item>
    <item>
      <title>I Built the Same Commerce App in Kudzu, Astro, React Router, TanStack Start, and Next.js</title>
      <dc:creator>bunzzeok</dc:creator>
      <pubDate>Tue, 18 Aug 2026 04:07:53 +0000</pubDate>
      <link>https://dev.to/bunzzeok/i-built-the-same-commerce-app-in-kudzu-astro-react-router-tanstack-start-and-nextjs-6n9</link>
      <guid>https://dev.to/bunzzeok/i-built-the-same-commerce-app-in-kudzu-astro-react-router-tanstack-start-and-nextjs-6n9</guid>
      <description>&lt;p&gt;In my previous post, I introduced &lt;strong&gt;Kudzu&lt;/strong&gt;, a compiler-first framework that turns a statically analyzable subset of React-shaped TSX into static HTML and route-specific JavaScript without shipping React, a virtual DOM, or a hydration runtime.&lt;/p&gt;

&lt;p&gt;That raises an obvious question:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What happens when you move beyond counters and small demos?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So I built the same commerce application five times:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kudzu&lt;/li&gt;
&lt;li&gt;Astro + React islands&lt;/li&gt;
&lt;li&gt;React Router&lt;/li&gt;
&lt;li&gt;TanStack Start&lt;/li&gt;
&lt;li&gt;Next.js App Router&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal wasn't to create a synthetic benchmark where Kudzu could win.&lt;/p&gt;

&lt;p&gt;I wanted to replay something closer to an actual user session and measure what the browser experiences.&lt;/p&gt;

&lt;p&gt;The benchmark is open source:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/SimYunSup/kudzu-based-bench" rel="noopener noreferrer"&gt;https://github.com/SimYunSup/kudzu-based-bench&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The fixture
&lt;/h2&gt;

&lt;p&gt;Each implementation represents the same store with the same behavioral contract.&lt;/p&gt;

&lt;p&gt;There are six routes covering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;home&lt;/li&gt;
&lt;li&gt;search with filtering and sorting&lt;/li&gt;
&lt;li&gt;collections&lt;/li&gt;
&lt;li&gt;product details&lt;/li&gt;
&lt;li&gt;policy/content&lt;/li&gt;
&lt;li&gt;checkout&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The interactive paths include product options, adding items to the cart, filtering, sorting, navigation into product pages, back navigation, and cart state.&lt;/p&gt;

&lt;p&gt;All five versions emit complete HTML.&lt;/p&gt;

&lt;p&gt;That matters because simply measuring when text becomes visible doesn't tell us much here.&lt;/p&gt;

&lt;p&gt;The more interesting question is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When does the page become reliably interactive, and what did the browser have to download to get there?&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I didn't make this an LCP benchmark
&lt;/h2&gt;

&lt;p&gt;LCP is useful, but it doesn't distinguish these implementations particularly well in this fixture.&lt;/p&gt;

&lt;p&gt;The LCP element is generally a product image, and the image bytes are intentionally identical between implementations.&lt;/p&gt;

&lt;p&gt;A framework benchmark where the dominant measurement is an identical image mostly tells us about the image.&lt;/p&gt;

&lt;p&gt;Instead, I focused on observable application behavior:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;contentReady&lt;/code&gt;: when the important content exists in the DOM&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;actReady&lt;/code&gt;: when a control actually works&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;stepLatency&lt;/code&gt;: successful interaction to next paint&lt;/li&gt;
&lt;li&gt;navigation latency&lt;/li&gt;
&lt;li&gt;dropped early clicks&lt;/li&gt;
&lt;li&gt;bytes transferred across the session&lt;/li&gt;
&lt;li&gt;JavaScript downloaded per route&lt;/li&gt;
&lt;li&gt;behavior when JavaScript is delayed or partially unavailable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The browser is the judge.&lt;/p&gt;

&lt;p&gt;I don't use framework-internal "hydration complete" signals.&lt;/p&gt;

&lt;h2&gt;
  
  
  Replaying an actual session
&lt;/h2&gt;

&lt;p&gt;The main test runs under:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Slow 4G + 4× CPU slowdown&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;and replays the same interactions five times for each implementation.&lt;/p&gt;

&lt;p&gt;The median results for initial listing interactivity were:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Framework&lt;/th&gt;
&lt;th&gt;contentReady&lt;/th&gt;
&lt;th&gt;actReady&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Kudzu&lt;/td&gt;
&lt;td&gt;170 ms&lt;/td&gt;
&lt;td&gt;250 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Astro&lt;/td&gt;
&lt;td&gt;223 ms&lt;/td&gt;
&lt;td&gt;2,229 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TanStack Start&lt;/td&gt;
&lt;td&gt;170 ms&lt;/td&gt;
&lt;td&gt;2,859 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;React Router&lt;/td&gt;
&lt;td&gt;170 ms&lt;/td&gt;
&lt;td&gt;2,957 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Next.js&lt;/td&gt;
&lt;td&gt;178 ms&lt;/td&gt;
&lt;td&gt;3,537 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The content itself appears at roughly the same time.&lt;/p&gt;

&lt;p&gt;That's expected: every implementation ships complete HTML.&lt;/p&gt;

&lt;p&gt;The large difference appears between &lt;strong&gt;seeing the interface&lt;/strong&gt; and &lt;strong&gt;being able to reliably use it&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For Kudzu, the compiler-generated behavior is available after roughly 250 ms in this test.&lt;/p&gt;

&lt;p&gt;For the React-based implementations, more client-side machinery has to arrive and execute first.&lt;/p&gt;

&lt;h2&gt;
  
  
  How much JavaScript reaches each route?
&lt;/h2&gt;

&lt;p&gt;I also measured JavaScript from the browser's network activity rather than statically crawling the import graph.&lt;/p&gt;

&lt;p&gt;That distinction turned out to matter.&lt;/p&gt;

&lt;p&gt;For example, Astro can load island runtime code through dynamic imports that a naive static crawler can miss.&lt;/p&gt;

&lt;p&gt;Here are the initial route-level JavaScript totals, gzip compressed:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Framework&lt;/th&gt;
&lt;th&gt;Home&lt;/th&gt;
&lt;th&gt;Search&lt;/th&gt;
&lt;th&gt;Product&lt;/th&gt;
&lt;th&gt;Checkout&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Kudzu&lt;/td&gt;
&lt;td&gt;4.7 KB&lt;/td&gt;
&lt;td&gt;9.4 KB&lt;/td&gt;
&lt;td&gt;4.9 KB&lt;/td&gt;
&lt;td&gt;4.7 KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Astro&lt;/td&gt;
&lt;td&gt;60.6 KB&lt;/td&gt;
&lt;td&gt;61.0 KB&lt;/td&gt;
&lt;td&gt;61.1 KB&lt;/td&gt;
&lt;td&gt;60.6 KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TanStack Start&lt;/td&gt;
&lt;td&gt;101.7 KB&lt;/td&gt;
&lt;td&gt;101.7 KB&lt;/td&gt;
&lt;td&gt;101.9 KB&lt;/td&gt;
&lt;td&gt;101.3 KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;React Router&lt;/td&gt;
&lt;td&gt;104.3 KB&lt;/td&gt;
&lt;td&gt;104.2 KB&lt;/td&gt;
&lt;td&gt;104.4 KB&lt;/td&gt;
&lt;td&gt;103.9 KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Next.js&lt;/td&gt;
&lt;td&gt;134.2 KB&lt;/td&gt;
&lt;td&gt;134.8 KB&lt;/td&gt;
&lt;td&gt;133.8 KB&lt;/td&gt;
&lt;td&gt;132.8 KB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This is the architectural difference I wanted to investigate when I started Kudzu.&lt;/p&gt;

&lt;p&gt;Kudzu's search route needs keyed-list behavior, so it ships more JavaScript than the simpler routes.&lt;/p&gt;

&lt;p&gt;The other routes don't pay for that capability.&lt;/p&gt;

&lt;p&gt;The generated JavaScript follows what the route actually uses.&lt;/p&gt;

&lt;h2&gt;
  
  
  But SPA navigation wins somewhere else
&lt;/h2&gt;

&lt;p&gt;I didn't want the benchmark to stop at initial page load.&lt;/p&gt;

&lt;p&gt;The session opens a product using a real link, adds it to the cart, and then navigates back.&lt;/p&gt;

&lt;p&gt;For listing → product navigation:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Framework&lt;/th&gt;
&lt;th&gt;Navigation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;TanStack Start&lt;/td&gt;
&lt;td&gt;182 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;React Router&lt;/td&gt;
&lt;td&gt;185 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Astro&lt;/td&gt;
&lt;td&gt;222 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kudzu&lt;/td&gt;
&lt;td&gt;271 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Next.js&lt;/td&gt;
&lt;td&gt;360 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Here the SPA routers show a real advantage.&lt;/p&gt;

&lt;p&gt;React Router and TanStack Start perform the transition faster than Kudzu's document navigation.&lt;/p&gt;

&lt;p&gt;That's an important tradeoff.&lt;/p&gt;

&lt;p&gt;Removing a persistent application runtime doesn't magically make every operation faster.&lt;/p&gt;

&lt;p&gt;It changes where the costs occur.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happens across the whole session?
&lt;/h2&gt;

&lt;p&gt;I also measured all network transfer across the session, including prefetching.&lt;/p&gt;

&lt;p&gt;Script transfer was:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Framework&lt;/th&gt;
&lt;th&gt;Script transferred&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Kudzu&lt;/td&gt;
&lt;td&gt;34.4 KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Astro&lt;/td&gt;
&lt;td&gt;193.1 KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TanStack Start&lt;/td&gt;
&lt;td&gt;317.6 KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;React Router&lt;/td&gt;
&lt;td&gt;322.3 KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Next.js&lt;/td&gt;
&lt;td&gt;455.5 KB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This is more interesting to me than a single initial bundle number.&lt;/p&gt;

&lt;p&gt;Users don't experience isolated benchmark pages.&lt;/p&gt;

&lt;p&gt;They enter an application, navigate, interact, reuse cached resources, and sometimes download things speculatively prefetched by the framework.&lt;/p&gt;

&lt;p&gt;So the session should carry its cache forward too.&lt;/p&gt;

&lt;h2&gt;
  
  
  What if JavaScript arrives late?
&lt;/h2&gt;

&lt;p&gt;I also wanted to test something performance benchmarks often ignore:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;failure and degradation.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I tested six capabilities:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;reading content&lt;/li&gt;
&lt;li&gt;category navigation&lt;/li&gt;
&lt;li&gt;entering a product&lt;/li&gt;
&lt;li&gt;filtering&lt;/li&gt;
&lt;li&gt;selecting an option&lt;/li&gt;
&lt;li&gt;adding to cart&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;under three conditions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JavaScript completely blocked&lt;/li&gt;
&lt;li&gt;scripts delayed by two seconds&lt;/li&gt;
&lt;li&gt;one script request lost&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That gives 18 capability checks per implementation.&lt;/p&gt;

&lt;p&gt;Results:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Framework&lt;/th&gt;
&lt;th&gt;Surviving capabilities&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Kudzu&lt;/td&gt;
&lt;td&gt;15 / 18&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Astro&lt;/td&gt;
&lt;td&gt;12 / 18&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TanStack Start&lt;/td&gt;
&lt;td&gt;8 / 18&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;React Router&lt;/td&gt;
&lt;td&gt;8 / 18&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Next.js&lt;/td&gt;
&lt;td&gt;8 / 18&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;None of them magically retain full interactivity without JavaScript.&lt;/p&gt;

&lt;p&gt;But their failure modes are different.&lt;/p&gt;

&lt;p&gt;That's something I want to explore much more deeply.&lt;/p&gt;

&lt;h2&gt;
  
  
  Kudzu also has a scaling problem
&lt;/h2&gt;

&lt;p&gt;One result I don't want to hide is build scaling.&lt;/p&gt;

&lt;p&gt;With 1,000 catalog items, median build times were approximately:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Framework&lt;/th&gt;
&lt;th&gt;Build time&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Astro&lt;/td&gt;
&lt;td&gt;1.82 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TanStack Start&lt;/td&gt;
&lt;td&gt;2.47 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;React Router&lt;/td&gt;
&lt;td&gt;3.07 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kudzu&lt;/td&gt;
&lt;td&gt;3.56 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Next.js&lt;/td&gt;
&lt;td&gt;5.62 s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;More importantly, Kudzu currently has the steepest scaling curve between 100 and 1,000 products.&lt;/p&gt;

&lt;p&gt;That's a compiler architecture problem.&lt;/p&gt;

&lt;p&gt;Kudzu currently emits capability modules per product in places where that work should be shared or amortized more effectively.&lt;/p&gt;

&lt;p&gt;So while the runtime results are encouraging, I wouldn't call this proof that Kudzu scales to large applications.&lt;/p&gt;

&lt;p&gt;It doesn't yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;

&lt;p&gt;The biggest takeaway for me isn't simply that "less JavaScript is faster."&lt;/p&gt;

&lt;p&gt;That's too simplistic.&lt;/p&gt;

&lt;p&gt;The more interesting result is that different architectures move cost to different places.&lt;/p&gt;

&lt;p&gt;A compiler-first architecture can dramatically reduce the amount of framework machinery required in the browser.&lt;/p&gt;

&lt;p&gt;But SPA routers can provide faster client-side navigation.&lt;/p&gt;

&lt;p&gt;Compiler specialization can reduce route JavaScript.&lt;/p&gt;

&lt;p&gt;But generating specialized artifacts can increase build cost as the application grows.&lt;/p&gt;

&lt;p&gt;Avoiding hydration can make interactions available earlier under constrained networks.&lt;/p&gt;

&lt;p&gt;But that doesn't automatically solve application architecture, state management, forms, routing, or ecosystem compatibility.&lt;/p&gt;

&lt;p&gt;Those are the problems I'm working on next.&lt;/p&gt;

&lt;h2&gt;
  
  
  This still isn't a large-app benchmark
&lt;/h2&gt;

&lt;p&gt;The commerce fixture is intentionally much larger than a toy benchmark, but I don't consider it evidence that Kudzu is ready for a truly large production application.&lt;/p&gt;

&lt;p&gt;The next step is larger fixtures with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;shared state&lt;/li&gt;
&lt;li&gt;async/server state&lt;/li&gt;
&lt;li&gt;deeper component and module graphs&lt;/li&gt;
&lt;li&gt;forms&lt;/li&gt;
&lt;li&gt;authentication&lt;/li&gt;
&lt;li&gt;more complex routing&lt;/li&gt;
&lt;li&gt;broader React ecosystem integration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In fact, I've already started using separate form and documentation/search fixtures because the commerce benchmark doesn't expose every architectural weakness.&lt;/p&gt;

&lt;p&gt;Some of those tests make Kudzu look much less flattering.&lt;/p&gt;

&lt;p&gt;That's useful.&lt;/p&gt;

&lt;p&gt;A benchmark should tell me where the architecture breaks, not just give me a chart I can put on a landing page.&lt;/p&gt;

&lt;p&gt;If you're interested in compiler-first frontend architecture, I'd especially like feedback on the benchmark methodology and what kinds of real application behavior I should test next.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benchmark repo:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/SimYunSup/kudzu-based-bench" rel="noopener noreferrer"&gt;https://github.com/SimYunSup/kudzu-based-bench&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kudzu:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/kudzujs/kudzu" rel="noopener noreferrer"&gt;https://github.com/kudzujs/kudzu&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>react</category>
      <category>performance</category>
    </item>
    <item>
      <title>Kudzu: Compiling React-shaped TSX to Static HTML Without Hydration</title>
      <dc:creator>bunzzeok</dc:creator>
      <pubDate>Thu, 06 Aug 2026 12:52:25 +0000</pubDate>
      <link>https://dev.to/bunzzeok/kudzu-compiling-react-shaped-tsx-to-static-html-without-hydration-41ij</link>
      <guid>https://dev.to/bunzzeok/kudzu-compiling-react-shaped-tsx-to-static-html-without-hydration-41ij</guid>
      <description>&lt;p&gt;React-shaped TSX is a familiar way to describe user interfaces, but deploying it usually involves shipping a JavaScript runtime, hydration, or a client-side component tree.&lt;/p&gt;

&lt;p&gt;I have been experimenting with a different approach through an open-source project called Kudzu.&lt;/p&gt;

&lt;p&gt;Kudzu compiles a statically analyzable subset of React-shaped TypeScript and TSX into complete static HTML, CSS, and only the route-specific ESM capabilities actually used.&lt;/p&gt;

&lt;h2&gt;
  
  
  A small example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@kudzujs/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;HomePage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      Grown &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; times
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The component executes during the build. It does not survive as a browser component.&lt;/p&gt;

&lt;p&gt;Kudzu generates the initial HTML and lowers the state update into direct browser behavior. State setters update logical state synchronously, while DOM writes are batched at the end of the synchronous turn.&lt;/p&gt;

&lt;h2&gt;
  
  
  Static routes ship no JavaScript
&lt;/h2&gt;

&lt;p&gt;When a route does not use browser interaction, Kudzu emits HTML and CSS without a client-side JavaScript runtime.&lt;/p&gt;

&lt;p&gt;Interactive routes include only the capabilities they use, such as state bindings, event handlers, effects, keyed collections, or runtime URL parameters.&lt;/p&gt;

&lt;p&gt;There is no React runtime, hydration pass, virtual DOM, or retained browser component tree.&lt;/p&gt;

&lt;h2&gt;
  
  
  This is not full React compatibility
&lt;/h2&gt;

&lt;p&gt;Kudzu accepts only patterns that it can analyze and lower safely.&lt;/p&gt;

&lt;p&gt;Supported patterns include function components, props, children, state, effects, conditions, keyed collections, refs, and selected React Router migration patterns.&lt;/p&gt;

&lt;p&gt;Unsupported nearby patterns fail during the build with a source location and actionable diagnostic instead of silently falling back to React.&lt;/p&gt;

&lt;p&gt;The project is experimental, and the supported TSX surface may change.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why build it?
&lt;/h2&gt;

&lt;p&gt;The goal is to explore whether ordinary React-shaped applications can be migrated to static deployment artifacts without forcing developers to rewrite declarative components as imperative DOM code.&lt;/p&gt;

&lt;p&gt;Build-known work stays at build time. Browser code is generated only when the browser is the only place where the required value or interaction exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;Documentation and demos: &lt;a href="https://kudzujs.cloud" rel="noopener noreferrer"&gt;https://kudzujs.cloud&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Source code: &lt;a href="https://github.com/kudzujs/kudzu" rel="noopener noreferrer"&gt;https://github.com/kudzujs/kudzu&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;npm: &lt;a href="https://www.npmjs.com/package/@kudzujs/core" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/@kudzujs/core&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I would appreciate feedback on the compiler boundaries, generated runtime model, and ordinary React patterns that would be most valuable to support next.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>opensource</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How I compile React-shaped TSX without React or hydration</title>
      <dc:creator>bunzzeok</dc:creator>
      <pubDate>Sat, 25 Jul 2026 12:23:04 +0000</pubDate>
      <link>https://dev.to/bunzzeok/how-i-compile-react-shaped-tsx-without-react-or-hydration-59k0</link>
      <guid>https://dev.to/bunzzeok/how-i-compile-react-shaped-tsx-without-react-or-hydration-59k0</guid>
      <description>&lt;p&gt;I started building Kudzu while making static websites with AI.&lt;/p&gt;

&lt;p&gt;AI coding tools have become very good at producing React-shaped TSX, and I have become used to reviewing code in that form. Function components, props, JSX, and event handlers are often easier for me to understand and verify than scattered DOM queries and imperative JavaScript mutations.&lt;/p&gt;

&lt;p&gt;But I was still building static pages.&lt;/p&gt;

&lt;p&gt;I wanted to keep TSX as the authoring and code-review format without automatically shipping React, a virtual DOM, hydration, or a browser-side component tree.&lt;/p&gt;

&lt;p&gt;Kudzu grew from that idea:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Write familiar TSX, execute components during the build, and ship ordinary HTML with only the JavaScript each route actually needs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Kudzu is an experimental, HTML-first TSX framework.&lt;/p&gt;

&lt;p&gt;Website: &lt;a href="https://kudzujs.cloud/" rel="noopener noreferrer"&gt;kudzujs.cloud&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/kudzujs/kudzu" rel="noopener noreferrer"&gt;github.com/kudzujs/kudzu&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem I wanted to solve
&lt;/h2&gt;

&lt;p&gt;Consider a blog, documentation site, newsletter, or product landing page.&lt;/p&gt;

&lt;p&gt;Most of the page is already known during the build:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;headings;&lt;/li&gt;
&lt;li&gt;navigation;&lt;/li&gt;
&lt;li&gt;articles;&lt;/li&gt;
&lt;li&gt;images;&lt;/li&gt;
&lt;li&gt;metadata;&lt;/li&gt;
&lt;li&gt;product descriptions;&lt;/li&gt;
&lt;li&gt;documentation content.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;TSX is a convenient way to author and review that structure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;PostCard&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;article&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;article&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The component model is useful for authoring, but that does not necessarily mean the browser needs a component runtime.&lt;/p&gt;

&lt;p&gt;For a static page, I wanted the output to remain ordinary HTML.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;article&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/posts/hello"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Hello&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;My first article.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I also wanted interactive pages to receive only the JavaScript required for their actual behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Kudzu's model
&lt;/h2&gt;

&lt;p&gt;Kudzu treats components as build-time authoring units.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;React-shaped TSX
        ↓
Kudzu compiler
        ↓
Static HTML + CSS + capability-specific ESM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Function components execute during the build.&lt;/p&gt;

&lt;p&gt;The browser does not receive:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the component functions;&lt;/li&gt;
&lt;li&gt;React;&lt;/li&gt;
&lt;li&gt;a virtual DOM;&lt;/li&gt;
&lt;li&gt;a hydration pass;&lt;/li&gt;
&lt;li&gt;a retained component tree;&lt;/li&gt;
&lt;li&gt;a general rerender loop.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A completely static route receives no client JavaScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  A static page
&lt;/h2&gt;

&lt;p&gt;A Kudzu page lives in &lt;code&gt;src/pages&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/pages/index.tsx&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;HomePage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello from Kudzu&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;This page becomes static HTML.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Build the project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output is written to &lt;code&gt;dist&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dist/
├─ index.html
└─ assets/
   └─ style.css
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because the page has no browser behavior, Kudzu does not add a JavaScript runtime.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding state
&lt;/h2&gt;

&lt;p&gt;Kudzu supports a React-shaped &lt;code&gt;useState&lt;/code&gt; API.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@kudzujs/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      Count: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The compiler identifies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the logical state;&lt;/li&gt;
&lt;li&gt;the setter;&lt;/li&gt;
&lt;li&gt;the event;&lt;/li&gt;
&lt;li&gt;the text node bound to the state.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The component is executed during the build to produce the initial HTML.&lt;/p&gt;

&lt;p&gt;The browser receives a small behavior plan that updates the relevant DOM node directly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;click
  → update logical state
  → queue a DOM commit
  → patch the bound text node
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The browser does not rerun the component.&lt;/p&gt;

&lt;h2&gt;
  
  
  Immediate logical state
&lt;/h2&gt;

&lt;p&gt;Kudzu deliberately differs from React's state snapshot behavior.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;increaseTwice&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Kudzu:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A setter updates logical state immediately.&lt;/li&gt;
&lt;li&gt;The next statement reads the latest logical value.&lt;/li&gt;
&lt;li&gt;Setters run in source order.&lt;/li&gt;
&lt;li&gt;DOM writes are batched until the synchronous turn ends.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The handler above increments the value by two and patches the DOM once.&lt;/p&gt;

&lt;p&gt;This model gives event handlers normal sequential JavaScript behavior without requiring a browser component rerender.&lt;/p&gt;

&lt;h2&gt;
  
  
  Simple commands and normal JavaScript
&lt;/h2&gt;

&lt;p&gt;Kudzu has two event compilation paths.&lt;/p&gt;

&lt;p&gt;Simple setter-only handlers compile to compact behavior commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  Increase
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Normal synchronous or asynchronous handlers compile to external ESM.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;loadStatus&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;loading&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/status&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;setStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;failed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kudzu does not use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;eval&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;new Function&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;inline executable JavaScript;&lt;/li&gt;
&lt;li&gt;hydration.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Relative TypeScript helpers can also be bundled into the generated handler module.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;normalizeStatus&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../lib/status&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;loadStatus&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/status&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="nf"&gt;setStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;normalizeStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Direct DOM bindings
&lt;/h2&gt;

&lt;p&gt;State can be used in text, attributes, styles, and form properties.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;open&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setOpen&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;
    &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;open&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;idle&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="na"&gt;aria-expanded&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;open&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setOpen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;open&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;open&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Close&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Open&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kudzu compiles the expressions into direct DOM updates.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;open changes
  → patch class
  → patch aria-expanded
  → patch text
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The entire component is not rerendered.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conditional DOM
&lt;/h2&gt;

&lt;p&gt;Inline conditional children compile to bounded DOM ranges.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;open&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setOpen&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setOpen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;open&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      Toggle menu
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;open&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;nav&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/docs"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Docs&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/example"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Examples&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;nav&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both branches are prepared during the build. The browser mounts or removes only the relevant DOM range.&lt;/p&gt;

&lt;p&gt;There is still no virtual DOM or component tree.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keyed lists
&lt;/h2&gt;

&lt;p&gt;Kudzu also supports a constrained form of keyed list rendering.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setItems&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Oak&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Pine&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;
          &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="nf"&gt;setItems&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
          &lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          Remove
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The initial list is emitted as static HTML.&lt;/p&gt;

&lt;p&gt;When state changes, Kudzu moves, inserts, updates, or removes the keyed DOM nodes directly.&lt;/p&gt;

&lt;p&gt;Existing keyed nodes are preserved instead of remounted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build-time data
&lt;/h2&gt;

&lt;p&gt;Async components can load data during the build.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ProductsPage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://example.com/api/products&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Products&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the route and data are available during the build, the result is complete static HTML.&lt;/p&gt;

&lt;p&gt;No browser fetch or hydration is required.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dynamic static routes
&lt;/h2&gt;

&lt;p&gt;Build-known dynamic routes use &lt;code&gt;getStaticPaths()&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/pages/posts/[slug].tsx&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getStaticPaths&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello-kudzu&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello Kudzu&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;static-html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Static HTML&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;title&lt;/span&gt;
&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The build produces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dist/posts/hello-kudzu/index.html
dist/posts/static-html/index.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result can be deployed to an ordinary static host.&lt;/p&gt;

&lt;h2&gt;
  
  
  Browser-only effects
&lt;/h2&gt;

&lt;p&gt;Sometimes data or browser APIs are only available after the document loads.&lt;/p&gt;

&lt;p&gt;Kudzu supports a deliberately constrained &lt;code&gt;useEffect&lt;/code&gt; form.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@kudzujs/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;StatusPage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setStatus&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;loading&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/status&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Status: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The effect is not executed during static rendering.&lt;/p&gt;

&lt;p&gt;Kudzu emits a route-specific effect entry that updates the existing logical state and bound DOM nodes.&lt;/p&gt;

&lt;p&gt;The component itself is not shipped or rerun.&lt;/p&gt;

&lt;h2&gt;
  
  
  Capability-specific output
&lt;/h2&gt;

&lt;p&gt;Kudzu does not give every interactive route the same runtime.&lt;/p&gt;

&lt;p&gt;A route receives only the capabilities it uses.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Static route          → HTML only
State commands        → compact behavior runtime
Reactive bindings     → binding capability
Conditional DOM       → bounded DOM operations
Keyed lists           → list capability
Normal handlers       → external handler ESM
Effects               → route-specific effect entry
Runtime parameters    → route-specific pathname reader
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A static route remains JavaScript-free even if another route in the same project is interactive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Static output and Cloudflare
&lt;/h2&gt;

&lt;p&gt;Kudzu writes deployable artifacts to &lt;code&gt;dist&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A minimal Cloudflare configuration looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"my-kudzu-site"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compatibility_date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-07-20"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"assets"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"directory"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dist"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Build and deploy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run build
npx wrangler deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Kudzu website itself is deployed using Cloudflare static assets.&lt;/p&gt;

&lt;p&gt;The project also uses build-time generation for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;canonical URLs;&lt;/li&gt;
&lt;li&gt;sitemap entries;&lt;/li&gt;
&lt;li&gt;robots metadata;&lt;/li&gt;
&lt;li&gt;structured data;&lt;/li&gt;
&lt;li&gt;static blog routes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why not just write vanilla JavaScript?
&lt;/h2&gt;

&lt;p&gt;Vanilla JavaScript is not the problem.&lt;/p&gt;

&lt;p&gt;For small behavior, it is often the smallest and best browser output.&lt;/p&gt;

&lt;p&gt;The problem I was trying to solve was authoring and review.&lt;/p&gt;

&lt;p&gt;When working with AI-generated code, I found this form easier to inspect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;PostCard&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`/posts/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;than a collection of unrelated operations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;article&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;article&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;heading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;h2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;link&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`/posts/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;
&lt;span class="nx"&gt;heading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;heading&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The browser may ultimately need ordinary DOM operations.&lt;/p&gt;

&lt;p&gt;I just did not want to author and review the entire site at that level.&lt;/p&gt;

&lt;p&gt;Kudzu uses TSX as the input language and ordinary HTML and DOM operations as the output.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Kudzu is not
&lt;/h2&gt;

&lt;p&gt;Kudzu is not a drop-in React replacement.&lt;/p&gt;

&lt;p&gt;It supports a statically analyzable React-shaped subset.&lt;/p&gt;

&lt;p&gt;Unsupported patterns fail during the build instead of silently causing Kudzu to ship a general component runtime.&lt;/p&gt;

&lt;p&gt;Kudzu currently does not provide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;arbitrary React package compatibility;&lt;/li&gt;
&lt;li&gt;a virtual DOM;&lt;/li&gt;
&lt;li&gt;request-time SSR;&lt;/li&gt;
&lt;li&gt;server actions;&lt;/li&gt;
&lt;li&gt;a default SPA router;&lt;/li&gt;
&lt;li&gt;Suspense semantics;&lt;/li&gt;
&lt;li&gt;concurrent rendering;&lt;/li&gt;
&lt;li&gt;a general browser component rerender loop.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is not to run every React application unchanged.&lt;/p&gt;

&lt;p&gt;The goal is to preserve familiar TSX authoring where it can be compiled safely into static HTML and direct browser behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Current status
&lt;/h2&gt;

&lt;p&gt;Kudzu is experimental, and the supported TSX surface may still change.&lt;/p&gt;

&lt;p&gt;The current implementation includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;function components;&lt;/li&gt;
&lt;li&gt;props and children;&lt;/li&gt;
&lt;li&gt;fragments;&lt;/li&gt;
&lt;li&gt;static and dynamic routes;&lt;/li&gt;
&lt;li&gt;async build-time components;&lt;/li&gt;
&lt;li&gt;primitive and serializable object state;&lt;/li&gt;
&lt;li&gt;reactive text and attributes;&lt;/li&gt;
&lt;li&gt;controlled form properties;&lt;/li&gt;
&lt;li&gt;conditional DOM;&lt;/li&gt;
&lt;li&gt;keyed lists;&lt;/li&gt;
&lt;li&gt;context;&lt;/li&gt;
&lt;li&gt;DOM refs;&lt;/li&gt;
&lt;li&gt;synchronous and asynchronous handlers;&lt;/li&gt;
&lt;li&gt;relative TypeScript helpers;&lt;/li&gt;
&lt;li&gt;mount effects;&lt;/li&gt;
&lt;li&gt;primitive effect dependencies;&lt;/li&gt;
&lt;li&gt;runtime path parameters;&lt;/li&gt;
&lt;li&gt;Cloudflare static deployment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I am especially interested in feedback about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the compiler model;&lt;/li&gt;
&lt;li&gt;migration from conventional React-shaped code;&lt;/li&gt;
&lt;li&gt;unsupported patterns that need better diagnostics;&lt;/li&gt;
&lt;li&gt;generated JavaScript size;&lt;/li&gt;
&lt;li&gt;immediate logical state semantics;&lt;/li&gt;
&lt;li&gt;real static-site use cases.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try Kudzu
&lt;/h2&gt;

&lt;p&gt;Create a project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm create kudzu@latest my-app
&lt;span class="nb"&gt;cd &lt;/span&gt;my-app
npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Build the static output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The generated files are available in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dist/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The build execution plan is available in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.kudzu/kudzu-plan.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;p&gt;Website: &lt;a href="https://kudzujs.cloud/" rel="noopener noreferrer"&gt;https://kudzujs.cloud/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Examples: &lt;a href="https://kudzujs.cloud/example" rel="noopener noreferrer"&gt;https://kudzujs.cloud/example&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Documentation: &lt;a href="https://kudzujs.cloud/docs" rel="noopener noreferrer"&gt;https://kudzujs.cloud/docs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/kudzujs/kudzu" rel="noopener noreferrer"&gt;https://github.com/kudzujs/kudzu&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;npm: &lt;a href="https://www.npmjs.com/package/@kudzujs/core" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/@kudzujs/core&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
