Reactive Framework • Zero Build

Reactive UIs with desktop-style event control

Write this.count++ and watch your UI update. Need complex interactions? Handle events with msgProc(event) like desktop frameworks.

<script src="https://cdn.jsdelivr.net/gh/quellabs/wakapac@main/wakapac.min.js"></script>
Live Demo - Try it!

{{greeting}}

Count: {{count}}

💡 Message-based event routing Need drag/drop, modal dialogs, or custom controls? Handle events with msgProc() for precise control. See examples →
<div id="app">
  <h4>{{greeting}}</h4>
  <p>Count: {{count}}</p>
  <input data-pac-bind="value: name">
  <button data-pac-bind="click: increment">+1 Click Me</button>
  <button data-pac-bind="click: reset">Reset</button>
</div>

<script>
wakaPAC('#app', {
  name: 'World', count: 0,
  computed: {
    greeting() { return `Hello ${this.name}!`; }
  },
  increment() { this.count++; },
  reset() { this.count = 0; this.name = 'World'; }
});
</script>

Simple.

Write plain JavaScript.
Assign values directly.
UI updates automatically.

No Build.

One file.
One script tag.
Working code in 60 seconds.

Powerful.

Full reactivity.
Computed properties.
Desktop-style event loop.

Get Started in 60 Seconds

Copy, paste, done. No installation. No configuration.

<!DOCTYPE html>
<html>
<head>
    <script src="https://cdn.jsdelivr.net/gh/quellabs/wakapac@main/wakapac.min.js"></script>
</head>
<body>

<div id="app">
    <h1>Hello {{name}}!</h1>
    <input data-pac-bind="value: name">
</div>

<script>
    wakaPAC('#app', {
        name: 'World'
    });
</script>

</body>
</html>

That's a complete reactive application ~70KB minified MIT licensed

Everything You Need. Nothing You Don't.

Complete reactive framework in one file

No Build Step

One script tag. Refresh your browser. It just works.

Direct Assignment

Write this.count++ not setCount(count + 1). Natural JavaScript, automatic updates.

Mustache Interpolation

{{expressions}} with full JavaScript operators, ternaries, array literals.

Computed & Browser Properties

Derived values recalculate automatically. Reactive network status, viewport size, scroll position - zero setup.

Component Hierarchy

Parent-child messaging built-in. Clear relationships, explicit communication.

Desktop-style event loop

Low-level msgProc for drag-and-drop, custom gestures, IDE-like UIs.

Why WakaPAC Exists

I started in desktop UI development, where state-driven, reactive programming was simple and efficient. On the web, I admired the directness of Knockout.js, but I still missed that same programming model in plain JavaScript. WakaPAC brings those two together: desktop-style clarity with Knockout-like simplicity, built on modern JavaScript.

— Floris, Quellabs

See It In Action

Real code, real patterns, ready to copy

Message Processor
wakaPAC('#box', {
  dragging: false,
  startX: 0,
  startY: 0,

  msgProc(event) {
    switch(event.message) {
      case wakaPAC.MSG_LBUTTONDOWN:
        this.dragging = true;
        this.startX = wakaPAC.LOWORD(event.lParam);
        this.startY = wakaPAC.HIWORD(event.lParam);
        break;

      case wakaPAC.MSG_MOUSEMOVE:
        if (this.dragging) {
          const x = wakaPAC.LOWORD(event.lParam);
          const y = wakaPAC.HIWORD(event.lParam);
          event.target.style.left = x + 'px';
          event.target.style.top = y + 'px';
        }
        break;

      case wakaPAC.MSG_LBUTTONUP:
        this.dragging = false;
        break;
    }
  }
});

Low-level control for drag-and-drop, custom gestures

Computed Properties
wakaPAC('#app', {
  firstName: 'John',
  lastName: 'Doe',
  items: [
    { name: 'Apple', price: 10 },
    { name: 'Banana', price: 20 }
  ],

  computed: {
    fullName() {
      return `${this.firstName} ${this.lastName}`;
    },

    totalPrice() {
      return this.items.reduce(
        (sum, item) => sum + item.price,
        0
      );
    },

    itemCount() {
      return this.items.length;
    }
  }
});

Automatically recalculates when dependencies change

Parent-Child Communication
// Child component
const child = wakaPAC('#child', {
  sendMessage() {
    this.notifyParent('alert', {
      text: 'Task completed',
      time: Date.now()
    });
  }
});

// Parent component
const parent = wakaPAC('#parent', {
  receiveFromChild(type, data, childPAC) {
    if (type === 'alert') {
      console.log('Child says:', data.text);
    }
  },

  broadcastToAll() {
    this.notifyChildren('refresh', {
      theme: 'dark'
    });
  }
});
Reactive Browser Properties
<div id="app">
  <!-- Network status -->
  <p data-pac-bind="visible: !browserOnline">
    ⚠️ You are offline
  </p>

  <!-- Viewport info -->
  <p>Screen: {{browserViewportWidth}} ×
         {{browserViewportHeight}}</p>

  <!-- Page visibility -->
  <p data-pac-bind="visible: !browserVisible">
    Tab hidden - updates paused
  </p>

  <!-- Scroll position -->
  <p>Scrolled: {{browserScrollY}}px</p>

  <!-- Network quality -->
  <p>Connection: {{browserNetworkQuality}}</p>
</div>

All reactive, zero configuration required

Built on PAC Architecture

Presentation-Abstraction-Control: A smarter alternative to MVC

Presentation

Your HTML and DOM — what users see and interact with

Abstraction

Your data model and business logic — what your app knows

Control

The reactive mediator — keeps everything synchronized

Why this matters: PAC enforces a single data flow path through the Control layer. When your UI breaks, there's only one place to look. No mystery mutations, just clear, predictable data flow.

Stop Configuring. Start Building.

Download one file and write working code in the next 60 seconds

Open source • MIT licensed • 70KB minified • Zero dependencies