Skip to Content
  • Home
  • Book
  • Blog
  • About us
  • Help
  • Contact us
  •  [email protected]
  • Sign in
  • English (US) Español (BO)
  • Simplify It S.R.L.
    • Contact Us
Simplify It S.R.L.
      • Home
      • Book
      • Blog
      • About us
      • Help
      • Contact us
    •  [email protected]
    • English (US) Español (BO)
    • Sign in
    • Contact Us

    Chapter 1: The "Why": From Static Pages to Modern UI

  • All Blogs
  • OWL Book
  • Chapter 1: The "Why": From Static Pages to Modern UI
  • August 25, 2026 by
    Chapter 1: The "Why": From Static Pages to Modern UI
    Grover Menacho

    Why this chapter? Every consultant eventually gets asked "why can't we just use jQuery for this?" — this chapter is the answer, backed by the actual history of the web and of Odoo's own frontend. What is Odoo trying to solve with this? Odoo needed a UI layer that could keep thousands of existing QWeb templates and legacy widgets working while still giving developers a modern, declarative way to build interfaces — a general-purpose framework like React couldn't guarantee that. Real-world application: When a client's list view feels sluggish or a custom widget breaks after an upgrade, the root cause is almost always a misunderstanding of declarative vs. imperative UI — the distinction this chapter builds from scratch.

    Welcome! Before we write a single line of OWL code, we need to understand why it exists. Every tool is created to solve a problem, and UI frameworks like OWL are a solution to decades of challenges in building dynamic, interactive user experiences on the web. This chapter is a journey through time, showing how we got from simple, static pages to the powerful applications we use today. Understanding this history will make the "how" of OWL much clearer.


    The Old Way: The Server-Rendered World

    Imagine walking into a restaurant. You look at the menu, tell the waiter you want a steak with fries, and a few minutes later, a complete, finished plate is placed in front of you. This is exactly how the web worked for a long time, and it's how classic Odoo applications were built.

    This is the server-rendered model.

    1. Your browser sends a request to the Odoo server (e.g., "I want to see the contact page for 'John Smith'").
    2. The Odoo server does all the work. It runs Python code, fetches data from the database, and uses a QWeb template to assemble a complete HTML page.
    3. It sends this finished HTML page back to your browser, which simply displays it.

    This approach is simple and effective. The server delivers a finished "plate." But what happens if you just want to change one small thing, like adding a pinch of salt? In this model, you have to send your entire plate back to the kitchen and wait for a whole new one to be made.

    For web applications, this meant that even a tiny change—like marking a task as complete or updating a customer's phone number—required a full page reload. The screen would go white, and you'd have to wait for the server to send a completely new version of the page. It was slow, clunky, and not a great user experience.


    The jQuery Era: Sprinkling Interactivity

    Developers knew the full-page-reload problem had to be solved. The solution that dominated the web for nearly a decade was jQuery.

    jQuery was a brilliant JavaScript library that allowed developers to reach into the web page and manipulate it directly, without asking the server for a new one. This is called an imperative approach. You give the computer direct, step-by-step commands.

    Think back to our restaurant analogy. Instead of ordering a new plate, you now give the waiter imperative commands:

    "Go to my table. Pick up the salt shaker. Move it three inches to the left. Now, pick up the pepper shaker..."

    You are describing how to change things. In code, it looked like this:

    // When the button with the id 'complete-task-btn' is clicked...
    $('#complete-task-btn').on('click', function() {
        // 1. Find the element with the id 'task-status'.
        // 2. Change its text to 'Completed!'.
        $('#task-status').text('Completed!');
    
        // 3. Find the button itself.
        // 4. Add the 'btn-success' class to make it green.
        $(this).addClass('btn-success');
    });
    

    This was a huge leap forward! We could now build much more responsive interfaces. But as applications grew larger, the imperative approach created its own set of problems:

    "Spaghetti Code": You ended up with hundreds of little instructions all tied to different buttons and inputs. It became incredibly difficult to follow the logic and understand what state the application was in.

    Difficult to Maintain: If you changed the HTML structure, you had to find and update all the JavaScript commands that were looking for the old structure. It was fragile and time-consuming.


    The Paradigm Shift: Declarative UIs

    The complexity of the imperative model led to the next major evolution in web development: declarative frameworks. This is where OWL, React, and Vue come in.

    Instead of telling the computer how to do something, you simply declare what you want the end result to be.

    In our restaurant, you no longer give step-by-step instructions. You just declare the state you want:

    "I want the salt shaker to be on the left side of the fork."

    You don't care how the waiter does it. You've described the final state, and you trust the waiter (the framework) to make it happen efficiently.

    In a declarative framework like OWL, you link your UI to your application's data (its "state").

    <!-- In our template (simplified — you'll learn the real syntax in Chapter 5) -->
    <button t-att-class="state.isCompleted ? 'btn-success' : 'btn-primary'">
        <t t-esc="state.isCompleted ? 'Completed!' : 'Mark as Complete'"/>
    </button>
    

    When you want to change the UI, you don't touch the UI directly. You just change the data: this.state.isCompleted = true;.

    OWL sees that the state has changed and automatically and efficiently figures out the minimum number of steps needed to update the button's text and color. You declared the "what" (the UI should look like this when isCompleted is true), and OWL handled the "how."

    This declarative approach is the foundation of all modern web development. It leads to code that is:

    • Predictable: The UI is always a direct representation of the state.
    • Maintainable: You can change the underlying HTML and logic without breaking dozens of little commands.
    • Scalable: It's much easier to build large, complex applications.

    Why Odoo Created Its Own Framework: The Perfect Fit

    At this point, you might be wondering: "If React, Vue, and Angular are so popular and powerful, why didn't Odoo just use one of them? Why create OWL from scratch?"

    This is an excellent question, and the answer reveals the thoughtful engineering behind OWL.

    The Odoo-Specific Challenges

    Odoo is not just any web application—it's a comprehensive business management suite with unique requirements:

    Deep Integration with QWeb: Odoo already had years of investment in QWeb templates for server-side rendering. The new framework needed to work seamlessly with existing QWeb syntax and conventions, not replace them entirely.

    Backward Compatibility: Odoo has thousands of existing modules and customizations built with the older widget-based system. Any new framework had to coexist with this legacy code during a gradual transition period.

    Performance at Scale: Odoo applications can have dozens of simultaneous components displaying hundreds of records. The framework needed to be optimized for this specific use case, not general web development.

    Small Bundle Size: Adding React or Vue would significantly increase Odoo's JavaScript bundle size. OWL is lightweight and focused, including only what Odoo actually needs.

    The Technical Advantages of OWL

    By creating their own framework, the Odoo team could make specific design decisions that perfectly match their needs:

    Native QWeb Integration: OWL templates are QWeb templates. There's no translation layer or syntax conversion needed—developers use the same template language they already know.

    Optimized Rendering Engine: OWL's rendering engine is specifically tuned for Odoo's patterns of data display and manipulation, making it fast for typical ERP operations.

    Built-in Services System: OWL comes with a service system that directly integrates with Odoo's RPC layer, database models, and business logic.

    Gradual Migration Path: OWL was designed from day one to work alongside the existing Odoo JavaScript framework, allowing for smooth, incremental upgrades of legacy code.

    The Strategic Vision

    Creating OWL wasn't just about solving today's problems—it was about ensuring Odoo's long-term technological independence and innovation. By owning their UI framework, the Odoo team can:

    • Evolve the framework in lockstep with Odoo's business requirements
    • Optimize performance for ERP-specific use cases
    • Maintain complete control over the developer experience
    • Avoid external dependencies and potential breaking changes from third-party frameworks

    This is the problem OWL was built to solve for Odoo: providing all the power and elegance of modern declarative UI development while being perfectly tailored to the unique needs of business applications. It's not just a framework—it's Odoo's strategic investment in the future of their platform.


    The Evolution: From OWL 1.0 to OWL 2.0

    If you're reading this book, you might have some experience with OWL 1.0, or you might have heard about the transition. Understanding what changed between versions will help you appreciate why OWL 2.0 is such a significant improvement and why it's worth learning from scratch.

    What Was OWL 1.0?

    OWL 1.0 was Odoo's first attempt at a modern JavaScript framework. It served its purpose well and introduced many developers to declarative UI concepts. However, as it was used in production across thousands of Odoo installations, certain limitations became clear:

    Performance Bottlenecks: The virtual DOM implementation, while functional, wasn't optimized for the complex, data-heavy interfaces that Odoo applications require.

    Complex State Management: Managing state across multiple components required verbose patterns and a lot of boilerplate code.

    Template Limitations: While QWeb was supported, the integration felt somewhat forced, and some advanced template features were difficult to use.

    Learning Curve: The API, while powerful, had many concepts that were difficult for new developers to grasp quickly.

    The OWL 2.0 Revolution: What Changed

    OWL 2.0 wasn't just an update—it was a complete redesign from the ground up, incorporating lessons learned from years of production use:

    1. Simplified Component API

    OWL 1.0 approach:

    class MyComponent extends Component {
        constructor(parent, props) {
            super(parent, props);
            this.state = {
                counter: 0
            };
        }
    
        willStart() {
            return this.loadData();
        }
    
        async loadData() {
            // Complex async setup
        }
    }
    

    OWL 2.0 approach:

    class MyComponent extends Component {
        setup() {
            this.state = useState({
                counter: 0
            });
    
            onWillStart(this.loadData);
        }
    
        async loadData() {
            // Same async logic, cleaner setup
        }
    }
    

    2. Revolutionary Hooks System

    OWL 2.0 introduced a hooks-based architecture (inspired by React hooks) that makes components more modular and reusable:

    Before (OWL 1.0): State and lifecycle management was tightly coupled to the component class.

    After (OWL 2.0): Hooks like useState, useService, useRef, and useEffect allow you to compose functionality in clean, reusable ways.

    // OWL 2.0: Clean, composable logic
    setup() {
        const state = useState({ count: 0 });
        const orm = useService("orm");
        const notification = useService("notification");
    
        useEffect(
            () => {
                // Side effects are cleanly separated
            },
            () => [state.count]  // dependencies are returned by a function
        );
    }
    

    3. Significantly Improved Performance

    Faster Rendering: OWL 2.0 replaced the classic virtual DOM with a "block-based" rendering engine that is significantly faster, especially when handling large lists and frequent updates.

    Smarter Re-rendering: The new reactivity system is much better at detecting when components actually need to update, reducing unnecessary re-renders.

    4. Enhanced Developer Experience

    Better Error Messages: When something goes wrong, OWL 2.0 provides much clearer, more actionable error messages with precise line numbers and context.

    Improved DevTools Integration: Browser debugging is much more intuitive, with better component inspection and state visualization.

    TypeScript Support: OWL 2.0 was designed with TypeScript in mind, providing excellent type safety for large projects.

    5. Streamlined Service System

    OWL 1.0: Services were available but the integration pattern was verbose and sometimes confusing.

    OWL 2.0: The useService hook makes accessing Odoo services (like orm, notification, action) incredibly clean and consistent.

    // OWL 2.0: Simple service access
    setup() {
        this.orm = useService("orm");
        this.notification = useService("notification");
        this.actionService = useService("action");
    }
    

    6. Better Integration with Modern JavaScript

    OWL 2.0 embraces all the modern JavaScript features we covered in this chapter: - Native support for async/await patterns - Excellent integration with ES6 modules - Built-in support for destructuring in templates and components - Template literals work seamlessly with the template system

    Migration Strategy: Why Start Fresh?

    If you're familiar with OWL 1.0, you might wonder whether to migrate existing code or start fresh. Odoo's recommendation—and the approach of this book—is to treat OWL 2.0 as a new framework rather than an upgrade.

    Why this approach makes sense:

    Different Mental Models: The hooks-based architecture requires thinking about components differently than the class-based approach of OWL 1.0.

    New Best Practices: Patterns that were optimal in OWL 1.0 might be anti-patterns in OWL 2.0.

    Clean Slate Benefits: Starting fresh lets you take advantage of all the new features without being constrained by old patterns.

    Future-Proofing: OWL 2.0 is the foundation for Odoo's frontend for years to come. Learning it properly now is an investment in your long-term productivity.

    What This Means for You

    Whether you're completely new to OWL or coming from OWL 1.0, this book will teach you OWL 2.0 from the ground up using modern best practices. If you have OWL 1.0 experience, some concepts will feel familiar, but approach each chapter with an open mind—the improvements in OWL 2.0 will likely change how you think about building user interfaces.

    The journey from jQuery spaghetti code to OWL 1.0 was significant. The leap from OWL 1.0 to OWL 2.0 is equally transformative, but in terms of developer productivity, code maintainability, and application performance.


    Common Pitfalls

    Assuming OWL 1.0 syntax still applies. If you find older Odoo tutorials or modules online, you may see constructor(parent, props), willStart(), or this.trigger(...). This book only teaches OWL 2.0, where setup() replaces the constructor and callback props replace event triggering (Chapter 9). Don't mix the two styles.

    Thinking "declarative" means "no logic." Declarative doesn't mean you stop writing code—it means you stop writing DOM-manipulation code. You still decide what the state should be; OWL decides how to reflect it on screen.

    Skipping the "why" to get to the "how." It's tempting to jump straight to Chapter 5 for working code. But the mental model in this chapter—state changes, not DOM instructions—is what makes every later chapter make sense. If a later example confuses you, it often helps to come back and re-read this chapter.

    Reflection Questions

    1. Using the restaurant analogy from this chapter, describe in your own words the difference between the jQuery (imperative) approach and the OWL (declarative) approach.
    2. Look at the jQuery snippet in "The jQuery Era" section. If ten different buttons on a page each needed similar logic, what problems would you expect to run into as the codebase grows?
    3. Name two Odoo-specific constraints (mentioned in "Why Odoo Created Its Own Framework") that a general-purpose framework like React would not have solved out of the box.

    TL;DR: OWL exists because Odoo needed a declarative UI framework tailored to its own QWeb templates, legacy widgets, and ERP-scale performance needs — OWL 2.0 rebuilt that framework around hooks for a simpler, faster, more maintainable developer experience.

    Try it yourself: This chapter's example is available as an installable Odoo 19 addon: simplifyit_owl_book_ch1_ex1. Installation instructions are in the repository README.


    What's Next?

    In the next chapter, we'll set up the tools you need to work effectively with this powerful, purpose-built framework — your editor, the browser DevTools, and the Odoo module structure you'll build everything in from here on.

    in OWL Book
    Chapter 2: Your Essential JavaScript Toolkit
    Reading the whole book? Take it with you — free, no sign-up.
    PDF EPUB All chapters
    Useful Links
    • Home
    • About us
    • Blog
    • The OWL 2.0 book
    • Help
    • Contact us
    About us

    Simplify It S.R.L. is an Odoo implementation and development firm based in La Paz, Bolivia, working with companies across Latin America and North America. We have been building on Odoo since version 6.1: custom modules, version migrations and Bolivian localization.

    We are also the authors of the OWL 2.0 book, published free chapter by chapter on our blog.

    Connect with us
    • Contact us
    • [email protected]
    • +591 65144144
    • La Paz, Bolivia
    Follow us
    Copyright © Simplify It S.R.L.
    English (US) | Español (BO)
    Powered by Odoo - Create a free website