travandClaude Opus 5 fc9539a618 /items shows items only, not custody transfers
A `nft: "give"` message is a change of custody, not a thing. It has no photo of
its own, so it borrowed the photo of the item it transferred - which meant the
same object appeared on the grid twice, a few cards apart, distinguished only
by a dimmed image and an id overlay. That reads as a duplicate, not as a
hand-off.

Custody is better answered one level down. Each card already links to its
item's thread, where the mint and every hand-off since are in order, with the
steward resolved. So the overlay was showing a truncated feed id on the grid to
save a click that is worth making.

Filters on nft === "mint" rather than excluding gives: every custodisco message
carries one of the two - checked across all 407 - so matching mint is exact.
301 items from 3 feeds, down from 407 entries.

The feed count now counts feeds that actually contributed an item rather than
the size of the follow set. The pub follows itself and publishes no items, so
the old number was one too high and would have drifted further as feeds get
followed for other reasons.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0192zBTNZKZn5svyJ5HTnYds
2026-08-22 20:30:46 -04:00
2016-12-15 13:26:20 -08:00
2016-12-15 13:26:20 -08:00
2017-06-10 14:25:21 -10:00
2026-08-22 19:30:42 -04:00
2026-08-22 19:30:42 -04:00

custo-viewer

The web view behind www.cust.ooo — a fork of ssb-viewer that renders custo items from a Scuttlebutt pub.

Upstream's own docs are kept verbatim in 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:

{ "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:

{ "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.

Running it

bin.js connects to a local ssb-server and serves on conf.viewer.port (8807). See UPSTREAM-README.md for the plugin-vs-standalone options.

Deployment

Deployed by rsync from a laptop, not by git pull — the server holds no push credentials, and one deploy path is better than two. The script, the systemd units, the nginx config, and the disaster-recovery runbook all live in the ops repo alongside this one (documents/custo/ssb-viewer), which is the source of truth for the server itself.

Never commit secrets here. Keys and server config belong in the ops repo.

AGPL-3.0+, inherited from upstream.

S
Description
a fork of ssb-viewer for custo items
Readme
485 KiB
Languages
JavaScript 97.4%
Shell 1%
CSS 0.8%
HTML 0.8%