Pp2pbuilders
learn › Build articles

8 min read · also at #/learn/build-terminal

Building the terminal HN

p2pbuilders shipped as a terminal app: pear run Legacy app — migration required: pear://… drops you at
a prompt on a live P2P board. This article is how it is built and the
decisions that got it out the door.

Architecture

Two halves, cleanly split:

per identity), the op schema, PoW minting/checking, the Hyperbee indexer
that folds every tracked core into hot/new/top views, reputation, rate
limits, and a Hyperswarm layer with a protomux announce channel. All
runtime-portable via one _rt.js shim (Bare walkthrough).

tiny state machine — feed view, thread view, compose mode. Commands are
first-word dispatch (submit, open 3, up 2, reply, …). ANSI
colors and a screen-clear redraw; a debounce coalesces peer-driven
refreshes so gossip storms do not flicker the screen.

Everything crosses one JSON-RPC dispatch layer — the same method surface the
dev HTTP/WS server and the (parked) iOS pipe use. The UI cannot reach into
internals; every transport gets the same API.

Decisions that shipped it

scope. One front feed cut it to a screen and a half of rendering; the
data model kept the board field, so the pivot cost nothing on-chain.

the terminal became the product. A readline loop has no build step, runs
identically under Bare and Node, and made the P2P parts — the actual hard
parts — the whole job.

type lines, . submits, :q cancels. The whole editor is ~60 lines.

constant enforced by the indexer (admin tombstones are honored for any
target; everyone else, own ops only). Pinned posts are a hardcoded opId
list. Governance-by-recompile is honest for the current scale — the
enforcement point (indexer, not UI) is what makes it real.

What it proved

41 tests cover every layer; the same backend booted under raw Bare (the iOS
milestone) without changes. The bet that "the app is the log + the fold, the
UI is whatever is cheapest today" — the whole premise of the
foundations track — held.

« PoW + reputation: honest limits One engine, two apps: porting to the browser »