<?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: denshya</title>
    <description>The latest articles on DEV Community by denshya (@denshya).</description>
    <link>https://dev.to/denshya</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.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F10238%2F9a490573-35a7-4f48-a2d1-8a376f0a59ce.jpg</url>
      <title>DEV Community: denshya</title>
      <link>https://dev.to/denshya</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/denshya"/>
    <language>en</language>
    <item>
      <title>End Of The Year For Denshya Libraries</title>
      <dc:creator>Valery Zinchenko</dc:creator>
      <pubDate>Tue, 16 Dec 2025 11:36:30 +0000</pubDate>
      <link>https://dev.to/denshya/end-of-the-year-for-denshya-libraries-2mom</link>
      <guid>https://dev.to/denshya/end-of-the-year-for-denshya-libraries-2mom</guid>
      <description>&lt;p&gt;Hello everyone,&lt;br&gt;
By now, there were some accomplishments.&lt;br&gt;
&lt;a href="https://github.com/pinely-international/tama/discussions/145" rel="noopener noreferrer"&gt;https://github.com/pinely-international/tama/discussions/145&lt;/a&gt;&lt;br&gt;
(Though I'm not entirely satisfied with the quality of the code, &lt;em&gt;AI is the evil&lt;/em&gt;)&lt;/p&gt;

&lt;p&gt;Some planned issues were not completed because there was 3 weeks pause on this project due to other projects I'm engaged in.&lt;/p&gt;

&lt;p&gt;Despite of this delay, I was constantly thinking and considering evolution options for Denshya and Tama, now I see clearly that mere renaming (to Tama) and documentation polishing is not enough.&lt;/p&gt;

&lt;p&gt;I was questioning signals approach generally (which I like) and by watching React Dev Conference 2025, I understood that React gives (at least) familiar and nice data-modelling approach, which I like too.&lt;br&gt;
I can't just ignore the fact that React nails it, whereas Tama focuses on different aspects.&lt;/p&gt;

&lt;p&gt;With this, I made a decision to support both approaches, both signals and plain JS scoped updates.&lt;br&gt;
For you, this just means React hooks will work in Tama (potentially any React components will work too). Though for me it means more work 🥲&lt;/p&gt;

&lt;p&gt;I adopted Tama in different projects to see how well it solves problems where React fails and how it &lt;strong&gt;feels&lt;/strong&gt; to use Tama. My conclusion: Tama itself is great, it feels much better than React in terms of "Freedom", but all-around reactivity is tedious at complex data structures, though the state-management overall is nice too.&lt;/p&gt;

&lt;p&gt;That's why now I will be focusing on providing more appealing and familiar way for data-modeling and state-management through React hooks and maybe something else. Only then I will switch back to "cosmetics", "ergonomics" and polishing. I will do that in &lt;a href="https://github.com/denshya/reactive" rel="noopener noreferrer"&gt;this Reactivity library&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I also implemented a documentation website with SSR and benchmarks for it, so take a look:&lt;br&gt;
&lt;a href="https://github.com/pinely-international/tama/tree/main/docs/ssr" rel="noopener noreferrer"&gt;https://github.com/pinely-international/tama/tree/main/docs/ssr&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/pinely-international/tama/tree/main/benchmarks/ssr" rel="noopener noreferrer"&gt;https://github.com/pinely-international/tama/tree/main/benchmarks/ssr&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For now, I'm suspending new releases until I figure a new data-modeling strategy and util I'm generally satisfied with the quality of the library. The new releases will definitely be resumed in the new year 2026! 😁&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Changed
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;feat: add &lt;code&gt;disableJSXCache&lt;/code&gt; flag&lt;/li&gt;
&lt;li&gt;Fix typos in README&lt;/li&gt;
&lt;li&gt;Remove unnecessary logic&lt;/li&gt;
&lt;li&gt;Refactor code&lt;/li&gt;
&lt;li&gt;Migrate &lt;code&gt;Symbol.subscribe&lt;/code&gt; to &lt;code&gt;subscribe&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add Multiple on Events Binding - issue #33&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;Mount&lt;/code&gt; for conditional mounting per attribute&lt;/li&gt;
&lt;li&gt;Integrate TransitionAPI state handling with tests&lt;/li&gt;
&lt;li&gt;feat(lifecycle): Add life.scoped and hook enter into component constructor &lt;/li&gt;
&lt;li&gt;Renaming to "Tama"&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;Tama.Ref&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;feat(lifecycle): Support cleanup functions in Life.scoped&lt;/li&gt;
&lt;li&gt;Update &lt;code&gt;CONTRIBUTING.md&lt;/code&gt; with AI usage guidelines&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;ref&lt;/code&gt; attribute&lt;/li&gt;
&lt;li&gt;Add SSR Benchmarks&lt;/li&gt;
&lt;li&gt;Implement Documentation Website with Tama itself&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  New Contributors
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;bittere made their first contribution in &lt;a href="https://github.com/pinely-international/tama/pull/97" rel="noopener noreferrer"&gt;https://github.com/pinely-international/tama/pull/97&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;1amKhush made their first contribution in &lt;a href="https://github.com/pinely-international/tama/pull/100" rel="noopener noreferrer"&gt;https://github.com/pinely-international/tama/pull/100&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;meetdhorajiya made their first contribution in &lt;a href="https://github.com/pinely-international/tama/pull/107" rel="noopener noreferrer"&gt;https://github.com/pinely-international/tama/pull/107&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Divayang-2006 made their first contribution in &lt;a href="https://github.com/pinely-international/tama/pull/126" rel="noopener noreferrer"&gt;https://github.com/pinely-international/tama/pull/126&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>news</category>
      <category>frontend</category>
      <category>showdev</category>
    </item>
    <item>
      <title>New Framework Ripple? What about Others?</title>
      <dc:creator>Valery Zinchenko</dc:creator>
      <pubDate>Sat, 13 Sep 2025 11:10:48 +0000</pubDate>
      <link>https://dev.to/denshya/new-framework-ripple-what-about-others-3mc8</link>
      <guid>https://dev.to/denshya/new-framework-ripple-what-about-others-3mc8</guid>
      <description>&lt;p&gt;That's funny how people who already has media traction can sell basically anything - unfinished, unpolished project that repeats Vuejs with React style.&lt;/p&gt;

&lt;p&gt;It's not something bad actually, but the way it's done is just killing me slow. Ripple is not unique, on my way of creating &lt;em&gt;actually new framework&lt;/em&gt; - &lt;a href="https://github.com/pinely-international/proton" rel="noopener noreferrer"&gt;Proton&lt;/a&gt;, I've seen so many frameworks like Ripple, so I don't really understand how people are attracted to THIS, while not attracted to anything else that really changing it.&lt;/p&gt;

&lt;p&gt;Yeah, I guess that's just marketing, now you have to &lt;strong&gt;sell&lt;/strong&gt; a open source project. Imagine how many projects die that could've changed the industry because they didn't have enough of media resource? - Probably a lot.&lt;/p&gt;

&lt;p&gt;Why Ripple even got attention? It uses JSX, while actually not, because it uses its own &lt;code&gt;.ripple&lt;/code&gt; files, which simply means entirely new syntax parser. It parasitize on what's loved by community and includes by what's hated, but still sold.&lt;/p&gt;

&lt;p&gt;Maybe it's giving something better than reactive &lt;code&gt;$&lt;/code&gt; that Vuejs has already been doing forever?&lt;/p&gt;

&lt;p&gt;A new syntax of mapping an array? Wait! Angular has already doing that.&lt;/p&gt;

&lt;p&gt;You can declare components with &lt;code&gt;component&lt;/code&gt; keyword - OMG, WTF, so you're saying I'm so idiot that I need a special keyword to declare a component?&lt;/p&gt;

&lt;p&gt;JavaScript directly in the html? Mmm, is this some kind of punishment? I think there is a reason why developer community is up to &lt;code&gt;{{foo}}&lt;/code&gt; syntax...&lt;/p&gt;

&lt;p&gt;Maybe a nice tree-shaking? SSR speed? Small bundle size? Customization? Anything actually new? Well It's basically a mix of several frameworks &lt;strong&gt;without&lt;/strong&gt; any change, and I'm afraid it inherits the worst qualities of all of them rather than vice versa.&lt;/p&gt;

&lt;p&gt;So what, people are dumb? - No, people are trustful, they trust in people they are already subscribed to, so they eat what they give, even if it's undercooked meat.&lt;/p&gt;

&lt;p&gt;Why youtubers advertise this? - Because &lt;strong&gt;they&lt;/strong&gt; are dumb... well I mean they just ride on a hype wave :(&lt;/p&gt;

&lt;h2&gt;
  
  
  What then?
&lt;/h2&gt;

&lt;p&gt;Can we just appreciate some open source projects that really require attention?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Back the builders, not the buzz, spotlight open source that actually make a move.&lt;/li&gt;
&lt;li&gt;Stop applauding noise, promote projects that solve real problems.&lt;/li&gt;
&lt;li&gt;Discover, star and support under-the-radar projects.&lt;/li&gt;
&lt;/ol&gt;




&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/pinely-international/proton" rel="noopener noreferrer"&gt;Support Proton with a ⭐&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/reactivehtml/rimmel" rel="noopener noreferrer"&gt;rimmel&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/kitajs/html" rel="noopener noreferrer"&gt;kitajs&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>opensource</category>
      <category>discuss</category>
    </item>
    <item>
      <title>TamaJs Core - No Root Components</title>
      <dc:creator>Valery Zinchenko</dc:creator>
      <pubDate>Sun, 06 Jul 2025 09:52:37 +0000</pubDate>
      <link>https://dev.to/denshya/rootless-unframed-framework-2gdh</link>
      <guid>https://dev.to/denshya/rootless-unframed-framework-2gdh</guid>
      <description>&lt;p&gt;Building a rootless framework is difficult, but still &lt;a href="https://github.com/pinely-international/tama" rel="noopener noreferrer"&gt;TamaJs&lt;/a&gt; was built with a very intentional design choice: its components are allowed to return anything - from DOM Nodes, to primitives, and &lt;code&gt;null&lt;/code&gt;/&lt;code&gt;undefined&lt;/code&gt;. This flexibility is not a bug, but a feature. However, this freedom comes with sharp edges: when &lt;code&gt;null&lt;/code&gt; is returned, no anchor is created, and the view replacement logic has nothing to latch onto.&lt;/p&gt;

&lt;p&gt;One of core goals of Tama is to eliminate the concept of "Root Components" entirely and embrace fully "Atomic Components" - meaning self-contained, relocatable, and behaviorally independent.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Another layout&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;),&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;_000&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;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Some layout&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;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;componentView1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;inflator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inflate&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;componentView2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;inflator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inflate&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// These should be two independent component nodes with identical reactive behavior.&lt;/span&gt;
&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&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;componentView1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;componentView2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;setTimeout&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="c1"&gt;// And they should be moveable across the DOM freely.&lt;/span&gt;
  &lt;span class="nx"&gt;anotherElement&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;componentView2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;componentView1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="nx"&gt;_000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is where complications begin to surface. Without an anchor or predictable rendering footprint, &lt;code&gt;null&lt;/code&gt; becomes a dead-end.&lt;/p&gt;

&lt;p&gt;These problems (dynamic mounts, node independence, movable view layers) are elegantly solved by &lt;a href="https://github.com/framemuse/node-group" rel="noopener noreferrer"&gt;&lt;code&gt;node-group&lt;/code&gt; library&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing &lt;code&gt;Group&lt;/code&gt; node
&lt;/h2&gt;

&lt;p&gt;The design of &lt;code&gt;Group&lt;/code&gt; is a practical implementation of the &lt;a href="https://github.com/whatwg/dom/issues/736" rel="noopener noreferrer"&gt;&lt;code&gt;DocumentPersistentFragment&lt;/code&gt; proposal&lt;/a&gt;, aiming to cover its core aspects in current browsers. The proposal envisions a fragment that can persist beyond a single parent and avoid surrogate wrapper elements. &lt;code&gt;node-group&lt;/code&gt; approximates these goals today by leveraging custom elements and live synchronization.&lt;/p&gt;

&lt;h3&gt;
  
  
  Alignment with the Proposal
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Persistent Fragment Semantics&lt;/strong&gt;&lt;br&gt;
The proposal defines a &lt;code&gt;DocumentPersistentFragment&lt;/code&gt; that its children remains even when its was attached to a parent. In &lt;code&gt;node-group&lt;/code&gt;, it follows this precisely.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;Group&lt;/code&gt; instance can be reparented at any time. When appended to a new parent, its associated nodes removed from the previous one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Zero-Wrapper Behavior&lt;/strong&gt;&lt;br&gt;
The proposal discussion emphasizes avoiding synthetic wrapper elements. &lt;code&gt;node-group&lt;/code&gt; uses a non-rendering custom element that emits no visual footprint. To engines, the &lt;code&gt;Group&lt;/code&gt; nodes appear as true direct children, preserving CSS, Box Model and Layout consistency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Live Mutation Tracking&lt;/strong&gt;&lt;br&gt;
While the spec would rely on low-level fragment mutation observers, &lt;code&gt;node-group&lt;/code&gt; hooks into the Custom Elements API (&lt;code&gt;connectedCallback&lt;/code&gt;/&lt;code&gt;disconnectedCallback&lt;/code&gt;) to detect when a relay enters or leaves the DOM. It then streams &lt;code&gt;append&lt;/code&gt;, &lt;code&gt;remove&lt;/code&gt;, and &lt;code&gt;move&lt;/code&gt; operations to the targeted parent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Group Usage Example&lt;/strong&gt;&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;Group&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;node-group&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;group&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Group&lt;/span&gt;
&lt;span class="nx"&gt;group&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="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;header&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&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;main&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&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;footer&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;content&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;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;content&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;group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;setTimeout&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;note&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;aside&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;note&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Persistent Fragment in action&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="nx"&gt;group&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;note&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Group&lt;/code&gt; not only solves TamaJs dynamic mounting challenges, but also opens up door for future enhancements.&lt;/p&gt;




&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/pinely-international/tama" rel="noopener noreferrer"&gt;Support Tama with a ⭐&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/denshya" rel="noopener noreferrer"&gt;Denshya Movemenet&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.pinely.eu/" rel="noopener noreferrer"&gt;Pinely International&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>opensource</category>
      <category>showdev</category>
    </item>
    <item>
      <title>A React Alternative That Turned out Better than I Thought</title>
      <dc:creator>Valery Zinchenko</dc:creator>
      <pubDate>Tue, 01 Jul 2025 13:35:01 +0000</pubDate>
      <link>https://dev.to/denshya/this-react-alternative-turned-out-better-than-i-thought-4ggf</link>
      <guid>https://dev.to/denshya/this-react-alternative-turned-out-better-than-i-thought-4ggf</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;I was always striving for something better, first I was making my own little tools working with JQuery, then I started learning more about VanilaJS, after all I found React. It was a Heaven that day, but learning deeply was really something incredible difficult and felt like hell.&lt;/p&gt;

&lt;p&gt;Now I'm very used to React, I don't even think about how things work anymore, I'm just building - which is great! Unless you want to strive for more.&lt;/p&gt;

&lt;p&gt;While learning React I was trying out how I could build application with different architectures. The thing I figured out is that &lt;strong&gt;everything is possible&lt;/strong&gt;, but you need &lt;strong&gt;hooks&lt;/strong&gt; :)&lt;/p&gt;

&lt;p&gt;This means you can't use your tools you've been developing and polishing for years in another frameworks or just in VanilaJS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limits are Reached
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz31b5swsswi0mijfteew.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz31b5swsswi0mijfteew.webp" alt=" " width="285" height="285"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While figuring out architecture patterns and how I can organize things with React, I realize I can't go even further just because &lt;strong&gt;React itself&lt;/strong&gt; doesn't allow me to do so, I can't really &lt;strong&gt;customize&lt;/strong&gt; it. It might seem like too much, but that's maybe just for you as a user-developer, but for as Developer-Tools developer, that's something I'm missing very much.&lt;/p&gt;

&lt;p&gt;The complexity of React is not going anywhere, they can't fix it, it wouldn't be React anymore. It's easily proven by React Team themself since they Pre-Released React Compiler, which should help avoid that fundamental complexity - even they understand that it can't be fixed.&lt;/p&gt;

&lt;p&gt;That's why some developers choose other frameworks over React like Angular, Vue, Svelte, SolidJS, ...&lt;/p&gt;

&lt;h2&gt;
  
  
  Tired 😩
&lt;/h2&gt;

&lt;p&gt;I'm honestly tired from React, that's true that it's my Money-Making machine and that's a tool I can use to quickly build something - even faster than AI as for now. However, I'm striving for even better reality and I'm really tired of using this one tool for too long with not so many improvements.&lt;/p&gt;

&lt;p&gt;Like why I need that &lt;code&gt;useOptimistic&lt;/code&gt; if I could build that hook on my own, just let me do that - they don't.&lt;/p&gt;

&lt;p&gt;Maybe let me introduce at least ONE SINGLE new attribute so I don't suffer  with importing a function over and over again, why I can't just do that?&lt;/p&gt;

&lt;p&gt;Is that really so difficult?&lt;br&gt;
&lt;code&gt;&amp;lt;div classBEM={["base", { active: true }]} /&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Sketching into Reality
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fll7fuxa7b56599lxav88.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fll7fuxa7b56599lxav88.gif" alt=" " width="444" height="666"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When I had enough of it, I just started sketching the better React and was a chaos to be honest. I was imagining a beast, but eventually I took the practical approach and simplified many things, it took almost a whole year to just sketch what I wanted - It took another year to reach several severe goals I wanted.&lt;/p&gt;

&lt;p&gt;Now I'm ready to give something I'm proud of&lt;br&gt;
&lt;a href="https://denshya.github.io/proton/learn/" rel="noopener noreferrer"&gt;https://denshya.github.io/proton/learn/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is something between React, SolidJS and VanilaJS - you can create components almost like in React with Observables like in SolidJS, while attaching Components like regular VanilaJS elements!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quick Example&lt;/strong&gt;&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;function&lt;/span&gt; &lt;span class="nf"&gt;RangeApp&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;progress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;State&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&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;input&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;range&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;min&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;100&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;step&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;progress&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&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;progress&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;progress&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;100&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;progress&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;/progress&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="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Reset&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;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&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;inflator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;WebInflator&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AppView&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;inflator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inflate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&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;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;"&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;AppView&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// And you can move it arround.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why it's better
&lt;/h2&gt;

&lt;p&gt;If you're too lazy to the whole docs, I will give a quick list of why I would prefer Proton over React for the next project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No hooks - Do things and reuse them anywhere (even in React).&lt;/li&gt;
&lt;li&gt;Observables - no need to rely on Component lifecycle, I can design and develop state flows and then use/reuse them in components or directly in elements as globals.&lt;/li&gt;
&lt;li&gt;Customization - I can add my own attributes to elements and even render DOM Nodes directly to JSX.&lt;/li&gt;
&lt;li&gt;No root hijacking - I'm just building components and then put them as see it fits - all the components can be Root Components right now.&lt;/li&gt;
&lt;li&gt;Super lightweight - I'm an extreme footprint optimizer, so for me saving 200kb of code means a lot! Proton is just ~5kb!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Seemingly Successful Road
&lt;/h2&gt;

&lt;p&gt;In the beginning I tried it on my own personal projects - it was not so good, I was really questioning if it's even worth continuing building.&lt;/p&gt;

&lt;p&gt;But now I'm building a website for the company I'm working at (&lt;a href="https://dev.pinely.eu/" rel="noopener noreferrer"&gt;Pinely&lt;/a&gt;) and we're planning to spread it to another projects we had if clients do not mind.&lt;/p&gt;

&lt;p&gt;So I think it's somewhat a success for me, I've been inspired by many people and library I've seen outer no one is looking at - so I want to say thanks to these libraries as well:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/WebReflection/uhooks" rel="noopener noreferrer"&gt;https://github.com/WebReflection/uhooks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/WebReflection/usignal" rel="noopener noreferrer"&gt;https://github.com/WebReflection/usignal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/WebReflection/dom-augmentor" rel="noopener noreferrer"&gt;https://github.com/WebReflection/dom-augmentor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/WebReflection/heresy-ssr" rel="noopener noreferrer"&gt;https://github.com/WebReflection/heresy-ssr&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ReactiveHTML/rimmel" rel="noopener noreferrer"&gt;https://github.com/ReactiveHTML/rimmel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/snabbdom/snabbdom" rel="noopener noreferrer"&gt;https://github.com/snabbdom/snabbdom&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/yelouafi/unReact" rel="noopener noreferrer"&gt;https://github.com/yelouafi/unReact&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/kitajs/html" rel="noopener noreferrer"&gt;https://github.com/kitajs/html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/denshya/proton" rel="noopener noreferrer"&gt;Support Proton with a ⭐&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/denshya" rel="noopener noreferrer"&gt;Denshya Movemenet&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.pinely.eu/" rel="noopener noreferrer"&gt;Pinely International&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>react</category>
      <category>showdev</category>
    </item>
    <item>
      <title>SSR with Full DOM Support</title>
      <dc:creator>Valery Zinchenko</dc:creator>
      <pubDate>Mon, 14 Apr 2025 06:13:00 +0000</pubDate>
      <link>https://dev.to/denshya/proton-pluggable-ssr-dom-or-how-i-implemented-better-ssr-from-scratch-4hl8</link>
      <guid>https://dev.to/denshya/proton-pluggable-ssr-dom-or-how-i-implemented-better-ssr-from-scratch-4hl8</guid>
      <description>&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;I have never worked with SSR, but recently I was tasked with that and it was somewhat challenging. I found out that usually you can't use much DOM things in your SSR components - sheesh, that's frustrating. As someone who loves the flexibility of the full browser environment, I felt defeated. I thought, “There has to be a better way.”&lt;/p&gt;

&lt;p&gt;So I decided that &lt;strong&gt;my SSR&lt;/strong&gt; will support all the DOM and it actually turned out better than I expected...&lt;/p&gt;

&lt;h2&gt;
  
  
  DOM Limitations
&lt;/h2&gt;

&lt;p&gt;Traditional SSR setups usually come with a set of constraints that simplify the rendering process, but at the cost of the natural browser experience. In many systems, SSR components are stripped of access to a rich DOM API, meaning you can't use many of the things that DOM naturally provides in a client-rendered app. This not only makes development cumbersome but also forces to adopt workarounds. 😠&lt;/p&gt;

&lt;p&gt;It was clear that the conventional way wasn't meeting my needs as a developer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dedication
&lt;/h2&gt;

&lt;p&gt;What if SSR could support the full browser environment, including unrestricted DOM access? That's when I set out to create a solution that didn't require a dedicated SSR build.&lt;/p&gt;

&lt;h2&gt;
  
  
  Full DOM Support in SSR
&lt;/h2&gt;

&lt;p&gt;First I take a look at how other libraries/frameworks implement SSR and found out that they either simply &lt;strong&gt;don't&lt;/strong&gt; implement DOM at all or implement the least of it (like &lt;a href="https://lit.dev/" rel="noopener noreferrer"&gt;Lit&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;I tried to copy-paste the Lit implementation and tried using it, but was &lt;strong&gt;disappointing&lt;/strong&gt; as it was merely a boilerplate without actual DOM rendering and without working features like HTML elements at least.&lt;/p&gt;

&lt;p&gt;I tried using JSDOM for that purpose - it magically worked, but when I setup my first performance benchmark - it was &lt;strong&gt;disappointing&lt;/strong&gt;. I realize I either should abandon this idea or implement my own JSDOM.&lt;/p&gt;

&lt;p&gt;I looked into the JSDOM code and saw a gigantic codebase - phew...&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ok, I don't need ALL the features to actually work but just &lt;strong&gt;some&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nah, I took a third path - looking for alternatives to &lt;a href="https://github.com/jsdom/jsdom" rel="noopener noreferrer"&gt;JSDOM&lt;/a&gt;... And I found it - &lt;a href="https://github.com/capricorn86/happy-dom" rel="noopener noreferrer"&gt;&lt;code&gt;happy-dom&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It stated that it's ... Mmm... It's better at everything at least 10x. So I decided to use it.&lt;/p&gt;

&lt;p&gt;The simple function I came with that just works was like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;Window&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;happy-dom&lt;/span&gt;&lt;span class="dl"&gt;"&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;injectDOMPolyfill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;globalThis&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="nb"&gt;window&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Window&lt;/span&gt;

  &lt;span class="k"&gt;for &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;key&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getOwnPropertyNames&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// @ts-expect-error ok.&lt;/span&gt;
      &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="c1"&gt;// eslint-disable-next-line @typescript-eslint/no-unused-vars&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="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// skip&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;requestAnimationFrame&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&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;callback&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="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;2&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;
  
  
  JSX Optimization
&lt;/h2&gt;

&lt;p&gt;This time, before benchmarking anything, since it was clear that I need to optimize how JSX elements are stringified (turned into a string) myself (I was purely relying on &lt;code&gt;document.documentElement.outerHTML&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;I developed &lt;a href="https://github.com/pinely-international/tama/blob/main/src/jsx/JSXSerializer.ts" rel="noopener noreferrer"&gt;&lt;code&gt;JSXSerializer&lt;/code&gt;&lt;/a&gt; class, which is standalone but able to inherit  &lt;a href="https://github.com/pinely-international/tama/blob/main/src/Inflator/web/WebInflator.ts" rel="noopener noreferrer"&gt;&lt;code&gt;WebInflator&lt;/code&gt;&lt;/a&gt; configs. And it does serialization as you can tell.&lt;/p&gt;

&lt;p&gt;It worked ~8x faster than React, so I thought it's cool and it's just 1kb of code.&lt;/p&gt;

&lt;p&gt;Now I was prepared to do benchmarking - it was AMAZING, it scored way more than Next or React and even 5% better than Solidjs, but frameworks like Vuejs and Svelte were 25% ahead in performance than TamaJs.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Which makes sense since they are string based from the beginning comparing to JSX, which is first creates objects and only then being converted into strings.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Assets Problem
&lt;/h2&gt;

&lt;p&gt;When setting up basic server to test my solution and ended up with a lot unnecessary code, but it was somehow working (&lt;em&gt;after 50 hours of suffering&lt;/em&gt;). Working, but not displaying any images nor loading CSS correctly, I was &lt;strong&gt;disappointed&lt;/strong&gt;. However this time it was clearly fixable as the incorrectness came from incorrect paths.&lt;/p&gt;

&lt;p&gt;Briefly saying: My imports of images were resolved to absolute path of the system like &lt;code&gt;import MyImagePNG from "./my-image.png"&lt;/code&gt; to &lt;code&gt;/home/user/project/src/component/my-image.png&lt;/code&gt;, which is clearly not where my image is located in the WEB.&lt;/p&gt;

&lt;p&gt;This time it really made my brain flexing, the question was&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How do I customize import resolution?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It first seemed like impossible until I googled. I found that Bun supports  runtime plugins via &lt;code&gt;Bun.plugin&lt;/code&gt; API, which to my surprise and fortune supported changing import resolution behavior.&lt;/p&gt;

&lt;p&gt;That's where I came up with my first plugin in Bun&lt;br&gt;
&lt;a href="https://github.com/FrameMuse/bun-vite-assets-import/blob/main/bun-plugin.ts" rel="noopener noreferrer"&gt;Here's the code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ok, now I can modify &lt;strong&gt;where&lt;/strong&gt; my assets imports are resolved to.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How do I specify where &lt;strong&gt;exactly&lt;/strong&gt; they should be resolved to?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Was my next question, which basically broke my brain... I came up with several ideas, all of them wasn't that great.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;So Vite places assets into &lt;code&gt;./assets&lt;/code&gt; folder - cool, it adds hash suffix to each file - sheesh. Ok I just need to figure what the hashing method is and the reuse it. Nope, I simply couldn't find anything useful, even though I kinda found the script for Vite hashing, but it turned out to be arbitrary, which means developer can override it in the config or even disable the hashing entirely.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So I decided to use additional build step - yeah now this contradicts with the article banner... Nonetheless, I continue and implemented &lt;strong&gt;the second&lt;/strong&gt; plugin for Vite&lt;br&gt;
&lt;a href="https://github.com/FrameMuse/bun-vite-assets-import/blob/main/vite-plugin.ts" rel="noopener noreferrer"&gt;Here's the code&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Entry points
&lt;/h2&gt;

&lt;p&gt;As for basically all the frameworks and for SSR generally, it's a standard to have two entry points and thus two builds. I thought I can go with one, so what I did instead was simply exporting the &lt;a href="https://github.com/pinely-international/tama/blob/main/src/Inflator/web/WebInflator.ts" rel="noopener noreferrer"&gt;&lt;code&gt;WebInflator&lt;/code&gt;&lt;/a&gt; instance and using in the &lt;code&gt;index.ts&lt;/code&gt; (or &lt;code&gt;main.tsx&lt;/code&gt;), which was used in the &lt;code&gt;index.html&lt;/code&gt;, which is the client entry point. And that's it.&lt;/p&gt;

&lt;p&gt;So it means, you don't need to modify your code or care about client/server sides in your Frontend App, you don't have to touch if want SSR, just use it or don't - that's up to your use case.&lt;/p&gt;

&lt;p&gt;Want SSR? - Put the plugins and that's it!&lt;/p&gt;
&lt;h2&gt;
  
  
  Server Setup
&lt;/h2&gt;

&lt;p&gt;Now it was the time to clean up the mess after my experiments with SSR, DOM and Import Resolution. Additionally, my use-case required Initial Data loading, but with this setup it was just a breeze to implement.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;server.ts&lt;/code&gt; code looks like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;compression&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;compression&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;express&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;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;sirv&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;sirv&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;injectDOMPolyfill&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;./dom&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;getInitialData&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;../src/initial-data&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;PORT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;45678&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;BASE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BASE&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;


&lt;span class="c1"&gt;// Load HTML template.&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;templateHTML&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;Bun&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./build/index.html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nx"&gt;templateHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;templateHTML&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replaceAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;*|&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sr"&gt;/gm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Minimize.&lt;/span&gt;

&lt;span class="c1"&gt;// Serve.&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;compression&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;BASE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;sirv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./build&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;extensions&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="c1"&gt;// SSR happens here.&lt;/span&gt;

&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&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="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;injectInitialData&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;initialDataJSON&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__INITIAL_DATA__&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;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;templateHTML&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;!--element--&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;jsxSerializer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;componentToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AppRoot&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;!--initial-data--&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`&amp;lt;script&amp;gt;window.__INITIAL_DATA__=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;initialDataJSON&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/script&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&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;text/html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;html&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="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Server error&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="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&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="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Server started at http://localhost:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// Polyfill DOM.&lt;/span&gt;

&lt;span class="nf"&gt;injectDOMPolyfill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;globalThis&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;[SSR] DOM polyfilled&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;Bun&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;plugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;assetsImportResolution&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;assets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;sourceAssetsMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assets&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}))&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;[SSR] Resolving imports to Vite Build Assets&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Inject initial data for app modules import&lt;/span&gt;
&lt;span class="c1"&gt;// as they may use the initial data immediately.&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;injectInitialData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;// Load app modules.&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;WebJSXSerializer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@denshya/proton&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;appInflator&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/app/inflator&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AppRoot&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/app/AppRoot&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Setup serializer.&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jsxSerializer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;WebJSXSerializer&lt;/span&gt;
&lt;span class="nx"&gt;jsxSerializer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inherit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;appInflator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;[SSR] Ready to render app&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&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;injectInitialData&lt;/span&gt;&lt;span class="p"&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="nx"&gt;globalThis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__INITIAL_DATA__&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;getInitialData&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="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="c1"&gt;// Gracefully.&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;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I implemented 2 little plugins in Vite and Bun, so that SSR can resolve assets imports of the client app directly to the static build.&lt;/p&gt;

&lt;p&gt;I used Express, Bun and Vite. I didn't introduced any new build for Vite, so it was building only once - just the client bundle with the bundle assets map. There were no modifications to the codebase since the DOM is fully supported (for real) and you don't have to care about server-side/client-side things.&lt;/p&gt;

&lt;p&gt;At this point I realized - it's Plug &amp;amp; Play SSR, it doesn't require dedicated SSR build (but a bundle map generated by plugin) and fully support browser environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cloud
&lt;/h2&gt;

&lt;p&gt;Unfortunately, this doesn't fit to cloud computing architecture, it works only with static assets, build and source code all placed in the same server, so it needs a further evolution that it can be implemented in Cloud (like AWS and Google Cloud).&lt;/p&gt;

&lt;p&gt;I'm working on it, so follow me for further news.&lt;/p&gt;




&lt;p&gt;I invite you to experiment with this approach, test out the plugins, and share feedback. There's always room for improvement, and I'm excited to see how this idea can evolve further with community input.&lt;/p&gt;

&lt;p&gt;Have you encountered similar challenges with SSR, or do you know of other innovative approaches?&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>opensource</category>
      <category>frontend</category>
      <category>javascript</category>
    </item>
    <item>
      <title>The Prove of No-Framework principal - TamaJs</title>
      <dc:creator>Valery Zinchenko</dc:creator>
      <pubDate>Thu, 10 Apr 2025 06:23:00 +0000</pubDate>
      <link>https://dev.to/denshya/framework-less-framework-11i3</link>
      <guid>https://dev.to/denshya/framework-less-framework-11i3</guid>
      <description>&lt;p&gt;In my &lt;a href="https://dev.to/framemuse/no-framework-principle-arised-2n39"&gt;previous blog post&lt;/a&gt; I introduced the &lt;strong&gt;No Framework&lt;/strong&gt; principle and argued that enforcing a rigid framework can sometimes stifle creativity and control. Today I'm excited to take that conversation a step further by introducing a new twist in this journey — the &lt;strong&gt;Framework-less Framework&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Philosophy Behind
&lt;/h2&gt;

&lt;p&gt;Traditional frameworks, while immensely popular, often come with a set of built-in "primitives" and hidden implementations that dictate how you build your applications. They're designed to abstract away the complexities of DOM manipulation and state management, but this also means you sometimes lose direct control over the inner workings of your UI.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Framework-less Framework&lt;/strong&gt; concept embraces the idea of &lt;em&gt;no framework&lt;/em&gt; in the sense that it strips away these superstructures, exposing open internals and giving you the flexibility to shape your UI as you see fit. It's about having a lean, minimalistic foundation that handles the essentials while letting you extend, experiment, and even replace parts as your project grows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing &lt;strong&gt;TamaJs&lt;/strong&gt;: A (No)Framework Library
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Or just read &lt;a href="https://github.com/pinely-international/tama" rel="noopener noreferrer"&gt;README&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is a fast, lightweight (around 5kb gzip) and component-based UI builder that embodies the no-framework philosophy. You can check it out on GitHub: &lt;a href="https://github.com/pinely-international/tama" rel="noopener noreferrer"&gt;denshya/tama&lt;/a&gt;. Tama isn't meant to become the next giant framework that monopolizes your codebase; instead, it's a tool that gives you the potential to build app and manage your UI the way you see it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Pillars of Tama
&lt;/h3&gt;

&lt;p&gt;Tama's design is built on four foundational pillars:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No Framework&lt;/strong&gt;: It liberates you from the heavy abstractions of typical frameworks, giving you direct control over the rendered output.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open Internals&lt;/strong&gt;: Every part of Tama is exposed and customizable, ensuring that you're never stuck with hidden magic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fault Tolerance&lt;/strong&gt;: Robust enough to handle errors gracefully while giving you tools like error boundaries and context APIs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customization&lt;/strong&gt;: From JSX mapping straight to DOM elements to flexible event handling and custom attribute management, Tama is designed with extension in mind.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These pillars reflect the beliefs I shared in my previous post, where I argued for simplicity and transparency over abstraction and obfuscation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exploring Tama Through Code
&lt;/h2&gt;

&lt;p&gt;Let's look at some of the basic examples and usage patterns that Tama makes available:&lt;/p&gt;

&lt;h3&gt;
  
  
  Quick Start
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bun i @denshya/tama
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For TypeScript and JSX support, add the following snippet to your &lt;code&gt;tsconfig.json&lt;/code&gt; or &lt;code&gt;jsconfig.json&lt;/code&gt;:&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;"compilerOptions"&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;"jsx"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-jsx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"jsxImportSource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@denshya/tama"&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;Once configured, you can get started by creating a simple component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&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;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello World!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;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;inflator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;WebInflator&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;appView&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;inflator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inflate&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;/&amp;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;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;replaceChildren&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;appView&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see how this is rather standalone and unbound comparing to things you've seen before.&lt;/p&gt;

&lt;p&gt;See a &lt;a href="https://stackblitz.com/~/github.com/denshya/tama-template" rel="noopener noreferrer"&gt;playground&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Observables and State
&lt;/h3&gt;

&lt;p&gt;Instead of relying on a built-in state management, Tama treats any object with a &lt;code&gt;Symbol.subscribe&lt;/code&gt; method as an observable. This opens up declarative and fine-grained UI updates just like &lt;a href="https://www.solidjs.com/" rel="noopener noreferrer"&gt;SolidJs&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ProductCard&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;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;State&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Title&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;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;State&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Image source&lt;/span&gt;&lt;span class="dl"&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;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"product-card__title"&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;div&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;img&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"product-card__image"&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Preview"&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;input&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&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;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;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;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See &lt;a href="https://github.com/pinely-international/tama/#states-observables" rel="noopener noreferrer"&gt;implementation of &lt;code&gt;State&lt;/code&gt;&lt;/a&gt; class.&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom JSX Attributes and Rendering
&lt;/h3&gt;

&lt;p&gt;Tama supports React-like JSX but maps it directly to the DOM. This means you're free to pass any value—primitive or object—into your JSX attributes. Moreover, Tama allows you to define &lt;strong&gt;custom JSX attributes&lt;/strong&gt;. For instance, if you want to override the default &lt;code&gt;className&lt;/code&gt; with a dynamic set of CSS modifiers, you can do so like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;inflator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;WebInflator&lt;/span&gt;
  &lt;span class="nx"&gt;inflator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsxAttributes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;classMods&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;className&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;bem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nf"&gt;castArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&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;Moreover, you can define how you treat values put into JSX as children:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;inflator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;WebInflator&lt;/span&gt;
&lt;span class="nx"&gt;inflator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;adapters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="err"&gt;{
  &lt;/span&gt;&lt;span class="nc"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inflator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inflator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;inflator&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;inflate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;MyObject&lt;/span&gt; &lt;span class="o"&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="k"&gt;return&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;div&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Do something cool.&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;This level of customization means you're not fighting against a rigid API—you're co-authoring it.&lt;/p&gt;




&lt;p&gt;The beauty of Tama is the freedom it provides. It does not lock you into a preordained structure or magic; instead, it exposes its internals and invites you to innovate. If you've ever felt that a framework was limiting your creative control, Tama offers a counterpoint: a toolkit that empowers you to build the UI exactly the way you want. In a sense, it is as much a challenge that encourages developers to rethink how they view UI libraries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Component API
&lt;/h2&gt;

&lt;p&gt;In Tama, components are constructed using functions that serve as both constructors and evaluators for &lt;code&gt;Tama.Component&lt;/code&gt;. This design allows developers to have direct control over the component's behavior and lifecycle.&lt;/p&gt;

&lt;p&gt;When a component function is invoked, an instance of &lt;code&gt;Tama.Component&lt;/code&gt; is automatically created and passed as the &lt;code&gt;this&lt;/code&gt; context to the function. This approach provides access to various APIs that manage the component's behavior.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;View API&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The View API manages the element displayed by a component. Developers can set or update the component's view using the &lt;code&gt;this.view.set&lt;/code&gt; method. 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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Tama&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello World!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt;

  &lt;span class="nf"&gt;setTimeout&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;I'm Replaced!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&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 this example, the component initially displays "Hello World!" and then updates to "I'm Replaced!" after one second. The View API facilitates dynamic content updates within components.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Async/Await Support&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Tama components can be asynchronous functions, enabling the use of &lt;code&gt;async/await&lt;/code&gt; for handling asynchronous operations. The View API is particularly useful in these scenarios:&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;MyView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Tama&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Loader&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;)&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&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;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;I'm loaded!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&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;In this example, a loader is displayed while waiting for the asynchronous operation to complete, after which the main content is rendered.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Error Boundaries&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Similar to React, Tama provides an interface to catch errors thrown in child components, including those occurring in event handlers:&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;Child&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Test&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Parent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Tama&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;this&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="nx"&gt;thrown&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* Handle error */&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;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Child&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&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;&lt;strong&gt;Context API&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Tama's Context API allows for the creation and consumption of context using classes:&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;class&lt;/span&gt; &lt;span class="nc"&gt;MyContext&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;value&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="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Child&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Tama&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&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;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MyContext&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;span&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;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&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;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Parent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Tama&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;provide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MyContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;value&lt;/span&gt;&lt;span class="dl"&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;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Child&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&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;By defining contexts as classes, it gives a developer complete freedom in how they define contexts since they can be anything, while also giving general structure and predictability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Proof of Concept
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Framework-less Framework&lt;/strong&gt; philosophy isn't about discarding all structure. It's about providing a flexible, transparent, and ultra-lightweight set of tools that let you decide what really matters in your application. Tama encapsulates this idea by giving you a robust set of primitives—state management, JSX transformation, observable handling, and more—without the bloat of an all-encompassing framework.&lt;/p&gt;

&lt;p&gt;I invite you to dive into the &lt;a href="https://github.com/pinely-international/tama" rel="noopener noreferrer"&gt;Tama library&lt;/a&gt; and experiment with building your next project with this no-framework approach.&lt;/p&gt;

&lt;p&gt;Remember this is a way to understand new possibilities and play around with alternative technologies. I'm trying to see what it can turn into.&lt;/p&gt;

&lt;h2&gt;
  
  
  For contributors and enthusiasts
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Idea behind Tama
&lt;/h3&gt;

&lt;p&gt;Beside what I mentioned above about Tama, it was created with a thought in mind that it can be very useful in Web Game Development as well, as its nature is atomic inflation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Movement
&lt;/h2&gt;

&lt;p&gt;Ideally, I want to make this much more than one single library, but create a whole new movement.&lt;/p&gt;

&lt;p&gt;I have plenty to do - pretty big roadmap, it includes various IDE plugins, remastering existing libraries, patterns/practices and forming a new way of thinking as a Web Developer.&lt;/p&gt;

&lt;p&gt;Generally, I'm trying to make Web Dev much easier and "entertaining" rather than vIbECoDiNg, LLMs are cool, but as a developer I want real vibe during development not Commercially Advertised. If you share my ideas, connect.&lt;/p&gt;

&lt;h2&gt;
  
  
  Eventually
&lt;/h2&gt;

&lt;p&gt;I encourage you to explore the &lt;a href="https://github.com/pinely-international/tama" rel="noopener noreferrer"&gt;Tama repository&lt;/a&gt; on GitHub. Fork it, extend it, share your projects, and contribute ideas. It's through this kind of community engagement that we redefine what it means to build UI efficiently and with minimal overhead &lt;em&gt;maybe&lt;/em&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/pinely-international/tama" rel="noopener noreferrer"&gt;Support Tama with a ⭐&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/denshya" rel="noopener noreferrer"&gt;Denshya Movemenet&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.pinely.eu/" rel="noopener noreferrer"&gt;Pinely International&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>webdev</category>
      <category>opensource</category>
      <category>frontend</category>
      <category>news</category>
    </item>
    <item>
      <title>No-Framework Principle in Frontend</title>
      <dc:creator>Valery Zinchenko</dc:creator>
      <pubDate>Fri, 04 Oct 2024 11:02:17 +0000</pubDate>
      <link>https://dev.to/denshya/no-framework-principle-arised-2n39</link>
      <guid>https://dev.to/denshya/no-framework-principle-arised-2n39</guid>
      <description>&lt;h2&gt;
  
  
  Statement
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;No-Framework Principle&lt;/strong&gt; in &lt;u&gt;Frontend Development&lt;/u&gt; states that Developer should not rely on framework utils/tools/methods to build &lt;a href="https://en.wikipedia.org/wiki/Dataflow" rel="noopener noreferrer"&gt;dataflow&lt;/a&gt; or &lt;a href="https://en.wikipedia.org/wiki/Data_structure" rel="noopener noreferrer"&gt;data structures&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Instead, Developer should rely on a language and well-known libraries to build and maintain them.&lt;/p&gt;

&lt;p&gt;Developer should go for a codebase that splits into two branches: Framework-Based and Framework-Free and provide another integration between. Shortly: good and isolated &lt;a href="https://simple.wikipedia.org/wiki/Application_programming_interface" rel="noopener noreferrer"&gt;APIs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The framework should take care of initiating, storing and reacting to updates of external data. On other hand, a Developer should choose right tools to better support the integration of the external data.&lt;/p&gt;

&lt;p&gt;Though there are cases when &lt;strong&gt;a part&lt;/strong&gt; of the flow could only be implemented in a way that is well-supported by framework. Or local object environments where data is not going beyond itself and has no &lt;a href="https://en.wikipedia.org/wiki/Side_effect_(computer_science)" rel="noopener noreferrer"&gt;side-effects&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem
&lt;/h2&gt;

&lt;p&gt;Writing components often involves establishing data flow/structures locally or between other components. This usually done by abusing framework (e.g. using React Hooks), which to accomplish correctly requires  learning the framework deeply that leads to a learning curve just to support a data flow/structure.&lt;/p&gt;

&lt;p&gt;Moreover, this tightly couples a data flow/structure to a framework, which kills reusability across other frameworks and puts additional burden to always stick to latest updates of the particular framework for maintenance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Afterward
&lt;/h2&gt;

&lt;p&gt;There is a noticeable movement to a similar paradigm, like this one: &lt;a href="https://pureweb.dev/" rel="noopener noreferrer"&gt;https://pureweb.dev/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And people are tend to ask for alternative approaches for handling reusability like bit.dev and such, which stores components in a specific way allowing better reusability across FrameWorks.&lt;/p&gt;

&lt;p&gt;The web itself is striving to provide much better support for native &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_components" rel="noopener noreferrer"&gt;Web Components&lt;/a&gt;&lt;br&gt;
&lt;a href="https://dev.to/brucou/comment/1ebij"&gt;Related comment to the topic of Components Composition&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Though I don't think we should just quit the FrameWorks, but rather they should be better optimized and adapted to handling, reusing and declaring the data-flow independently of their own code.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The original "&lt;a href="https://bitworking.org/news/2014/05/zero_framework_manifesto/" rel="noopener noreferrer"&gt;zero framework manifesto&lt;/a&gt;"&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.infoq.com/articles/functional-UI-introduction-no-framework/" rel="noopener noreferrer"&gt;Framework-Free at Last&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>javascript</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
