xoong
Menu · Overview
DocsStartOverview

xoong

Build data-driven web pages with HTML, plain CSS and your OpenAPI document. Custom elements in the Light DOM, no virtual DOM, no runtime dependencies in the core, no build step needed to try it.

What you write

A screen is HTML. The table below reads listPeople from an OpenAPI operation; sorting, search, paging, selection, the confirm dialog and the toast are attributes. Try it: sort a column, type in the search box, tick rows.

{role}
<xo-view get="listPeople">
  <xo-table columns="name,email:E-mail,role" sortable filters="name:Search by name" selectable page-size="5" empty="Nobody here">
    <span slot="role" class="badge">{role}</span>
    <button class="danger" xo-click="deletePerson" xo-confirm="Delete {name}?" xo-notice="Deleted">Delete</button>
    <button slot="bulk" class="danger" xo-click="deletePerson" xo-selected>Delete ticked</button>
  </xo-table>
</xo-view>
import { configure } from '@xoong/data';
import '@xoong/data/view';
import '@xoong/ui';
import operations from '/.xoong/operations.json' with { type: 'json' };

configure({ api: operations, baseUrl: '/api' });
{
  "paths": {
    "/api/people": {
      "get": {
        "operationId": "listPeople",
        "parameters": [{ "name": "sort", "in": "query" }, { "name": "limit", "in": "query" }, { "name": "offset", "in": "query" }, { "name": "name", "in": "query" }],
        "responses": { "200": { "description": "ok" } }
      }
    }
  }
}

There is no server behind this page: a function in the page plays the API (configure({ fetch })), and everything else, the typed operation, the cache, the loading and error states, is the real thing.

Ideas

Standards first

Custom elements in the Light DOM, the History API, native <dialog> and Popover, Intl, ElementInternals for form controls.

Your API is the contract

xoong sync reads OpenAPI and writes typed operations. Tables and forms are drawn from the schemas; validation comes from them too.

Plain CSS

Design tokens are custom properties in cascade layers. Your own CSS always wins, no utility classes, no CSS-in-JS.

Strict CSP ready

xoong build writes static output with no inline code and no import map. This site is built that way.

Accessible by default

Tabs, menu, tooltip, combobox and the toolbar follow the WAI-ARIA patterns, with keyboard support and tests in three browsers.

Made for AI and humans

A short llms.txt, an MCP server, and xoong check, which catches mistakes in markup and tells you the fix.

Where to go next