Seattle at night, chat picks the route
IRL · Capitol Hill
The OpenVibe Kit · v4.235.0 · MIT
50 parts, each one function call that returns plain HTML: escaped, phone first, on the site's own theme. Pages work without JavaScript; one small file adds the menus, copy buttons and sheets. All of it is 17.8 KB of CSS. How closely each OpenVibe site follows it, read from its code: design health.
Every builder returns a string of HTML with its text escaped. The page is whole before any script runs.
// npm i https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.235.0
const kit = require('openvibe-shared/kit');
res.send(kit.head({ title: 'Rooms' })
+ kit.list(rooms.map((r) => kit.row({ href: `/r/${r.slug}`, title: r.name, sub: r.topic }))));The same builders on window.OpenVibeKit, from the CDN with open CORS. Call enhance after adding markup.
<link rel="stylesheet" href="https://openvibe.network/shared/kit.css">
<script src="https://openvibe.network/shared/kit.js"></script>
<script src="https://openvibe.network/shared/kit-web.js" defer></script>
<script>
const box = document.querySelector('#rooms');
box.innerHTML = OpenVibeKit.list(rooms.map((r) => OpenVibeKit.row({ title: r.name, sub: r.topic })));
OpenVibeKit.enhance(box);
</script>Each part's page prints the HTML its call returns. Keep kit.css and it looks the same; without OpenVibe's theme, set --bg-*, --text-* and --accent yourself.
kit.css12.2 KBkit-web.js6.8 KBkit-data.css5.6 KBkit-data-web.js3.0 KBkit.js33.7 KBButtons, menus and the small marks beside them.
kit.button()One clear action: primary, quiet, ghost or danger. A link with href, a form button without.
1.5 KB of CSS
kit.iconButton()An action that is only an icon. Its label is what a screen reader says and what the tooltip shows.
1.0 KB of CSS
kit.action()A button that posts, with an optional confirm: leave, remove, stop.
1.4 KB of CSS · uses kit-web.js
kit.more()The rest of a row's actions, behind one button. Dangerous ones confirm.
1.2 KB of CSS · uses kit-web.js
kit.badge()A word beside a title: live, new, a state. Five tones.
257 B of CSS
kit.dot()How many are new. Nothing at zero; 9+ past nine.
138 B of CSS
kit.askAgent()The chip that asks: a tap hands the question to your own agent in the Dock, with this page's context, and it never sends for you.
1.5 KB of CSS · needs the shared navbar
Cards, rails, pictures of people and what a page says when it has nothing.
kit.card()A stream, a clip, a room or a place: picture first, the title, who, and one line.
1.3 KB of CSS
kit.rail()A row of cards that scrolls sideways on a phone and wraps on a computer when asked. A long list never makes a long page.
1.3 KB of CSS
kit.mark()A person or a place: their picture, or up to two letters on a colour that comes from the name.
199 B of CSS
kit.empty()What a page says when there is nothing yet, and the one thing to do about it.
1.5 KB of CSS
kit.snippet()Code to copy, with a copy button in the corner.
1.1 KB of CSS · uses kit-web.js
kit.sheet()More choices without leaving the page: up from the bottom on a phone, a dialog on a computer.
1.9 KB of CSS · uses kit-web.js
The shape of a page: its head, tabs, lists, sections and folds.
kit.head()The top of an app page: back, the title, one muted line, icon actions and the tabs. It sticks under the navbar.
1.5 KB of CSS
kit.tabs()Links, so they work without JavaScript. For settings and explainers, never to hide content.
313 B of CSS
kit.list()Rows under a title, with a link to all of them.
707 B of CSS
kit.row()A mark, the title with a badge and the time on one line, one muted line under it. The whole row is the link.
607 B of CSS
kit.pageHead()The top of a page: the way back, the page's icon and title, its actions, and one line saying what it is for.
1.5 KB of CSS
kit.section()A titled block of a page, with its count and one quiet note.
745 B of CSS
kit.fold()A card that opens: setup, extras, the danger zone. It says what is inside and how much.
1.5 KB of CSS
kit.sidebar()Navigation down the left on a computer, a drawer on a phone.
1.7 KB of CSS · uses kit-web.js
kit.page()The whole shape of an app page in one call; the side column sits beside the content from 1024 px, under it below.
1.1 KB of CSS
Settings rows, search, the composer and the file drop.
kit.find()A search, or "add by name": a pill with an icon, the field and a round button.
518 B of CSS
kit.dock()The one thing you type, pinned at the bottom. Enter sends; it grows as you write.
647 B of CSS · uses kit-web.js
kit.switchRow()An on/off setting: the label and a hint on the left, the switch on the right.
586 B of CSS
kit.rangeRow()An amount: the label, the slider and its value.
463 B of CSS
kit.selectRow()One choice of several, as a row.
429 B of CSS
kit.seg()Two to four choices you can see at once.
423 B of CSS
kit.segmented()Three or four equal choices filling the row, each with an icon; the radios post without JavaScript.
437 B of CSS
kit.chips()Filters you can turn on and off, or one of a few.
432 B of CSS
kit.saveBar()The save button of a settings form, kept in reach above the phone's app bar.
1.3 KB of CSS
kit.drop()Where a file goes: a real file input, plus drag and drop, paste and the phone's camera.
1.7 KB of CSS · uses kit-web.js
Numbers, steps, tables, charts, rankings and meters.
kit.labels()What a stream, recording, picture or post carries (nudity, strong language, graphic, 18+, flashing lights, spoilers), in words. Only the labels in force: a suggestion is the creator's to confirm. The page marks the thing itself with kit.labelsAttr so each viewer's own choice (show, blur, hide) applies.
271 B of CSS
kit.stats()A strip of numbers that matter. Zero and unknown are left out; it scrolls sideways on a phone.
436 B of CSS
kit.num()A number the way a reader wants it: money, compact, percent, time. Missing is "–", never 0.
No CSS of its own
kit.steps()A flow of a few steps. Done steps link back; later ones never link ahead.
742 B of CSS
kit.table()Plans, prices, endpoints: anything compared across columns. On a phone each row becomes a card.
615 B of CSS
kit.chart()Line, area, bar or scatter. Text stays its real size at every width, and a table with the same numbers sits behind it.
845 B of CSS · uses kit-web.js
kit.rank()A leaderboard: the place, the name, the value with its interval, the change, a bar in proportion.
714 B of CSS
kit.meter()How full something is. With tone auto, a limit turns amber from 75 % and red from 90 %.
164 B of CSS
One order for every tool page: what it does, the input, the answer, the family.
kit.toolHead()What the tool does, in its colour, with the facts that matter (free, no sign-in, what is kept).
571 B of CSS
kit.toolInput()The one field a tool needs, its button, and examples to try.
1.8 KB of CSS
kit.answer()The answer first, then its rows, then what to do next.
1.6 KB of CSS
kit.family()The tools next to this one.
459 B of CSS
kit.tool()One order for every tool page: head, input, answer, family, folds, related.
2.5 KB of CSS
kit.tries()Examples a person can run with one tap.
308 B of CSS
Notices, receipts and the shape of a page while it loads.
kit.notice()A sentence about what just happened: ok, info, warn or error. Errors are announced.
438 B of CSS
kit.receipt()A result and what it took: the answer first, then one quiet line of facts.
1.5 KB of CSS
kit.skeleton()The shape of what is coming, so nothing jumps when it arrives. It never spins.
322 B of CSS
Small functions with nothing to draw.
kit.esc(text)kit.labelsAttr(labels)kit.LABEL_NAMESkit.url(href)kit.mediaW(url, width)kit.icon(name)kit.when(ts)kit.hueOf(key)kit.tabOf(query, keys)kit.enhance(el)Eleven parts are also drawn natively, in Jetpack Compose and SwiftUI: see Components. The icons are at Icons.