<?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: Heber Almeida</title>
    <description>The latest articles on DEV Community by Heber Almeida (@heberalmeida).</description>
    <link>https://dev.to/heberalmeida</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%2F4055309%2F901d7d15-b6a8-4d8b-bd9f-3e5862c642bd.jpg</url>
      <title>DEV Community: Heber Almeida</title>
      <link>https://dev.to/heberalmeida</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/heberalmeida"/>
    <language>en</language>
    <item>
      <title>Building a Compile-Time JavaScript Framework from Scratch</title>
      <dc:creator>Heber Almeida</dc:creator>
      <pubDate>Thu, 30 Jul 2026 15:07:44 +0000</pubDate>
      <link>https://dev.to/heberalmeida/building-a-compile-time-javascript-framework-from-scratch-206l</link>
      <guid>https://dev.to/heberalmeida/building-a-compile-time-javascript-framework-from-scratch-206l</guid>
      <description>&lt;p&gt;Every few years someone asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Do we really need another JavaScript framework?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The honest answer is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Probably not.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But building one is one of the best ways to truly understand how modern frontend frameworks work.&lt;/p&gt;

&lt;p&gt;Over the last several months I've been building &lt;strong&gt;Jacaré&lt;/strong&gt;, an experimental compile-time JavaScript framework.&lt;/p&gt;

&lt;p&gt;The objective wasn't to replace existing tools.&lt;/p&gt;

&lt;p&gt;The objective was to understand how everything works internally by designing every major subsystem from scratch.&lt;/p&gt;

&lt;p&gt;That meant building:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A compiler&lt;/li&gt;
&lt;li&gt;A reactive runtime&lt;/li&gt;
&lt;li&gt;A rendering engine&lt;/li&gt;
&lt;li&gt;A component model&lt;/li&gt;
&lt;li&gt;Navigation&lt;/li&gt;
&lt;li&gt;Forms&lt;/li&gt;
&lt;li&gt;SSR&lt;/li&gt;
&lt;li&gt;DevTools&lt;/li&gt;
&lt;li&gt;CLI tooling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This article isn't about announcing a framework.&lt;/p&gt;

&lt;p&gt;It's about sharing what I learned while building one.&lt;/p&gt;




&lt;h1&gt;
  
  
  Why build a framework?
&lt;/h1&gt;

&lt;p&gt;Most frontend developers use frameworks every day.&lt;/p&gt;

&lt;p&gt;Very few have the opportunity to understand what actually happens behind the scenes.&lt;/p&gt;

&lt;p&gt;Questions like these kept coming back:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How does a template become JavaScript?&lt;/li&gt;
&lt;li&gt;How are reactive dependencies tracked?&lt;/li&gt;
&lt;li&gt;Why do some runtimes stay incredibly small?&lt;/li&gt;
&lt;li&gt;How do frameworks update only what changed?&lt;/li&gt;
&lt;li&gt;How can rendering stay predictable while remaining fast?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Eventually I stopped reading about these problems.&lt;/p&gt;

&lt;p&gt;I started implementing them.&lt;/p&gt;




&lt;h1&gt;
  
  
  The first architectural decision
&lt;/h1&gt;

&lt;p&gt;One of the earliest decisions was choosing &lt;strong&gt;compile-time rendering&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of parsing templates inside the browser, Jacaré compiles &lt;code&gt;.jcr&lt;/code&gt; files into optimized JavaScript during the build.&lt;/p&gt;

&lt;p&gt;A simple component looks like this:&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;signal&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="s1"&gt;@jacare/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&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;export&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;$&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;
            &lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&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="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;n&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="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/main&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/view&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The compiler transforms this into optimized DOM operations.&lt;/p&gt;

&lt;p&gt;There is no runtime template parser.&lt;/p&gt;

&lt;p&gt;The browser only executes JavaScript.&lt;/p&gt;




&lt;h1&gt;
  
  
  Fine-grained reactivity
&lt;/h1&gt;

&lt;p&gt;The next challenge was designing the reactive system.&lt;/p&gt;

&lt;p&gt;Instead of updating an entire component whenever state changes, each binding subscribes only to the signals it actually depends on.&lt;/p&gt;

&lt;p&gt;Conceptually 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;Signal
   │
   ▼
Binding
   │
   ▼
DOM Node
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a signal changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;no component re-executes&lt;/li&gt;
&lt;li&gt;no template is interpreted again&lt;/li&gt;
&lt;li&gt;no unrelated DOM nodes are touched&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Only the affected bindings update.&lt;/p&gt;

&lt;p&gt;This design keeps updates deterministic while allowing the runtime to remain extremely small.&lt;/p&gt;




&lt;h1&gt;
  
  
  Why use a compiler?
&lt;/h1&gt;

&lt;p&gt;A compiler can eliminate work before the application even reaches the browser.&lt;/p&gt;

&lt;p&gt;Instead of interpreting templates during execution, the compiler generates specialized JavaScript tailored for each component.&lt;/p&gt;

&lt;p&gt;That allows the runtime to focus almost entirely on state propagation and DOM updates.&lt;/p&gt;

&lt;p&gt;Moving complexity from runtime to build time became one of the guiding principles of the project.&lt;/p&gt;




&lt;h1&gt;
  
  
  Building the runtime
&lt;/h1&gt;

&lt;p&gt;One of my goals was keeping the runtime as small as possible.&lt;/p&gt;

&lt;p&gt;Current runtime size:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;~1.2 KB (gzip)&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The small size wasn't the primary objective.&lt;/p&gt;

&lt;p&gt;It was simply the result of pushing as much work as possible into the compiler.&lt;/p&gt;




&lt;h1&gt;
  
  
  The hardest problem wasn't rendering
&lt;/h1&gt;

&lt;p&gt;Surprisingly, rendering wasn't the most difficult part.&lt;/p&gt;

&lt;p&gt;Designing the reactive graph was.&lt;/p&gt;

&lt;p&gt;Questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How should dependencies be represented?&lt;/li&gt;
&lt;li&gt;How should updates propagate?&lt;/li&gt;
&lt;li&gt;How should lists be reconciled?&lt;/li&gt;
&lt;li&gt;How should shared state work?&lt;/li&gt;
&lt;li&gt;How should effects be scheduled?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those decisions ended up influencing almost every subsystem in the framework.&lt;/p&gt;




&lt;h1&gt;
  
  
  Current features
&lt;/h1&gt;

&lt;p&gt;Today Jacaré includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Compile-time rendering&lt;/li&gt;
&lt;li&gt;Fine-grained reactivity&lt;/li&gt;
&lt;li&gt;Direct DOM updates&lt;/li&gt;
&lt;li&gt;Incremental rendering&lt;/li&gt;
&lt;li&gt;SSR&lt;/li&gt;
&lt;li&gt;Navigation&lt;/li&gt;
&lt;li&gt;Forms&lt;/li&gt;
&lt;li&gt;DevTools&lt;/li&gt;
&lt;li&gt;Interactive API tutorial&lt;/li&gt;
&lt;li&gt;Online playground&lt;/li&gt;
&lt;li&gt;Component contracts&lt;/li&gt;
&lt;li&gt;Reactive CSS variables&lt;/li&gt;
&lt;li&gt;Native shared state&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The project is still experimental, and there are many ideas I'd like to explore in future versions.&lt;/p&gt;




&lt;h1&gt;
  
  
  Things I would redesign today
&lt;/h1&gt;

&lt;p&gt;Building a framework changes how you think about software architecture.&lt;/p&gt;

&lt;p&gt;Some APIs that looked elegant at first became harder to maintain.&lt;/p&gt;

&lt;p&gt;Other ideas that initially seemed complicated turned out to simplify the entire system later.&lt;/p&gt;

&lt;p&gt;That's probably the biggest lesson from this project:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The first implementation is rarely the final architecture.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Every subsystem taught me something different.&lt;/p&gt;




&lt;h1&gt;
  
  
  I'd love technical feedback
&lt;/h1&gt;

&lt;p&gt;If you're interested in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;compiler design&lt;/li&gt;
&lt;li&gt;reactive runtimes&lt;/li&gt;
&lt;li&gt;incremental rendering&lt;/li&gt;
&lt;li&gt;DOM engines&lt;/li&gt;
&lt;li&gt;framework architecture&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'd genuinely appreciate your feedback.&lt;/p&gt;

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

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

&lt;p&gt;Interactive API tutorial&lt;/p&gt;

&lt;p&gt;&lt;a href="https://jacarejs.github.io/core/lab/" rel="noopener noreferrer"&gt;https://jacarejs.github.io/core/lab/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Online playground&lt;/p&gt;

&lt;p&gt;&lt;a href="https://jacarejs.github.io/core/studio/" rel="noopener noreferrer"&gt;https://jacarejs.github.io/core/studio/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm especially interested in criticism.&lt;/p&gt;

&lt;p&gt;If you think an architectural decision could be improved—or completely redesigned—I'd love to hear why.&lt;/p&gt;




&lt;h1&gt;
  
  
  What's next?
&lt;/h1&gt;

&lt;p&gt;Over the next few weeks I plan to write a series of articles covering the internals of the project, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Building a reactive runtime&lt;/li&gt;
&lt;li&gt;Writing a template compiler&lt;/li&gt;
&lt;li&gt;Incremental DOM rendering&lt;/li&gt;
&lt;li&gt;Designing a component model&lt;/li&gt;
&lt;li&gt;Shared state architecture&lt;/li&gt;
&lt;li&gt;Compiler optimizations&lt;/li&gt;
&lt;li&gt;DevTools implementation&lt;/li&gt;
&lt;li&gt;Lessons learned from building a framework from scratch&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks for reading! 🐊&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>javascript</category>
      <category>softwaredevelopment</category>
    </item>
  </channel>
</rss>
