<?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: kwy404</title>
    <description>The latest articles on DEV Community by kwy404 (@kwy404).</description>
    <link>https://dev.to/kwy404</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1761111%2F3184e9b5-50fe-4a90-9603-2dfd8d31ab4d.png</url>
      <title>DEV Community: kwy404</title>
      <link>https://dev.to/kwy404</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kwy404"/>
    <language>en</language>
    <item>
      <title>What 99 merged pull requests taught me about contributing to big open source projects</title>
      <dc:creator>kwy404</dc:creator>
      <pubDate>Sat, 03 Oct 2026 01:27:04 +0000</pubDate>
      <link>https://dev.to/kwy404/what-99-merged-pull-requests-taught-me-about-contributing-to-big-open-source-projects-439b</link>
      <guid>https://dev.to/kwy404/what-99-merged-pull-requests-taught-me-about-contributing-to-big-open-source-projects-439b</guid>
      <description>&lt;p&gt;I recently passed 99 merged pull requests across 41 organizations: Google, Microsoft, Apple, Meta, NVIDIA, Netflix, Samsung, Uber, plus projects like Bootstrap, Excalidraw, three.js, MUI, Tailwind CSS and Puppeteer.&lt;/p&gt;

&lt;p&gt;None of them is a big feature. Almost all are small bug fixes, often under 15 lines including the test. This post is about how that works in practice: how I pick bugs, how I write a PR a maintainer can merge in two minutes, and the lessons I got from the times a maintainer said "not like this".&lt;/p&gt;

&lt;p&gt;Pick bugs you can prove&lt;br&gt;
The best contributions I made all had one thing in common: before touching the code, I could write a test that failed.&lt;/p&gt;

&lt;p&gt;I look for bugs in the boring places:&lt;/p&gt;

&lt;p&gt;Parsers and formatters. Edge cases like empty input, a trailing separator, a negative number, a character that needs escaping.&lt;br&gt;
Boundaries. &amp;lt; versus &amp;lt;=, off by one, a range that is empty.&lt;br&gt;
Unit conversions. Nanoseconds versus microseconds, rounding, sign handling.&lt;br&gt;
Places where two code paths should agree but don't. One branch escapes a value and the other one forgets.&lt;br&gt;
These bugs are small, but they are real, and someone somewhere is hitting them.&lt;/p&gt;

&lt;p&gt;Five bugs I enjoyed fixing&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;An HTML entity inside a regular expression (Red Hat, vscode-yaml). The auto indentation rule for YAML was supposed to indent after a key with an anchor, like base: &amp;amp;base. It never did. The pattern in language-configuration.json contained &amp;amp; instead of &amp;amp;, so it was looking for the literal text &amp;amp;. A one character fix, plus a test that reads the real config file. Then a maintainer found that &amp;amp;ref-erance still failed, because the pattern only allowed word characters after &amp;amp;. YAML anchors can contain almost anything, so the second commit fixed that too.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;One character in a drag and drop check (Meta, Lexical). Dropping dragged text exactly on the edge of its own selection deleted the text. The check used &amp;lt; where it needed &amp;lt;=. The maintainer extended the fix before merging, and the boundary change and the test stayed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;"60.0s" in a build log (ByteDance, Rsbuild). A build that took 59.96 seconds was logged as 60.0s, and one that took 119.96 seconds as 1m 60.0s. The function checked &amp;lt; 60 and split minutes and seconds on the raw value, and only rounded at the very end. Rounding first fixed both. Tiny, visible, and easy to test.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Decimal breakpoints in Tailwind CSS. Breakpoints in the same unit were compared with parseInt, which drops the fractional part, so 40.25rem and 40.5rem looked equal. min-[40.5rem] could be emitted before min-[40.25rem], and the smaller breakpoint won in the cascade. Switching to parseFloat fixed the order, with a test for decimal values.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A three.js geometry edge case. Line3.distanceSqToLine3() also writes the two closest points into optional targets. When both segments were degenerate (start equal to end), an early return computed the distance with c1.sub( c2 ), so c1 ended up holding a difference vector instead of a point. A previous fix had covered the general case but missed this branch. The test now checks both points for two degenerate segments.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;How I write the pull request&lt;br&gt;
Maintainers of big projects review a lot of PRs. Mine follow the same shape every time:&lt;/p&gt;

&lt;p&gt;Root cause first. One or two sentences that explain why the bug happens, not just what changed. "The pattern contains &amp;amp;, so it never matches &amp;amp;" is better than "Fix indentation".&lt;br&gt;
The fix. What I changed and why it is the smallest correct change.&lt;br&gt;
The test. A test that fails before the change and passes after it. I say that explicitly in the description, and I run it both ways before opening the PR.&lt;br&gt;
I also follow each repository's own conventions: commit message style, PR template, changelog or changeset files, CLA or DCO. Reading CONTRIBUTING.md before writing any code saves a round of review.&lt;/p&gt;

&lt;p&gt;Keep the diff small. A five line fix with a test gets merged in days. A refactor that "cleans things up while I'm here" sits for months.&lt;/p&gt;

&lt;p&gt;What maintainers taught me&lt;br&gt;
The most useful part of this was not the merges. It was the reviews.&lt;/p&gt;

&lt;p&gt;"Fix the cause, not the symptom." In one project I made a duration formatter handle negative values. The maintainer replied that negative durations should be impossible at that point and should never reach the formatter. They were right: the real issue was a function that passed a signed difference between two durations. I moved the fix there and left the formatter alone.&lt;/p&gt;

&lt;p&gt;"A narrow fix is not always worth the review." I fixed a host parsing bug for IPv6 addresses in a networking library. The maintainer explained that a one off IPv6 fix does not help much if the rest of the stack cannot run over IPv6 yet, and every PR costs review and CI time. That was a fair point, so I closed the PR. Sometimes the right contribution is an issue with a plan, not code.&lt;/p&gt;

&lt;p&gt;Maintainers often improve your fix. In Lexical the maintainer extended my change before merging. In Adobe's Spectrum Web Components a maintainer carried two of my fixes into their own PRs with co-author credit. In DataComPy the maintainer wrote an extra test for a two column key case. None of that is a rejection. It is how you learn how a codebase is meant to work.&lt;/p&gt;

&lt;p&gt;Small process details matter. One PR was approved and then blocked because the repository requires signed commits. Setting up commit signing took five minutes and unblocked it.&lt;/p&gt;

&lt;p&gt;A checklist you can steal&lt;br&gt;
Read CONTRIBUTING.md and the PR template before writing code.&lt;br&gt;
Search open and closed PRs and issues for the bug first. Someone may already be on it.&lt;br&gt;
Reproduce it with a failing test.&lt;br&gt;
Make the smallest change that fixes the root cause.&lt;br&gt;
Run the test without your change, then with it.&lt;br&gt;
Run the project's linters and formatters on the files you touched.&lt;br&gt;
Explain the root cause in the first lines of the description.&lt;br&gt;
Answer review comments quickly, and say thanks.&lt;br&gt;
Why bother&lt;br&gt;
Open source is one of the few places where you can learn directly from engineers who maintain software used by millions of people, and where your work is public and verifiable. Every one of these PRs is a small, reviewed piece of evidence of how you write code.&lt;/p&gt;

&lt;p&gt;If you want to see the full list, it is on my GitHub profile: github.com/kwy404.&lt;/p&gt;

&lt;p&gt;If you have never contributed to a big project before: pick one you use every day, find one small bug you can prove with a test, and send it. The first merge is the hardest one.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>github</category>
      <category>programming</category>
      <category>career</category>
    </item>
    <item>
      <title>I Built Voodoo.js to Bring TSX and Reactivity Directly Into Plain HTML</title>
      <dc:creator>kwy404</dc:creator>
      <pubDate>Fri, 04 Sep 2026 22:47:57 +0000</pubDate>
      <link>https://dev.to/kwy404/i-built-voodoojs-to-bring-tsx-and-reactivity-directly-into-plain-html-5g24</link>
      <guid>https://dev.to/kwy404/i-built-voodoojs-to-bring-tsx-and-reactivity-directly-into-plain-html-5g24</guid>
      <description>&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj23n7wr0ocyhd6c4rvy6.png" 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj23n7wr0ocyhd6c4rvy6.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What if you could write reactive interfaces, map arrays, filter data, use components, and even write JSX style syntax directly inside a plain HTML file?&lt;/p&gt;

&lt;p&gt;That is the idea behind Voodoo.js.&lt;/p&gt;

&lt;p&gt;Voodoo.js is an HTML first JavaScript framework designed for developers who want modern frontend capabilities without introducing a complex toolchain.&lt;/p&gt;

&lt;p&gt;You can start with a single script tag and keep working directly inside your HTML.&lt;/p&gt;

&lt;p&gt;No bundler.&lt;/p&gt;

&lt;p&gt;No compiler.&lt;/p&gt;

&lt;p&gt;No configuration.&lt;/p&gt;

&lt;p&gt;No project scaffolding.&lt;/p&gt;

&lt;p&gt;Just HTML, JavaScript, and reactivity.&lt;/p&gt;


&lt;h2&gt;In stock&lt;/h2&gt;


&lt;ul&gt;

    {products
      .filter(p =&amp;gt; p.stock &amp;gt; 0)
      .sort((a, b) =&amp;gt; b.stock - a.stock)
      .map((p, i) =&amp;gt; (
        &lt;li&gt;

          {i + 1}. {p.name} {p.stock} left
        &lt;/li&gt;

      ))
    }
  &lt;/ul&gt;

&lt;p&gt;The interesting part is that this is still a normal HTML file.&lt;/p&gt;

&lt;p&gt;You can use familiar JavaScript methods such as filter, sort, and map while generating reactive markup directly inside the page.&lt;/p&gt;

&lt;p&gt;For developers coming from React, Vue, Alpine, or even vanilla JavaScript, the syntax should feel immediately familiar.&lt;/p&gt;

&lt;p&gt;But the philosophy is different.&lt;/p&gt;

&lt;p&gt;HTML stays at the center of the application.&lt;/p&gt;

&lt;p&gt;Voodoo.js adds the reactive layer around the markup you already have instead of forcing your HTML into a completely different application structure.&lt;/p&gt;

&lt;p&gt;One script tag&lt;/p&gt;

&lt;p&gt;Getting started can be as simple as adding Voodoo.js to an HTML page.&lt;/p&gt;

&lt;p&gt;From there you can use reactive data, events, expressions, components, HTTP utilities, forms, and JSX style templates.&lt;/p&gt;

&lt;p&gt;There is no required build pipeline.&lt;/p&gt;

&lt;p&gt;That also makes Voodoo.js interesting for prototypes, small applications, internal tools, static websites, experiments, and developers who simply enjoy working close to the browser.&lt;/p&gt;

&lt;p&gt;The Playground&lt;/p&gt;

&lt;p&gt;I also built an interactive playground where you can experiment with the framework directly in the browser.&lt;/p&gt;

&lt;p&gt;You can edit the HTML, run the example, and immediately see the result in the live preview.&lt;/p&gt;

&lt;p&gt;Try the JSX map example here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://kwy404.github.io/Voodoo.js/playground.html#jsx-map" rel="noopener noreferrer"&gt;https://kwy404.github.io/Voodoo.js/playground.html#jsx-map&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://kwy404.github.io/Voodoo.js/" rel="noopener noreferrer"&gt;https://kwy404.github.io/Voodoo.js/&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://github.com/kwy404/Voodoo.js" rel="noopener noreferrer"&gt;https://github.com/kwy404/Voodoo.js&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Voodoo.js is open source and still evolving.&lt;/p&gt;

&lt;p&gt;I would really like feedback from other JavaScript developers.&lt;/p&gt;

&lt;p&gt;What do you think about this approach?&lt;/p&gt;

&lt;p&gt;Would you use JSX or TSX style syntax directly inside an HTML file if it meant keeping the project simple and avoiding a build step?&lt;/p&gt;

&lt;p&gt;If you find the project interesting, consider checking the repository, opening an issue, contributing, or giving it a star on GitHub.&lt;/p&gt;

&lt;h1&gt;
  
  
  JavaScript #TypeScript #TSX #JSX #WebDevelopment #Frontend #FrontendDevelopment #OpenSource #HTML #WebDev #Programming #Coding #DeveloperTools #JavaScriptFramework #VoodooJS
&lt;/h1&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>frontend</category>
      <category>opensource</category>
    </item>
    <item>
      <title>A reactive JS framework for server-rendered apps — no Virtual DOM, no eval(), no build step required. Looking for critical feedback.</title>
      <dc:creator>kwy404</dc:creator>
      <pubDate>Mon, 31 Aug 2026 20:01:48 +0000</pubDate>
      <link>https://dev.to/kwy404/built-voodoojs-an-html-first-javascript-framework-with-reactivity-http-forms-and-no-virtual-249d</link>
      <guid>https://dev.to/kwy404/built-voodoojs-an-html-first-javascript-framework-with-reactivity-http-forms-and-no-virtual-249d</guid>
      <description>&lt;p&gt;I've been building a JavaScript framework called &lt;strong&gt;Voodoo.js&lt;/strong&gt;, and I'd rather get torn apart in the comments than hear that it looks cool.&lt;/p&gt;

&lt;p&gt;It started with one question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How much JavaScript do we actually need to write for everyday interactive interfaces?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For a lot of apps I don't want to build a component tree, configure a bundler, install five libraries, wrap the API, manage state somewhere else, and then wire it all back into HTML.&lt;/p&gt;

&lt;p&gt;Sometimes I just want to keep writing HTML.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/kwy404/Voodoo.js" rel="noopener noreferrer"&gt;https://github.com/kwy404/Voodoo.js&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The 30-second version
&lt;/h2&gt;

&lt;p&gt;A reactive counter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;v-data=&lt;/span&gt;&lt;span class="s"&gt;"{ count: 0 }"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"count--"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;-&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;strong&amp;gt;&lt;/span&gt;{ count }&lt;span class="nt"&gt;&amp;lt;/strong&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"count++"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;+&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No &lt;code&gt;querySelector&lt;/code&gt;. No &lt;code&gt;addEventListener&lt;/code&gt;. No &lt;code&gt;innerHTML&lt;/code&gt;. No Virtual DOM.&lt;/p&gt;

&lt;p&gt;Voodoo observes the real DOM and connects HTML directives to a fine-grained reactive system built on &lt;code&gt;Proxy&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  "Why another JS framework?"
&lt;/h2&gt;

&lt;p&gt;Fair question. It's the first one I'd ask too.&lt;/p&gt;

&lt;p&gt;Voodoo isn't trying to replace React, Vue or Svelte. The target is different: &lt;strong&gt;projects where the server already renders the HTML.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Laravel, Django, Rails, PHP, ASP.NET, Node, Go templates — plus small frontends where a full SPA is overkill.&lt;/p&gt;

&lt;p&gt;Philosophically it lives somewhere near Alpine.js, HTMX and petite-vue. The difference I was chasing: HTTP, forms, validation, state, components, routing, UI helpers and reactivity should feel like &lt;strong&gt;one system&lt;/strong&gt;, not five glued together.&lt;/p&gt;




&lt;h2&gt;
  
  
  Declarative HTTP
&lt;/h2&gt;

&lt;p&gt;This is the part I enjoy using most.&lt;/p&gt;

&lt;p&gt;Instead of wiring a button by hand:&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="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&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="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="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;confirm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Delete user?&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="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/users/42&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;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DELETE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="nf"&gt;showToast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User deleted&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You declare the intent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt;
  &lt;span class="na"&gt;v-delete=&lt;/span&gt;&lt;span class="s"&gt;"/api/users/42"&lt;/span&gt;
  &lt;span class="na"&gt;v-confirm=&lt;/span&gt;&lt;span class="s"&gt;"Delete this user?"&lt;/span&gt;
  &lt;span class="na"&gt;v-toast-success=&lt;/span&gt;&lt;span class="s"&gt;"User deleted"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Delete
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The goal isn't to make JavaScript disappear. It's to stop writing JavaScript that only restates what the HTML already says.&lt;/p&gt;




&lt;h2&gt;
  
  
  Forms
&lt;/h2&gt;

&lt;p&gt;Same idea:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt;
  &lt;span class="na"&gt;v-submit=&lt;/span&gt;&lt;span class="s"&gt;"/api/users"&lt;/span&gt;
  &lt;span class="na"&gt;v-validate&lt;/span&gt;
  &lt;span class="na"&gt;v-toast-success=&lt;/span&gt;&lt;span class="s"&gt;"User saved"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Save&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For most CRUD screens, that's the whole thing. When you need more, plain JavaScript is still right there. Voodoo is meant to be progressive, not restrictive.&lt;/p&gt;




&lt;h2&gt;
  
  
  No &lt;code&gt;eval()&lt;/code&gt;, no &lt;code&gt;new Function()&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Take this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"count++"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The lazy implementation is &lt;code&gt;new Function(expression)&lt;/code&gt; or &lt;code&gt;eval(expression)&lt;/code&gt;. Voodoo does neither.&lt;/p&gt;

&lt;p&gt;There's a full expression engine inside:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Lexer → Pratt Parser → AST → Interpreter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expressions are parsed and interpreted by Voodoo itself. That gives the framework control over which syntax is supported and what the expression environment can touch — and honestly it's the most interesting engineering in the project.&lt;/p&gt;




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

&lt;p&gt;The reactive layer uses &lt;code&gt;Proxy&lt;/code&gt;, tracking dependencies per object and per property:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;reactive object
    ↓ property accessed
dependency tracked
    ↓ property changed
only dependent effects run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No Virtual DOM diff between updates. The real DOM is patched directly.&lt;/p&gt;

&lt;p&gt;The reactivity package exposes a familiar surface:&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="nf"&gt;reactive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;   &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;        &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;      &lt;span class="nf"&gt;watchEffect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nf"&gt;effectScope&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;toRaw&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;      &lt;span class="nf"&gt;markRaw&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you've used a modern reactive framework, none of this should surprise you.&lt;/p&gt;




&lt;h2&gt;
  
  
  Works with or without a build step
&lt;/h2&gt;

&lt;p&gt;Drop it in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"voodoo.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;v-data=&lt;/span&gt;&lt;span class="s"&gt;"{ open: false }"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"open = !open"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Toggle&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;v-show=&lt;/span&gt;&lt;span class="s"&gt;"open"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Hello DEV Community 👋&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or import it like anything else:&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;reactive&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;voodoojs/reactivity&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both audiences matter to me: the "paste a script tag" crowd and the "give me proper ESM" crowd.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where it fits
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Server-rendered HTML  +  Voodoo.js  →  Reactive interface
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A Laravel view, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@foreach($users as $user)
  &amp;lt;button
    v-delete="/users/{{ $user-&amp;gt;id }}"
    v-confirm="Delete user?"&amp;gt;
    Delete
  &amp;lt;/button&amp;gt;
@endforeach
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The backend keeps rendering the app. Voodoo adds the interactive layer. No separate frontend application.&lt;/p&gt;




&lt;h2&gt;
  
  
  The honest part
&lt;/h2&gt;

&lt;p&gt;What began as an experiment grew into a large framework: reactivity, directives, components, stores, HTTP, forms, validation, persistence, routing, i18n, UI utilities, animation, drag and drop, charts, streaming, devtools, and a CLI.&lt;/p&gt;

&lt;p&gt;That growth is now the problem. The project doesn't need another hundred features — it needs &lt;strong&gt;stability&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Current focus:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔒 Security hardening&lt;/li&gt;
&lt;li&gt;🧩 Parser edge cases&lt;/li&gt;
&lt;li&gt;✅ Test coverage&lt;/li&gt;
&lt;li&gt;📐 API stability&lt;/li&gt;
&lt;li&gt;📦 Bundle modularity&lt;/li&gt;
&lt;li&gt;⚡ Performance benchmarks&lt;/li&gt;
&lt;li&gt;📚 Documentation&lt;/li&gt;
&lt;li&gt;🚀 Package and release quality&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'd rather ship a small set of features people can trust in production than a huge one nobody can.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I'm asking for
&lt;/h2&gt;

&lt;p&gt;If you work with Alpine.js, HTMX, Vue, petite-vue, Stimulus, Livewire, server-rendered apps, or plain JS — I want your read on this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What would stop you from using something like Voodoo.js?&lt;/li&gt;
&lt;li&gt;Which parts of the API feel intuitive?&lt;/li&gt;
&lt;li&gt;Which parts feel unnecessary?&lt;/li&gt;
&lt;li&gt;What would you need to see before calling it production-ready?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And if you like working on JS internals, there's real work available: parsers, reactivity, testing, browser compatibility, TypeScript, performance, security, docs, components.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/kwy404/Voodoo.js" rel="noopener noreferrer"&gt;https://github.com/kwy404/Voodoo.js&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you find something questionable in the architecture, the API, the security model or the implementation, tell me. That's the feedback I actually need.&lt;/p&gt;

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