Skip to main content

daub-ui

Build, preview and verify UI with DAUB (daub.dev), a drop-in CSS + JS component library with 91 components and 21 theme families. Covers three paths: plain HTML with db-* classes, json-render or OpenUI Lang specs rendered by daub-render.js, and the hosted DAUB MCP server (generate_ui, validate_spec, render_spec, parse_openui, get_block_library). Includes the rules that prevent broken renders, 266 ready-made blocks, playground share links, a verify loop, and Jev recipes for picking components, blocks and themes. Use when the user mentions DAUB, daub.dev, daub-ui, db- classes, the DAUB playground or MCP, json-render or OpenUI specs, or asks for a themed dashboard, landing page, form or settings screen without a build step.

Source facts

Repository
sliday/daub
Last source activity
October 9, 2026 at 11:39
Detected SKILL.md language
English
Stars
41
Forks
3

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
daub-ui
description
Build, preview and verify UI with DAUB (daub.dev), a drop-in CSS + JS component library with 91 components and 21 theme families. Covers three paths: plain HTML with db-* classes, json-render or OpenUI Lang specs rendered by daub-render.js, and the hosted DAUB MCP server (generate_ui, validate_spec, render_spec, parse_openui, get_block_library). Includes the rules that prevent broken renders, 266 ready-made blocks, playground share links, a verify loop, and Jev recipes for picking components, blocks and themes. Use when the user mentions DAUB, daub.dev, daub-ui, db- classes, the DAUB playground or MCP, json-render or OpenUI specs, or asks for a themed dashboard, landing page, form or settings screen without a build step.
license
MIT
compatibility
Any agent that reads files and runs shell or HTTP. The MCP path needs network access to daub.dev. Jev recipes need an OpenRouter API key.
metadata
{"daub-version":"3.20.6","homepage":"https://daub.dev"}
# DAUB UI DAUB is a drop-in CSS + JS component library. `daub.css` styles 91 components through `db-*` classes, `daub.js` wires the interactive ones (tabs, overlays, switches, dropdowns), and 21 theme families give 42 light and dark themes. No build step and no framework. | Path | You write | Good for | |---|---|---| | 1. Plain HTML | `<button class="db-btn db-btn--primary">` | Existing HTML, JSX or template code, static sites | | 2. Specs | json-render JSON or OpenUI Lang, rendered by `daub-render.js` | LLM output, streaming, UI as data, playground previews | | 3. Hosted MCP | Tool calls to `https://daub.dev/api/mcp` | Drafting from a prompt, validating and rendering without local tooling | ## Pick a path - The user has HTML, JSX, Vue or template files: path 1. Look up each component in `references/components.md` (HTML classes) or `https://daub.dev/llms.txt` before you write markup. - You generate UI from a prompt, or a program consumes the UI: path 2. Write OpenUI Lang when a model writes the spec (about 67% fewer tokens than JSON). Write JSON when code edits the spec. - You want a server to draft or check a spec: path 3, then edit the returned spec under path 2 rules. - The user wants React: `npm install daub-react daub-ui` with React and React DOM 19 or later (React section of llms.txt). The React package depends on `@shadcn/react` 0.3.1; build the app with its bundler. ## Path 1: plain HTML ```html <link rel="stylesheet" href="https://daub.dev/daub.css"> <script src="https://daub.dev/daub.js"></script> <main class="db-container db-container--narrow"> <div class="db-card"> <div class="db-card__header"> <h3 class="db-card__title">Notifications</h3> <p class="db-card__desc">Choose what reaches you.</p> </div> <div class="db-flex db-flex--col db-gap-4"> <div class="db-field"> <label class="db-field__label" for="email">Email</label> <input class="db-field__input" id="email" type="email" placeholder="you@acme.com"> <span class="db-field__helper">We send one digest a week.</span> </div> <div class="db-switch" role="switch" tabindex="0" aria-checked="true"> <span class="db-switch__track"><span class="db-switch__thumb"></span></span> Mentions </div> </div> <div class="db-card__footer"> <button class="db-btn db-btn--primary" data-db-modal-trigger="saved">Save</button> </div> </div> </main> <div class="db-modal-overlay" id="saved" aria-hidden="true"> <div class="db-modal" role="dialog" aria-modal="true"> <div class="db-modal__header"> <h2 class="db-modal__title">Saved</h2> <button class="db-modal__close" aria-label="Close">&times;</button> </div> <div class="db-modal__body">Your preferences are live.</div> </div> </div> ``` - Set the theme on the root: `<html data-theme="nord-light">`, or call `DAUB.setFamily('nord')` and `DAUB.setScheme('dark')`. - `daub.js` runs `DAUB.init()` on load. After you insert markup later, call `DAUB.init(container)`. - Overlays (`db-modal-overlay`, `db-alert-dialog`, `db-sheet`, `db-drawer`, `db-command`) need an `id`. Open them with `DAUB.openModal('id')` and friends, or a `data-db-modal-trigger="id"` button. - Toasts are JS only: `DAUB.toast({ type: 'success', title: 'Saved', message: 'Changes are live.' })`. - CDN copies: `cdn.jsdelivr.net/npm/daub-ui@latest/daub.css` and `/daub.js`. npm can lag the site; `https://daub.dev/daub.css?v=3.20.6` is the current build. ## Conversation components The HTML catalog has 91 components; the browser/OpenUI/MCP registry has 89 renderer types. Compose MessageScroller, Message, Bubble, Attachment, Marker, and ChangeSummary with ChatComposer. ChatComposer adds local attachments, dictation, model controls, queue and steer events; your app owns message data, AI transport, approval enforcement, uploads, persistence, and reaction state. See `https://daub.dev/chat-demo.html` and the Chat Components section of `https://daub.dev/llms.txt`. ChangeSummary is static markup with host-provided `files: [{path, additions?, deletions?, status?}]`, optional title/description, and explicit action children. It needs `daub.css` without `daub.js`. Render paths as plain text and counts with accessible addition/deletion labels. Counts floor finite numbers and clamp rows/totals to `0..Number.MAX_SAFE_INTEGER`; other counts become zero. Empty files default to `No files changed`. Label demo data `Prepared 2 demo files` / `Demo changes`; omit actions unless the host wires them. React `onUndo` / `onViewChanges` render buttons only when supplied; `undoLabel` / `undoDisabled` configure the callback-backed Undo button. DAUB performs no file operations. - Use stable `data-db-message-id` rows in `db-message-scroller__item`. The native root accepts `data-db-auto-scroll`, `data-db-scroll-position="start|end|last-anchor"`, and `data-db-scroll-peek`. - `DAUB.createMessageScroller(root, {autoScroll, scrollPosition, scrollPeek})` returns a handle with `scrollToStart`, `scrollToEnd`, `scrollToMessage`, `getState`, and `destroy`. Renderer options use `defaultScrollPosition` and `peek`. - Chat OpenUI signatures take children first; pass metadata as named props. Attachment children represent actions. Bubble and Marker content accept plain text. Keep image and link URLs safe. ## Path 2: specs A spec is a flat element map. json-render JSON: ```json { "theme": "github", "root": "page", "elements": { "page": { "type": "Stack", "props": { "direction": "vertical", "gap": 5, "container": "wide" }, "children": ["header", "kpis", "revenue"] }, "header": { "type": "Stack", "props": { "direction": "horizontal", "justify": "between", "align": "center" }, "children": ["title", "export"] }, "title": { "type": "Text", "props": { "tag": "h1", "content": "Revenue" } }, "export": { "type": "Button", "props": { "label": "Export CSV", "variant": "secondary", "icon": "download" } }, "kpis": { "type": "Grid", "props": { "columns": 3, "gap": 4 }, "children": ["mrr", "churn", "arpu"] }, "mrr": { "type": "StatCard", "props": { "label": "MRR", "value": "$48,210", "trend": "up", "trendValue": "+6.2%", "icon": "dollar-sign" } }, "churn": { "type": "StatCard", "props": { "label": "Churn", "value": "2.1%", "trend": "down", "trendValue": "-0.4 pts", "icon": "user-minus" } }, "arpu": { "type": "StatCard", "props": { "label": "ARPU", "value": "$38.40", "trend": "up", "trendValue": "+$1.10", "icon": "wallet" } }, "revenue": { "type": "ChartCard", "props": { "title": "Monthly revenue ($k)" }, "children": ["revenue-chart"] }, "revenue-chart": { "type": "Chart", "props": { "bars": [ { "label": "Apr", "value": 39 }, { "label": "May", "value": 41 }, { "label": "Jun", "value": 44 }, { "label": "Jul", "value": 43 }, { "label": "Aug", "value": 46 }, { "label": "Sep", "value": 48 } ] } } } } ``` A settings page in OpenUI Lang, one statement per line: ```openui __theme = "nord-light" root = Stack([header, prefs, account, confirm], "vertical", 5, container: "narrow") header = Stack([Text("Settings", "h1"), Text("Manage how Acme reaches you.", "p")], "vertical", 1) prefs = Card([mentions, push, digest], "Notifications", "Choose what reaches you and where.") mentions = Switch("Email me when a teammate mentions me", true) push = Switch("Push notifications on this device", false) digest = Select("Weekly digest", [{label: "Monday 9:00", value: "mon"}, {label: "Friday 16:00", value: "fri"}, {label: "Never", value: "off"}], "mon") account = Card([deleteBtn], "Delete account", "Removes all 14 projects and their files.") deleteBtn = Button("Delete account", "icon-danger", icon: "trash-2", trigger: "confirm-delete") confirm = AlertDialog("confirm-delete", "Delete your account?", "You cannot undo this.", footer: [keepBtn, confirmBtn]) keepBtn = Button("Keep account", "secondary") confirmBtn = Button("Delete account", "primary") ``` Render either one in any page. The parser and renderer ship only on daub.dev (the npm package has neither): ```html <link rel="stylesheet" href="https://daub.dev/daub.css?v=3.20.6"> <script src="https://cdn.jsdelivr.net/npm/lucide@0.576.0/dist/umd/lucide.min.js" integrity="sha384-b05ba3pt6xaC7F4r130arhf8cF18GH/gKu9JDz/NMf+BhLlBVwIWUdAZSpf1IWRZ" crossorigin="anonymous"></script> <div id="app" style="padding-block: 24px"></div> <script src="https://daub.dev/daub.js?v=3.20.6"></script> <script src="https://daub.dev/daub-render.js?v=3.20.6"></script> <script src="https://daub.dev/daub-openui-parser.js?v=3.20.6"></script> <script> const spec = DaubOpenUI.openUItoSpec(openuiText); // or JSON.parse(jsonText) document.documentElement.dataset.theme = spec.theme || 'light'; const app = document.getElementById('app'); app.appendChild(renderElement(spec.elements, spec.root, 0)); for (const id in spec.elements) // elements the tree never reached render after it if (!app.querySelector('[data-spec-id="' + id + '"]')) app.appendChild(renderElement(spec.elements, id, 0)); DAUB.init(); lucide.createIcons(); </script> ``` Full formats: `references/json-render.md` (state, actions, visibility) and `references/openui.md` (syntax, every signature). ## Path 3: hosted MCP - Claude Code: `claude mcp add daub --transport http https://daub.dev/api/mcp` - Cursor and other Streamable HTTP clients: `{ "mcpServers": { "daub": { "url": "https://daub.dev/api/mcp" } } }` - stdio-only clients: `npx -y mcp-remote https://daub.dev/api/mcp` - No MCP client (pi, scripts): POST JSON-RPC `tools/call` to the same URL (curl recipe in `references/mcp.md`). Tools: `generate_ui` (prompt to spec + HTML), `get_component_catalog`, `validate_spec`, `render_spec`, `parse_openui`, `get_block_library`. `validate_spec` and `render_spec` take the spec as a JSON string or an object. `generate_ui` picks components with Jev first; `routing.picked_components` shows the pick. Rate limit: 60 requests per minute per IP. ## Golden rules These rules prevent the failures seen most in generated DAUB UIs. 1. OpenUI arguments are positional in parser order. Check the signature in `references/openui.md`, or pass named args: `Button(label: "Save", variant: "primary")`.
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub