RelayCTX app surface · v1
App surface · diagnosis

25 doors.
Three jobs.

“Something like 35 screens” was the right instinct and slightly understated. But the count is the symptom. The disease is that the navigation is organised by projection instead of by job — and it does not agree with itself about what the product's own object is called.

1 · What is actually there

Measured against relay-app on 2026-08-26. Nothing here is an estimate.

33routes registered via onNavigate()
25nav destinations in the rail
31page panels in index.html
73modules · 30,633 lines of hand-written TS
4screens the streamlined preset hides

That last number is the surprising one. A mechanism for shipping a smaller app to a cohort already exists and is already wired — gating.ts, hide-don't-disable, deep links redirected. Only 9 of 33 screens carry any gate, and streamlined trims the rail from 25 items to 21. The lever is built and barely pulled.

2 · The navigation contradicts its own page

Before any question of how many screens there should be, there is a simpler one: what is the thing called?

The rail says
Transfers
web/index.html
opens →
That page renders
120 relays
web/src/relays.ts · ${total} relays

Relay and Transfer are the same object. “Relay” is the product name; “transfer” is the API-layer name. The API-layer name is the one in the navigation, and the product name is the one in the content — so the first list a new user opens tells them, in two places at once, that it holds two different things. The module behind it is even called relays.ts.

This is a one-word fix with no architectural consequence, and it removes more confusion per unit of effort than anything else on this page.

3 · Ten doors, one question

Sorting all 25 destinations by the job a person is actually trying to do rather than by what engineering built, the surface collapses to three groups — and one of them is enormous.

Find something I already have9 doors + Inbox
RelaysInboxSeries StreamSessionsGraph LibraryCatalogSearch Trash
Move context in or out4 doors
SendReceive CaptureConnect
Manage who I am and who we are9 doors
AccountProfileSettings OrganizationsTeamNetwork ContractRequestsGetting started

Nine of those ten are the same corpus under a different filter. Series is relays grouped by name. Sessions is relays grouped by agent run. Stream is relays grouped by thread. Library is relays in folders. Trash is relays with deleted. Graph is the same set drawn as nodes. Search is a query over it. Nobody opens an app wanting the Series projection — they want to find a thing.

Correction, 2026-08-26 — Inbox is the exception, and it matters. This page first listed Inbox among the duplicates on the strength of its name. Reading inbox.ts says otherwise: it carries relays shared with you that you have not yet received, and those sit in neither direction of the relay list — so that list structurally cannot show them. The module records the incident behind it: a sender was told nothing had been sent while the relay sat unreceived. Inbox stays. Nine doors, not ten.

That is why it reads as confusing rather than merely large. A person cannot predict which of ten doors holds their thing, because the doors are not divided by anything they know about their thing — they are divided by how the system stores it.

4 · The fix is mostly already built

This would be a rewrite, except that the two hard parts already shipped.

Already in the repoWhat it means
One shared list shell
packages/ui/list-shell.css · 10 KB
Consumed by relays, series, sessions, files and trash — five of the ten projections already render through the same anatomy. Screens sharing a shell can share a screen.
A working cross-type table
concepts/app-v35/catalog.html
The Catalog “Objects” tab already lists relays, series, sessions and streams together, with a type facet, click-to-sort and a pager. The merged corpus screen is not a proposal — it is a prototype you can open right now.
A shipping reduction mechanism
web/src/gating.ts
Role gates, server-set flags, and the streamlined cohort preset. Hides rather than deletes, redirects deep links, reversible per account from the admin console. Reduction needs no code deleted — only the manifest widened.

So the honest scope is much smaller than “rethink the app”. Promote work that exists, widen a flag that exists, and rename one nav item. No rewrite, nothing deleted, every step reversible.

5 · 25 → 6, in the order it should ship

Each phase stands alone and is independently revertible. Phase 1 is a word.

#MoveEffect · risk
1 Rename Transfers → Relays SHIPPED Ends the nav-vs-content contradiction. One string. Zero risk, ship today, no decision required.
2 Widen streamlined IN REVIEW Hide the projection duplicates for new accounts — Series, Sessions, Stream, Catalog, Trash, Graph reachable by facet and deep link, absent from the rail. 25 → ~10 for that cohort. Reversible per account; existing users untouched until you say so.
3 Promote the Objects table The prototype becomes the one corpus screen; the ten projections become facets on it. This is the real work, and it is porting rather than inventing.
4 Collapse Account behind the avatar Profile, Settings, Organizations, Team, Network, Contract, Requests leave the rail for a menu. Nine doors → one. Low risk — none of these are daily surfaces.
5 Re-measure, then decide what dies After 1–4 the rail converges on the DEC-029 noun rail (decided 2026-08-30 — the two-rail study): Home · Inbox · Relays · Library · Streams · Sessions · Graph · Network · Apps + pinned Settings (revised same day: Library and Graph keep their own screens — a door for a different kind of thing or way of seeing; only Series and Trash nest as views). The verb-forward rail this row first named is Option B there, kept as record. Only then is there enough evidence to delete anything permanently.

What this deliberately does not do: delete code, remove capability, or touch the admin console. Everything above is navigation and gating. A surface that is hidden and reachable is recoverable in an afternoon; a surface that is deleted is a decision you cannot walk back once someone is depending on it.

6 · What is genuinely yours to call

How far does streamlined go? Phase 2 sets the aggression. Hiding six projections is defensible; hiding Graph may not be, since it is an active build under epic #475.
Does it apply to existing users? New accounts only is the safe read. Applying it to current users changes an app people already know — cheaper to reverse than to apologise for.
Is Relay the noun everywhere? Phase 1 assumes yes, since the product is called Relay. If “transfer” is meant to stay user-facing anywhere, that needs saying before the rename spreads.