WEBMOJO

Browser application framework

Compose the interface.
Keep the control.

Views, models, forms, tables, navigation, portals, and extensions—one coherent client framework with the seams left visible.

Run an example

Open source · version 2.8.1 · 104 runnable examples

view.compose()PAINTED
01
MODELstate · validation · events
ready
02
VIEWtemplate · children · actions
bound
03
PORTALroute · nav · theme
16ms
DOM<main data-view="active">…</main>
92reference articles
104runnable routes
2.8.1current release

Documented from the repository, demonstrated in a canonical registry, and designed for browser applications that need structure without opacity.

One composition model

The browser pieces you wire on every application—already speaking the same language.

Start with small views and models. Scale the same lifecycle into tables, forms, navigation, portals, and domain extensions.

You used to coordinateWEB-MOJO composes

DOM queries · event cleanup

Lifecycle viewsTemplates, child views, delegated actions, deterministic teardown.

Fetch wrappers · ad hoc state

Models + collectionsREST-aware state, change events, pagination, filtering, identity.

Form markup · validation glue

Schema-driven formsFields, layouts, model binding, uploads, dialogs, autosave.

Table plugins · bespoke lists

Data surfacesTables, lists, detail views, filters, grouping, feedback states.

Router · sidebar · topbar

Portal shellRoutes, menus, themes, active groups, permissions, responsive chrome.

Charts · maps · lightboxes

Focused extensionsOptional capabilities that share the same view contract.

The pattern

State in. Composed view out.

WEB-MOJO keeps lifecycle, rendering, and actions together. A page remains plain JavaScript while the framework handles the repetitive browser mechanics.

  1. Extend the smallest useful view.
  2. Declare its template and route.
  3. Compose children as the interface grows.
Explore View →
pages/HelloPage.js
import { Page } from 'web-mojo';

class HelloPage extends Page {
  static route = 'hello';

  constructor(options = {}) {
    super({
      ...options,
      title: 'Hello',
      template: '<button data-action="greet">Hello</button>'
    });
  }

  onActionGreet() { this.toast.success('Composed.'); }
}

Start with one view

Your interface is the custom part.

Let WEB-MOJO carry the lifecycle and composition patterns that serious browser applications repeat.

Run the examplesRead the docs