PraxisJS

Introduction

What PraxisJS is, why it exists, and how it approaches frontend reactivity.

Introduction

PraxisJS is a signal-driven frontend framework written in TypeScript. It uses class components with decorators and fine-grained signals that update only the exact DOM nodes that changed — no virtual DOM, no component re-renders.

The core idea

Most frameworks track reactivity implicitly. You write templates or JSX, and the runtime figures out what to re-run. PraxisJS takes the opposite stance: reactivity is always explicit, always visible in the code.

@Component()
class Counter extends StatefulComponent {
  @State() count = 0

  render() {
    return (
      <div>
        <p>Count: {() => this.count}</p>   {/* reactive — updates when count changes */}
        <button onClick={() => this.count++}>+</button>
      </div>
    )
  }
}

The arrow function {() => this.count} is the contract: this value changes, track it. Without the arrow function, the value is read once at render time and never updates. You can see exactly what is reactive and what is not — directly in the template, without reading any framework documentation to find out.

How rendering works

render() runs exactly once, on mount. It builds the initial DOM. After that, the renderer is done — it never runs render() again.

Updates happen through reactive effects: each {() => expr} arrow function in JSX becomes a live subscription. When any signal it reads changes, only that specific DOM node is updated. The rest of the tree is untouched.

This means:

  • No diffing, no reconciliation
  • No cascading re-renders from parent to child
  • Predictable update granularity — you know exactly what updates and when

What makes it different

PraxisJS
Reactivity modelFine-grained signals
Update mechanismDirect DOM mutations — no virtual DOM
Component styleTypeScript class + decorators
render() behaviorRuns once on mount
Template reactivity{() => this.value} arrow functions
State declaration@State() on a class field

Philosophy

Praxis (πρᾶξις, Greek: action, practice). Not how things should be — how they are actually done.

@State doesn't suggest a property is reactive — it is reactive, and you can see that in the code. @Watch doesn't hint at a side effect — it commits to one. The component doesn't hide what it does: it practices openly.

This has a practical benefit: when something doesn't update the way you expected, the answer is almost always visible right in the template — either the value is wrapped in {() => ...} or it isn't.

The first-party ecosystem

PraxisJS ships a complete set of packages that use the same signal system and decorator conventions as core:

All packages are optional and completely independent — install only what your project needs.

Next steps

On this page