Why it made sense
Pages in 2006 were documents with a little behaviour. Reading state back out of the DOM ("is the menu open? check the class") was perfectly reasonable at that scale.
What changed
Modern interfaces have many pieces of state that affect many parts of the page. With only imperative DOM edits, every change must update every dependent element by hand, in the right order β miss one and the UI lies. This is the bug class that pushed teams towards frameworks, often for pages that didn't need a single-page app.
What jsKjs does instead
Pulse puts state where it is used β kj-data="{ open: false }" β and binds the page to it. Change the value and every kj-text, kj-show, :attr and kj-model that depends on it updates. No build step, no virtual DOM, and the jQuery API is still there for everything else.
jQuery
$('#toggle').on('click', function () {
const open = !$('#menu').hasClass('open');
$('#menu').toggleClass('open', open);
$(this).attr('aria-expanded', open).text(open ? 'Close' : 'Menu');
$('#overlay').toggle(open); // β¦and every other dependent element
});jsKjs
<div kj-data="{ open: false }">
<button @click="open = !open" :aria-expanded="open ? 'true' : 'false'" kj-text="open ? 'Close' : 'Menu'"></button>
<nav id="menu" kj-show="open">β¦</nav>
<div id="overlay" kj-show="open"></div>
</div>