# @leumas/livepools-web — Leumas LivePools, at livepools.leumas.tech

Leumas LivePools at livepools.leumas.tech — put every live source you care about into one pool and read it as one real-time stream: in the browser, from the Fusion Node on your own machine, or from...


Put every live source you care about into one pool and read it as one real-time stream — in this
browser, from the LivePools Node on your own machine, or from an application through `@leumas/livepools`.

```
pnpm dev:livepools                          # vite on :5085, API proxied from :3000, /ws proxied too
pnpm --filter @leumas/livepools-web build   # vite → prerender → crawler files → check:livepools-public
pnpm check:livepools                        # the wiring invariants (+ --self-test)
pnpm check:livepools-public                 # every route indexed, or excluded with a reason
pnpm smoke:livepools                        # the MVP chain, headless, against a real API
pnpm smoke:livepools-site                   # the row through the real Imperium worker, /ws claimed
```

## The product, in one line

```
SOURCE ──-> observation ──-> POOL ──-> browser · @leumas/livepools · SSE · rules
```

Every source becomes `{ id, pool, source, type, ts, data, meta }` (`@leumas/fusion-protocol`) and
nothing downstream learns the transport. The browser is one consumer among several, not the product.

## Where things are

| | |
|---|---|
| `src/pages.js` | THE page table — router, sitemap, llms.txt, nav, prerender and the guard all read it |
| `src/lib/live.js` | the page's one `/ws/livepools` socket: subscribe, publish, reconnect, re-subscribe |
| `src/lib/bridge.js` | the browser sources: serial (Web Serial), camera + motion, microphone level, GPS, Bluetooth, this machine, a note |
| `src/components/LiveView.jsx` | tiles for every field's current value per source, and the live log |
| `src/screens/Pool.jsx` | Live · Sources · Rules · API (keys are minted here, plaintext shown once) |
| `src/screens/Connect.jsx` | the bridge page — each source its own card with its own Start (user gestures) |
| `shared/engines/fusion` | the engine: store, hub, controller, router, gateway |
| `shared/packages/fusion-node` | the node runtime; `products/standalone/leumas-fusion-node` is its shell |
| `shared/packages/fusion-client` | published as `@leumas/livepools` |

## Traps this site keeps

- **`/api` is a proxied prefix** — the docs page is `/docs`, never `/api`.
- **Root assets are namespaced `fusion-`** — the apex build is mounted first on every host.
- **`createRoot`, not `hydrateRoot`** — the prerendered article is not what React renders.
- **A camera, a microphone or GPS never becomes public by default.** Every pool starts private.
- **Every Start is a click.** Web Serial, the camera, the microphone and Web Bluetooth all need a
  user gesture; a "start everything" button would open one and lose the rest.


## [critical] Three surfaces, three different jobs

This is the rule new work here is held to, and it is what makes "cinematic" and "instant" compatible
instead of contradictory. Getting it backwards is the easiest mistake to make on this product,
because every one of these is the same dark deck and looks like it wants the same treatment.

| | job | treatment |
|---|---|---|
| `/`, `/pricing`, `/download`, `/enterprise` | **persuasion** — seen once or twice | Cinematic. May cost a little. Must never block first paint. |
| `/connect`, the first pool | **the moment** — ninety seconds to a real reading | Warm and guided. It ends at a **live number**, not a success toast. |
| `/pools`, `/pools/:id` | **the instrument** — opened forty times a day | Dense, fast, quiet, keyboard-first. **No decorative motion at all.** The only thing that moves is data. |

Concretely:

- `CinematicHero` and `PoolConstellation` are `lazy()`. The prerendered static hero is the LCP element
  and is complete on its own. In the eager path they would tax every route — including the pool page
  an operator lives in. `pnpm check:livepools-budget` asserts `lp-const__spoke` is in its **own**
  chunk and not the entry.
- **No entrance animation on a prerendered page.** The words are already on screen when React mounts;
  fading them in means they were there and then were not. `Suspense` falls back to a reserved BOX.
- `prefers-reduced-motion` is honoured everywhere, and nothing the picture *says* is lost when the
  motion stops — which is the test of whether the motion was content or ornament.
- `FirstReading` removes itself the instant an observation lands. The tiles are the success state;
  putting a congratulation between somebody and the thing they came for is worse than saying nothing.

## Guards

```
pnpm check:livepools            # 18 invariant groups (+ --self-test)
pnpm check:livepools-public     # every route advertised, crawler files on disk
pnpm check:livepools-head       # JSON-LD parses; unique titles, descriptions, canonicals
pnpm check:livepools-budget     # a MARKER grep first, byte ceilings second
pnpm smoke:livepools            # 54 checks — the chain, quotas, CORS, webhooks, audit
pnpm smoke:livepools-realtime   # 35 checks — latency, gap replay, slow-consumer eviction, clocks
pnpm smoke:livepools-site       # the Imperium row, deep links, /ws claimed
```


---
Source: products/leumas-livepools/README.md
Canonical: https://docs.leumas.tech/p/products/livepools-web
