OWL

A modern, lightweight UI framework for applications that scale

Built by Odoo — ~20kb gzipped, zero dependencies, written in TypeScript

Signal-based Reactivity

Explicit, composable, and debuggable state management. Read signals by calling them, making dependencies visible and bugs easier to trace.

Plugin System

Type-safe, composable sharing of state and services across components. Plugins replace the env pattern with something more powerful.

Class Components

Familiar OOP patterns with ES6 classes. Combine the readability of class-based architecture with modern reactivity.

XML Templates

Declarative templates with a clean syntax. Templates can be stored, modified dynamically, and targeted with xpaths.

Async Rendering

Concurrent mode for smooth user experiences. Components can load data asynchronously without blocking the UI.

No Toolchain Required

Works directly in the browser with native ES modules. No build step needed to get started.

Quick Example

main.js
import { Component, signal, mount, xml } from "@odoo/owl";

class Counter extends Component {
    static template = xml`
        <div class="counter">
            <button t-on-click="this.decrement">-</button>
            <span t-out="this.count()"/>
            <button t-on-click="this.increment">+</button>
        </div>`;

    count = signal(0);

    increment() { this.count.set(this.count() + 1); }
    decrement() { this.count.set(this.count() - 1); }
}

mount(Counter, document.body);
Result