# Installation

See the [Usage Guide](usage-guide.md) for the end-to-end integration path (choosing an API, install, theming, verification). This page covers install mechanics only.

BaseUI is distributed as one CSS file and one JavaScript file for browser use. `dist/baseui.min.js` is fully self-contained: Bootstrap's JS bundle (Popper.js included) and the Owl runtime are embedded ahead of BaseUI's own code, in load order (Bootstrap, then Owl, then BaseUI) — nothing else needs to load first. Both install paths below load this same file; the pure Owl component API is the recommended way to consume BaseUI in an Owl app, with the static `b-ui` markup API available as a lighter-weight alternative for non-Owl pages.

The snippets below use the `@latest` tag for readability. Pin an exact version instead (e.g. `@0.0.4`) for any production page — `@latest` can silently change what your page loads the moment a new version is published.

## Pure Owl component install (recommended)

If you're building your own Owl app and want to import BaseUI components as real Owl component classes (`<Button/>`, `<Card/>`, `<Tabs/>`, ...) instead of `b-ui` markup, it's the same one file as the static install, just accessed through an import map:

```html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@thebase/ui@latest/dist/baseui.min.css">
<script type="importmap">
{
  "imports": {
    "@base/owl": "https://cdn.jsdelivr.net/npm/@thebase/ui@latest/dist/baseui.esm.js",
    "@base/component": "https://cdn.jsdelivr.net/npm/@thebase/ui@latest/dist/baseui.esm.js",
    "@base/theme": "https://cdn.jsdelivr.net/npm/@thebase/ui@latest/dist/baseui.esm.js",
    "@base/templates": "https://cdn.jsdelivr.net/npm/@thebase/ui@latest/dist/baseui.templates.xml"
  }
}
</script>
```

`https://unpkg.com/@thebase/ui@latest/dist/...` mirrors the same files if jsDelivr is unreachable — swap the host in each URL above.

`@base/owl`, `@base/component`, and `@base/theme` all resolve to the exact same `dist/baseui.esm.js` module — the browser fetches and evaluates it once, so `Component`/`mount`/`xml` from `@base/owl` and `Button`/`Card`/... from `@base/component` are guaranteed to be the same runtime identity (no separate script needs to load first to set up a shared global). Your own app code should still import Owl from `@base/owl`, never install or import `@odoo/owl` directly — that's what keeps a `class Root extends Component` you write instanceof-compatible with BaseUI's own components. `@base/templates` maps to the templates XML — not a JS module, so resolve it with `import.meta.resolve("@base/templates")` and `fetch()` the result rather than `import`ing it.

For npm/bundler usage, everything (Owl framework, component classes, theme helper) is exported from the one `@thebase/ui` package entry: `import { Component, mount, xml, Button, Card, createThemeController } from "@thebase/ui";` — plus `@thebase/ui/dist/baseui.templates.xml` (component templates — fetch or load them before mounting). Note that importing the main entry always runs its `autoMount()` side effect (it scans the DOM for `[b-ui]`/`[b-icon]` markers on `DOMContentLoaded`) — harmless if your page has none, but worth knowing if you specifically wanted a side-effect-free import.

See [Pure Owl Components](owl-components.md) for the full loading contract, a worked example, and common mistakes.

## Static `b-ui` install (alternative)

For static HTML, a server-rendered page, or a Base HUB website page that has no Owl runtime of its own, load the same bundle as plain CSS + a classic `<script>` tag instead of an import map:

```html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@thebase/ui@latest/dist/baseui.min.css">
<script src="https://cdn.jsdelivr.net/npm/@thebase/ui@latest/dist/baseui.min.js" defer></script>
```

Bootstrap 5 is the bundled baseline CSS framework, and its JS bundle now drives BaseUI's interactive components directly.

`@thebase/ui` is published on npm, so [unpkg](https://unpkg.com/@thebase/ui@latest/) mirrors the same files as an alternative CDN (`https://unpkg.com/@thebase/ui@latest/dist/baseui.min.css` / `baseui.min.js`) if jsDelivr is unreachable in your environment. Pin an exact version (e.g. `@0.0.4`) instead of `@latest` for production.

For npm/self-hosted usage:

```sh
npm install @thebase/ui
```

Then copy or serve `node_modules/@thebase/ui/dist/baseui.min.css` and `node_modules/@thebase/ui/dist/baseui.min.js`.

`dist/bootstrap.bundle.min.js` also ships standalone, unmodified, with its own integrity hash in `dist/baseui.registry.json`, in case a project wants vendored Bootstrap JS on its own — BaseUI itself never needs it loaded separately.

The static bundle auto-mounts existing `[b-ui]` and `[b-icon]` markers on `DOMContentLoaded`. Use `BaseUI.mountAll(root)` after later DOM injection, and `BaseUI.destroy(root)` before removing a mounted subtree that owns listeners or an Owl-backed controller.

The package also ships the complete Lucide SVG icon set under `dist/icons/lucide/` and a generated `dist/icons/lucide.json` manifest. The built-in icon component can use the pinned jsDelivr Lucide CDN by default or your own self-hosted path:

```html
<span b-icon="search"></span>
<span b-icon="panel-left" b-icon-base-url="/dist/icons/lucide"></span>
```

Production pages should use pinned version URLs. `latest` is for demos and experiments.

## Package exports and browser aliases

| Need | npm/bundler export | Browser import-map key | Dist file |
| --- | --- | --- | --- |
| Static `b-ui` runtime, Owl framework, every pure Owl component class, theme helper | `@thebase/ui` | `@base/owl`, `@base/component`, `@base/theme` (all three point at the same file) | `dist/baseui.esm.js`, `dist/baseui.min.js` |
| Styles | `@thebase/ui/baseui.css` | none; load with `<link>` | `dist/baseui.min.css` |
| Bootstrap JS | embedded; standalone file is a vendoring convenience only, not part of BaseUI's own load path | none | `dist/bootstrap.bundle.min.js` |
| Named-icon components (`IconEye`, ...) | `@thebase/ui/icons` | `@base/icons` | `dist/baseui.icons.esm.js` |
| Owl templates XML | `@thebase/ui/dist/baseui.templates.xml` | `@base/templates` | `dist/baseui.templates.xml` |
| Registry metadata | `@thebase/ui/registry` | none; fetch the JSON file | `dist/baseui.registry.json` |

`@base/templates` points to XML, not JavaScript. Resolve and fetch it (`fetch(import.meta.resolve("@base/templates"))`) before mounting an Owl app that uses BaseUI component classes.

## Release Guardrails

BaseUI intentionally keeps Bootstrap bundled for the browser build, both CSS and JS. Bootstrap's JS bundle and the Owl runtime are embedded directly into `dist/baseui.min.js`/`baseui.esm.js` — in that load order — along with every pure Owl component class and the theme helper, so both the static API and the pure Owl API install with one stylesheet and one script/import: there is no more separate `baseui.owl.*`/`baseui.components.esm.js`/`baseui.theme.esm.js` file to keep in load order. Bootstrap's JS instances (`bootstrap.Modal`, `Dropdown`, `Collapse`, `Tab`, `Toast`, `Carousel`, `Tooltip`, `Popover`, `Alert`) drive the components that map to them, wrapped by BaseUI's own `.behavior.js`/`runtime/*.js` helpers so both the static and pure-Owl APIs share identical ARIA/keyboard/event behavior.

Release checks enforce runtime dependency, peer dependency, scoped CSS selector, and CDN file-size budgets through `npm run lint` and `npm run build`.
