OpenVibe.Shared
Every shared release, and where it shows
Every release of the shared package, newest first, in its changelog's words, with the screens it changed.
- releases
- 375
- with screenshots
- 6
- pinned
- 4.235.0
The layers: what floats folds into a small handle and grows to the window, and what opens from a button is anchored to it (the owner's phone, watching a live stream, 11-13: "a small button that lets you pop it in and out", "doesn't allow it to be off screen", "I can't even resize it bigger", "the little three dots doesn't actually open a menu").
- ov-float.js, tucked.
- Thrown past a side (or T, or a tuck button), a box folds into a small handle at that edge: 30 × 64 px, 34 × 72 to a finger, set with
--ov-float-tab-w/-h. It used to leave a strip as tall as itself hanging off the screen. - The fold is a clip animated with the Web Animations API, so nothing inside is squeezed, while the landing's spring moves it to the side.
- The handle is a button that moves: a tap opens it, a drag up or down slides it along its side, and a pull sideways brings it out under the finger.
- Tucked by hand, it opens again where it was (
ux, kept in this browser only).
- Thrown past a side (or T, or a tuck button), a box folds into a small handle at that edge: 30 × 64 px, 34 × 72 to a finger, set with
- ov-float.js, size.
- It grows to the whole width of the window:
MAX_Wis 1 (was 0.60). - Past what a docked frame holds (its width, or 85% of its height), a pinch, the corner or + lifts it over the page where it is, and it keeps growing, up to 92% of the window's height.
- A double tap on a phone makes it the screen's width.
- New
f.sizeTo(px).
- It grows to the whole width of the window:
- ov-float.js, the place.
- This browser's place wins. The account's (
/api/me/layout) fills a device that has none, so a phone and a desktop each keep their own. - The account and
onChangeget only the account's fields (placeOf), never the browser's extras. - A turn of the phone, the keyboard (the visual viewport), the address bar or a resize puts it back inside, once a frame.
- While it moves, nothing in it is blurred: a backdrop blur repainted every frame made a phone's drag stutter.
- This browser's place wins. The account's (
- surfaces.js,
OVSurfaces.anchor(el, trigger, { place, gap, margin, sheet, animate }).- The element goes in the top layer (the Popover API; fixed without it). No
overflow: hidden, mask or stacking context clips it. - It is placed beside its button:
placeis side-align. It flips to the side with room, shifts to stay inside the visual viewport, and is kept no taller than its side's room. - It is placed again on scroll, resize and size changes, and released when its button leaves the page.
sheet: 'phone'makes it a bottom sheet under 560 px.data-ov-sidesays where it went, and the default entrance grows from the button.OVSurfaces.popover({ …, pop, place, sheet })anchors its menu while it is open.
- The element goes in the top layer (the Popover API; fixed without it). No
- kit-web.js. Every
details.ovk-moremenu is anchored, not only those inside a rail: a phone's clipped layout, a sheet or a rail no longer hides it. - Tests:
ov-float-chrome(the handle's size and place, a slide, a pull, growing past the frame, a phone's double tap, this device's place, the account's fields) andsurfaces-chrome(a clipped menu at a phone's bottom opens above, on top, inside the screen, and is released;placeBox).
Rules39 The account lives in the menu's You tab, not in a dropdown.
The bottom bar hides all the way, and the composer stops repeating itself (the owner's phone screenshots, 11-13).
- The bottom bar (
appbar.js). It stepped aside for a keyboard or an open panel withtranslateY(110%)while its lift above the visible viewport still applied, so above a keyboard, or with Android's toolbar gap, it stopped half on the screen. A hidden bar now drops the lift, sits fully below the screen, and is invisible and not clickable until it comes back. - The + sheet. It no longer repeats a tool the row already shows; the emoji button and an "Emoji" tile side by side were the same thing twice. The sheet holds what a narrow row hides, and the extras (Timer, GitHub).
- The GitHub picker:
- each row's mark is its owner's initial on a colour of the name; GitHub's own pictures were blocked by most sites' image policy, so every row showed a broken picture, and each one asked GitHub;
- the same words are answered from the page's cache for ten minutes;
- a new search cancels the one still running;
- it waits a third of a second after the last key;
- the list scrolls inside its panel and no longer runs over the box.
- Tests
composer-v2-chrome(nothing repeated, the initial, the cache) andnavbar-appbar(hidden is all the way).
PagesThe navbarThe kit
Rules41 The site's name in the bar opens that site's pages, Home first.96 The Pair is the only mark, and it does the waiting.31 One navbar per page, owned by the shared Frame.
ov-metrics.js on a phone, and prices under a dollar.
- A narrow table is cards (
OVMetrics.table):- in a box under 520 px wide (a container query, so a side column counts too), each row is a card: its name on top and each value under its label;
- the column heads become a row of sort buttons, and the one in use is outlined;
- nothing scrolls sideways;
- the table, its rows, cells and heads carry their roles, so a screen reader still reads a table whatever the display.
format.usdkeeps two significant digits under a dollar: $0.0118 is$0.012, not$0.01; $0.25 stays$0.25. A per-call price no longer rounds away.- Test
ov-metrics-chrome: the card form at 390 px, the labels, the roles, no sideways scroll, and the new prices.
ov-metrics.js: the network's one way to show numbers (ai-metrics.md). Report, Exchange, Compare and the admin panel draw their AI and usage numbers with it, and nobody draws a chart of their own. The look is the theme's (tokens only). Every piece works at 390 px and in both themes, and stays still with motion off.
OVMetrics.tiles(): label, value, unit, a delta that knows whether up is good, a sub-line and a trend..spark(): a trend line with its last point..bars(): a ranked bar list..percentiles(): p50, p90 and p95 on one scale, with a spoken summary..split(): one bar in parts, with a legend..table(): sortable on a click, witharia-sort, numeric columns and an optional in-cell bar.OVMetrics.format: the same words everywhere, and servers get them fromrequire('openvibe-shared/ov-metrics'):ms(540 ms · 1.3 s · 1 min 38 s),usd($0.0042 · $61.20),count(18k · 9.1M),tokens,rate(99.4%);tps(86.0 tok/s),bytes,delta(+12%);- unknown is a dash, never 0.
- Test
ov-metrics-chrome.
Rules4 Calm makes motion smaller and slower. Only Off removes it.31 One navbar per page, owned by the shared Frame.
OpenVibe's own icons, and no Font Awesome drawing left (the owner, 11-12: "make sure no remnants of font awesome or other libraries are still being used rather than our openvibe.design systems").
- The ring icons' solids are the glyphs' own. Nine product icons (Network, Live, Tools, Media, Games, Community, Chat, Domains, Bench) drew Font Awesome outlines as their solid twin. Each is now the solid drawing of the glyph that stands for it, on the same 24-unit grid as the line drawings. Exchange keeps its line drawing until
swaphas a solid.scripts/build-navbar-icons.jswrites them fromglyphs.jsand refuses any drawing that is not a glyph. - The generator that read Font Awesome's font is gone (
scripts/build-nav-icons.py;npm run build:iconsisbuild-navbar-icons.js). The bar's dead 512-grid path innavbar.jswent with it. - OpenVibe's own markup:
<i data-ov-icon="eye">names any glyph and<i data-ov-brand="github">any logo, drawn byov-glyphs.js;- classes
ovg-xs…ovg-3x,ovg-fw,ovg-rotate-*,ovg-flip-h/-vandovg-fill(whatfa-soliddid); OVGlyphs.icon(),.html()and.has()in a page, andglyphs.markup()on a server;- the drop-in now carries every glyph (287), and the navbar loads it for this markup too.
- The bar draws glyph names: a name the bar's set lacks is drawn as
<i data-ov-icon>, never as Font Awesome. scripts/fa-to-ov.jsrewrites a repository's static Font Awesome markup intodata-ov-icon/data-ov-brand. It keeps each attribute's own quote, and running it twice changes nothing. It lists what a person has to decide (names built at run time, JS class strings, CSS rules, animations, unknown names).glyphs.fromFaClasses()is its mapping.- Names that drew nothing now draw their glyph:
arrow-rotate-left,chart-pie,book-skull,crosshairs,location-crosshairs,satellite,globe-americas,street-view,magnifying-glass-location,apple-whole,backpack,shield-heart,openstreetmap; and the logosreddit-alienandkickstarter-k. - Test
fa-to-ov.
PagesThe bar’s brandThe navbarIconsRules
Rules92 The menu's places: Here, Feed, Chat, Vibe, You; Vibe holds Chat and Agents.2 An icon name is checked against the set that draws it.31 One navbar per page, owned by the shared Frame.
- OpenVibe's own controls on every site (the owner, 11-12: "improve the selection boxes to use a more customized look integrated into openvibe.design and themed better with animations and effects for all inputs and buttons").
ov-forms.cssnow draws every checkbox and radio: a rounded box whose check pops in, and a ring whose dot grows. The mark is the box's own::before(a clip-path check, scaled), so no picture is fetched. Both lift their border on hover, squeeze on a press and glow with focus; the mixed state is a bar; disabled is faded. A switch (role="switch") glows when on, its knob squeezes when pressed, and it has a focus ring. Buttons answer a press, and text fields, text areas and selects glow in the accent with focus. Everything is:where(), so a site's own rule wins;data-ov-nativekeeps the browser's control; motion follows the person (Calm slower, Off moves nothing). - The bar loads
ov-forms.csson any page with a text field, a text area or a button. The select kit's script still waits for a select, a box or a file input.
PagesThe navbarMotionThemesThe kit
Rules94 A site's name opens its pages, and a way to every site.4 Calm makes motion smaller and slower. Only Off removes it.10 A change is New, Improved or Fixed, and says so with a small mark.
- Back brings you back to the menu (the owner, 11-12: "fix the history back button so it properly brings you back to this GUI rather than the page behind it"). Leaving through a link in the menu marks where it was on its history entry (its place, its door, its scroll); Back to that page opens the menu again there, whether the page comes back from the browser's cache, loads again, or a site swaps it in place (Boost). It reuses that entry, so Forward still works, and closing it then leaves the page as it was. Only for a Back or Forward within half an hour.
- Links are on their way before the click: anywhere on the page (the bar, the menu, a footer, a card), a finger landing on or a pointer resting on a link to another OpenVibe site opens its connection at once; this site's pages were already prefetched by the bar's speculation rules.
- All apps has one search (the owner, 11-12: "confusing"): no second box under the menu's pill. The pill reads "Find among 64 apps" and filters the apps in place; the view's head is its name, its count and a hint, coming in with the view. Back on Home, the pill searches OpenVibe again.
- The close x has no white ring: the ring that leaves it as the menu opens is invisible at rest, so where animations are off (a phone's "Remove animations") it no longer stays as a white circle.
- The Feed never shows a card twice: a card id already on the list is skipped (Network names a Deals burst once, as of its #887).
- Feed cards with no person wear their site's app icon (design rule 142), 40 px beside 40 px faces, the glyph filling the square (the owner, 11-12: "icons to increase size").
- Any button can open a place in the menu (the owner, 11-12: "other tools and buttons can open specific areas of the menu"). A menu address is a place, or place/part:
you/notifications,you/apps(All apps),you/recent,feed,here/live, or a door (vibe,chats,agent,code,tasks). Any element withdata-ov-menu="you/notifications"opens it on a click, on any page with the bar; a link with an address still opens elsewhere with a modifier key. A page address ending#ov-menu=you/notificationsopens it as the page loads (on any OpenVibe site), and a same-page link to it works too; the hash leaves the address.OpenVibeNavbar.openMenu(address)andOpenVibeNavbar.menuAddress(address)take the same addresses; OpenVibeHome'sshow('drawer')opens All apps. - One search field for every site:
ov-searchbox.js(the owner, 11-12: "improve the search field … autocomplete, dropdown, animated effects … a shared, universal, reusable search input component").<input name="q" data-ov-searchbox="/api/…/suggest" data-ov-examples="streams|clips">in a form becomes a pill: the search mark, the field, a clear button and a "/" key hint on a computer; its edge glows with focus. The placeholder walks through the examples while idle (Calm slower, Off never). Suggestions come from the source in OVCombo's shape, with icons (search, recent, page, person, live, video, place) or a small picture; while empty, the person's recent searches here. The first suggestion that starts with the typed words shows the rest as a ghost: Tab or → takes it. Enter searches the typed words (the form's action) or the chosen row's page; "/" anywhere puts the cursor in it; Escape closes, then clears.OVSearchBox.mount(input, { source, examples, scope, recent, onSearch }); a cancelableov-searchevent lets a page search in place. - OVCombo grows hooks for anything that is not a value picker:
pick,enter,onRows,selectFirst: false,none,limit,cacheMs,anchor; rows takeiconorimage; the skeleton no longer flashes over rows already showing while a quick answer comes. - The navbar's budget is 52 KB brotli (51.6 KB with the menu addresses).
PagesThe search pillThe menuThe footerThe navbar
Rules92 The menu's places: Here, Feed, Chat, Vibe, You; Vibe holds Chat and Agents.94 A site's name opens its pages, and a way to every site.36 The menu button opens on the site you are on.
- A page's sections as tabs on a phone (the owner, 11-11: "consolidate these into tabs, self-contained tabs, so the page isn't so freaking huge … at least on mobile").
showcase.parts({ name, items: [{ id, label, count, html }], front })shows one part at a time with a tab bar (its name and count) at 900 px and under, 600 for a front page; every part stays in the HTML (crawlers, AI readers); radios and:has(), no script; the arrow keys move between parts; wide screens and browsers without:has()stack them.ov-parts.cssis the same look alone, for a page that does not load showcase.css (Live's home). showcase.pick(): the pick block, once. Twenty-five sites kept a copy of a "pick block" (server/render/short.js) whose chips only jumped to a pane, so a phone still showed them all.pick({ key, label, head, panes, checked })is that block onparts(): a heading, then tabs on a phone, every pane in the HTML with its id,ov-parts.csslinked by its hash.parts()takescheckedtoo, and a link to something inside a part opens it (CSS:target, no script).- Caption it with AI. A picture in any composer has ✨: one tap sends it, made small (JPEG, 768 px), to the Frame's
/api/frame/captionon the person's own allowance; the caption fills an empty box (theirs to change) andovc:captioncarries the alt text.ctx.alt(file)andctx.caption(file)for a page;data-ovc-caption="off"leaves it out. OpenVibeNavbar.token()reads the person's Network token the site gaveinit(). Caption it sends it as the Bearer on any site (the Network's session cookie is not sent cross-site), and the composer's settings sync, which asked for it all along, now finds it.- A picture alone is a post. The menu's Feed composer no longer asks for a description of every picture: one left empty is written by AI as it posts, and a post goes without one if that cannot be done.
- One app icon, drawn on the server too (design rule 142).
OpenVibeIcons.appHtml(site, { size, label, hue })returns the app icon as markup (no DOM needed): its hue and size inline and its glyph already drawn, soov-icons.jsfinds nothing to fill and nothing moves when it arrives.OpenVibeIcons.APP_CSSis the app icon's own rules, sizes 20 · 26 · 32 · 44 · 56 · 64 included: a server-drawn page puts it in its stylesheet once and its icons are whole before any script runs. - Every site's "More on OpenVibe", app launcher and next steps draw sites as their app icons (showcase
network(),apps(), the next-step list), whole on the server and the same as the menu's: 44 px in a row, 56 px as a launcher tile on a phone. A non-OpenVibe glyph (fa-…) keeps its tile. - The square keeps its size before
ov-icons.js: the navbar's early rules hold every.ov-appiconat itsdata-size, so a page's app icons no longer pop in. - The menu's "Across OpenVibe" sites and a quest's steps wear their app icons instead of a small glyph in a ring.
- The Feed's chips name the one feed's new kinds: Rundown, Jobs, Deals and Stats, beside the media kinds.
- A release reaches a returning visitor within minutes: an unversioned asset (
cache-policyassetHeaders) keeps five minutes of stale-while-revalidate, not a day. Sites loadnavbar.jswithout?v=, so the first visit to each site after a release ran the old menu. - /updates passes its contrast check again: a filter chip's count no longer fades to 70% (axe color-contrast, serious, on every site's /updates; the release browser check had paged as critical).
PagesThe quest cardThe menuThe navbarIcon ink
Rules94 A site's name opens its pages, and a way to every site.31 One navbar per page, owned by the shared Frame.90 Assets are addressed by their content, so people always get the current one.
- The menu's feed draws the one feed's new kinds (feed.item@1) (the one-feed job's finding: they fell through to a bare card):
- A report is its number, large, with which way it moved and from what (▲ 12%, was 1,075).
- A folded run (new jobs, new deals) lists its first three, each with its picture where there is one, rows lined up, then "and 11 more".
- What a count means is said: "14 jobs", "41 voted";
counts.watchersreads "watched". - The Rundown is about its actor (feed.item@1's
subjectis a person's id, so the old reading found nothing). - A card without a person no longer says its text twice.
menu-feed-v2-chromechecks each.
PagesThe menu
The menu's Vibe is one place: All · Chats · Tasks · Code, no switch (the owner, 11-12, crossing out the Chat · Code · Agents switch: "one new unified agent … a shared UI").
- Vibe opens on All: every run from the Frame (Vibe chats, tasks, coding runs) in one list (
ov-run.js, 4.224.0).- The Action Center's waiting and running work from every product (Network
/api/v1/me/actions) joins it, unless a run already shows it. What needs you comes first, approved or declined in place; the rest open their own pages. - Above the list: the Dock's Now and timeline, your Actor and your agent's live view (lent with
OpenVibeDock.mountInto(el, { tab: 'agent', part: 'top' })). - Vibe's six starters sit above the box; a press starts that run. Enter in the menu's field starts a run too.
- The Action Center's waiting and running work from every product (Network
- Chats, Tasks and Code are the Dock's own panels, lent whole (Vibe's conversations with voice, undo and the timer; Agents with its history, skills and filters; Code with its repos). They move into the one view when it does all they do, so nothing is lost on the way.
- The Dock's places open their filter:
OpenVibeDock.open({ tab: 'vibe' })opens Chats,'agent'Tasks,'code'Code. The status on the menu button still opens what needs you.OpenVibeNavbar.openMenu()also takes'code'and'tasks'. ov-run.jsgains:o.starters;o.actions: { base }, the Action Center's work in the list;o.top(el), the host's slot above the list on All;o.panes: { chat, task, code }, filters the host draws itself;o.onPlace;view.prefill(text), words in the box, unsent.
- A system light theme darkens the agents' glyphs.
- The menu scrolls on a phone wherever the swipe begins (the owner, 11-12: "scrolling is very buggy … on mobile … especially in notifications").
- Inside the menu, the notifications list was a scroll box of its own that held its overscroll. It never overflowed there, so a swipe that began on a notice moved nothing.
- Inside the menu it is now part of the menu's one scroller (one scroller per layer).
- Measured with real touches at 390 px, and checked on every tab: nothing else nests a scroll box like it.
- New test
notifications-menu-scroll-chrome(it fails without the fix). notification-ui.js's brotli budget grows from 25.9 to 26.1 KB for it.
- The composer's + has GitHub.
- It searches repositories through OpenVibe Exchange's code search (the Frame's
/api/frame/code/search, Network #878) a quarter second after the last key. - Each row shows the owner's picture (GitHub's avatar host only), the name, the description, the language, stars and the licence, all as text. Enter or a press puts the repository's address in the box, where every site draws it as a card.
- A box may point it at another Network with
data-ovc-frame.composer-v2-chromechecks it.
- It searches repositories through OpenVibe Exchange's code search (the Frame's
- One app icon for every site:
.ov-appiconandOpenVibeIcons.app(site, { size, label })(design rule 142).- It is the menu's and Home's own icon: the app's steady hue on a rounded square, with its glyph drawn over it.
- Use it from markup (
<span class="ov-appicon" data-icon="live" data-size="64">) or from script. Markup added later, or an app that changes, is drawn again. - With a label it is an image with a name; otherwise it is decoration.
OpenVibeIcons.hue(id)is the shared hue.ov-appicon-chromechecks it.
- Home on a phone: a long press then a move keeps the app under the finger.
- Entering Edit repaints the grid, so the tile under the finger left the page, and the grid's touch guard no longer heard that touch: the first move scrolled the menu and cancelled the press.
- The guard now rides on the pressed tile itself until the finger lifts.
menu-home-screen-chromedrags with a real touch (it fails without the fix).
- The menu reads runs and the Action Center from the Dock's Network base (
runsBase). - Tests:
dock-chromegains the All view at 390 px: the four filters on All; a run and the Action Center's work in one order; the Dock's top lent without its list; the starters; Tasks as the Agents panel, remembered by the Network; approve in place from All. Every Dock check before it still passes unchanged.run-thread-chromegains the starters, the Action Center's rows (nothing twice), the host's slot, the place and prefill.menu-places-chromeandmenu-home-screen-chromefollow the filters in place of the switch.
PagesThe avatarThe menuThe DockIcon ink
Rules92 The menu's places: Here, Feed, Chat, Vibe, You; Vibe holds Chat and Agents.94 A site's name opens its pages, and a way to every site.41 The site's name in the bar opens that site's pages, Home first.
One thread view for every run: chats, tasks and code (the owner, 11-12, crossing out the menu's Chat · Code · Agents switch: "one new unified agent … a shared UI … a full conversation with rich embedding").
- New module
ov-run.js(OpenVibeRun) draws any run from the Frame's Run API (Network/api/frame/runs; Contractsagents.run@1,agents.step@1), on every site:OpenVibeRun.mount(host, { base, token, me, sibling, examples, start, filter, open })returns{ list(filter), open(ref), start(text), destroy() }.OpenVibeRun.card(type, render)adds a rich card for a step'sui.type; built in:results,table,link,code. A card it does not know shows the step's words.
- The list:
- Filters: All · Chats · Tasks · Code.
- Order: what needs you first, then newest.
- Each run shows its agent's face (its picture, or its glyph on its own hue, with a badge saying what it is doing), its title in the brand face, its last line and when.
- Pills say "Needs you", "Working" and "Did not finish". A product that did not answer is named under the list.
- A run that asks before it acts is answered from the list: Approve or Not now, in place.
- A filter reloads only the rows, so the words you are typing stay.
- The thread:
- Your words on the right. The agent's on the left: paragraphs, lists, bold, inline code, links, and numbered sources whose [n] marks link to them.
- Thinking is folded. Each tool is one quiet row (it opens to its output).
- An approval is a card with its answers. Child runs are rows that open them; files are chips or pictures.
- It follows the run live: server-sent events read with fetch, so the bearer goes along, resuming after the last step it has.
- The composer underneath says the next thing. A new run starts from the list's box, sent once with an idempotency key.
- Page text is never markup, and only https links are drawn.
- The menu keeps the Dock's panels for now. Its Vibe moves to this view (and the switch goes) once the view does everything those panels do:
- the Action Center's items from every product, approved in place;
- the live agent view (Pause, Curtain, Mute, End);
- Vibe's starters and voice;
- "Ask your agent" from a page;
- the place the Network remembers.
- Arrange: Stop is an ordinary optional part; it docks right like any other (#501).
ov-run.jsandov-composer.jshave content hashes inSIBLING_REV, ready for the menu. Every site servesov-run.js(files.js), and the package exportsopenvibe-shared/ov-run.- Tests:
- New
run-thread-chrome(390 and 1280 px): the list and filters; approve in place; every kind of step; the live stream and where it resumes; approvals, messages and a new run reaching the API with the person's token; no markup from page text; no overflow.
- New
PagesThe bar’s brandThe menuThe DockIcons
Rules92 The menu's places: Here, Feed, Chat, Vibe, You; Vibe holds Chat and Agents.94 A site's name opens its pages, and a way to every site.90 Assets are addressed by their content, so people always get the current one.