# custo-viewer The web view behind **[www.cust.ooo](https://www.cust.ooo)** — a fork of [ssb-viewer](https://gitlab.com/dwynen/ssb-viewer) that renders custo items from a Scuttlebutt pub. Upstream's own docs are kept verbatim in [UPSTREAM-README.md](UPSTREAM-README.md). ## What custo adds | | | |---|---| | `/items` | One merged grid of every item the pub knows about, across all kiosks. New kiosks appear by being followed — no code change. | | known-blob gate | `serveBlob` only serves blobs referenced by a feed we replicate, so the node never hands out a stranger's cached blob. | | exit on dead sbot | `bin.js` exits when its muxrpc handle dies, instead of holding the port open and hanging every request forever. | | `blob-wanter.js` | Standing `blobs.want` orders for our own feeds' blobs, replacing what `ssb-blobs` `sympathy` used to do before it was turned off. | ## The data model An **item** is an ordinary `type: "post"` carrying custo's own fields: ```json { "type": "post", "custodisco": "true", "nft": "mint", "text": "![photo.jpg](&…sha256)\n\n…\n\n a #custodisco item ", "mentions": [{ "name": "photo.jpg", "type": "image/jpeg", "link": "&…sha256" }] } ``` A **transfer** of custody is a reply to that message: ```json { "type": "post", "custodisco": "true", "nft": "give", "target": "@…ed25519", "root": "%…sha256", "branch": "%…sha256" } ``` Two things to know before writing a query against this: - `custodisco` is the **string** `"true"`, not a boolean. - **No message ever sets `content.channel`.** The `#custodisco` hashtag exists only in post text. Anything keyed on the channel index will silently return nothing — which is why `/channel/custodisco` renders an empty page. Messages are published by the kiosks (`/home/trav/custodisco-kiosk/ssb-post.sh`), not by this viewer. The viewer is read-only. ## Changing how pages look Everything visual is in **`render.js`**. There is no template directory and no CSS files to hunt through — pages are built as strings and there is exactly one `