ExoGP3Design IA + flows · rev 5 · 2026-07-29
Proposed architecture · derived from source, not invented

Information architecture
and the ten flows that matter

The app currently has nine nav items and sixteen routes, each one a table of a noun. This proposes five places and one action layer. The reason it can collapse that far is not taste — it is that the API cannot write at all, so every change settles through one of three paths, and two of those are shapes a conventional form cannot express.

01

The constraint that sets the shape

Three settlement paths, read from the source

Most IA proposals argue from preference. This one starts from the write surface that already exists — the GraphQL API, the pilot's tool definitions, and the eight deployed contracts. What the product can and cannot save is a fact, and it constrains the design more than any opinion does.

The API is read-only. src/graphql/builder.ts:63 has no builder.mutationType — zero mutations. Nothing a player does is ever saved by the API, so every write settles one of the three ways below and no screen can assume otherwise.

Two of the three are unusual enough to shape the whole interface

Path A · talkno chain
You tell the pilot how to fly, and only the pilot can write it down. update_race_orders validates, clamps and persists server-side — strategy, aggression, risk, line, overtaking, corner risk, boost discipline, exit boost, boost braking. There is no endpoint that edits orders directly, so this is the one function in the product that is unreachable except by conversation.
costs compute · no signature · immediate
Path B · signwallet only
The player's wallet writes straight to a contract. Most actions live here: equip, repair*, recycle*, buyPack, buyAndOpen, enterRace, clone, setCloneFee, claimPrize, buyCredits. A form can do this perfectly well — LoadoutStudio.tsx already does, with a Save on-chain button that commits all five slots in one atomic LoadoutVault.equip.
gas + fees · 1 signature
Path C · co-signserver + player
Neither side can act alone. Fabricator.fabricate is player-called and payable, but it verifies an orchestrator EIP-712 signature over the exact (player, parentA, parentB, child, materialTier, materialAmount, nonce, deadline). The server decides what the child will be and signs it; the player pays and submits. A form alone cannot start this — the authorisation has to be issued first.
fee + scrap · 2 signatures
And chat is metered, which limits how much of the interface it may own. src/services/llm/pilotChat.ts:634 — if (balance < cost) return { ok: false, error: "insufficient_credits" }. At zero compute the pilot cannot answer, so chat can never be the only route to anything essential — and above all not to the thing that restores it. A chat-only storefront cannot sell you compute: you would need compute to ask for it. The rule this forces: compute buys advice, never access. Spending money, collecting money and restoring compute all need a route that costs nothing to reach — which is settled by selling compute in the Shop, as its own SKUs and bundled into packs. The storefront is then the recovery route, and it is the one place that must work at a zero balance.

Path A is why a settings panel for orders cannot work: there is nothing to submit it to. Path C is why fabrication cannot be a pure client form: the outcome is authorised off-chain before it can be paid for.

Path B, though, is ordinary — and that is the correction this document needed. Chat is not the only way to write, and it should not be. It earns its place where a decision wants advice, where the server must co-sign, or where orders are involved. Where a player already knows exactly which two pieces to swap, direct manipulation is better, and the existing loadout editor is evidence that it works.

What follows from it One settlement path per action, reachable more than one way. A gear-swap dialog and a conversation should both produce the same typed loadout proposal and the same single equip call — never two code paths that can disagree about what is equipped.
02

Proposed architecture

Five places · one action layer

Read this top to bottom as one causal chain: an open surface anyone can see without a wallet, five places you can stand, a chat layer that lives inside every place rather than beside them, what that chat can emit, and where it settles.

Chat is drawn as a bar and not as a box because it is not a sixth destination — it is the verb layer, present wherever a pilot is.

place — a URL you can stand at and share
chat — costs compute, no signature
proposal — you sign it
chain / read path
readable with no wallet
Tier 0open surface
The live broadcastOn Air · no wallet
Any pilot's pageshareable dossier
Any settled resultsigned, verifiable
Records & laddersthe audit surface
a spectator becomes an owner here — one CTA, no nav item
Tier 1places · 7
On Airthe live race
The Cardnext races · eligibility
Pilotsroster · each dossier
Bloodlinelineage, cloning, studs
Inventorywallet-scoped · no pilot needed
Shoppacks · entries · compute · works at zero
Recordsresults · ladders · proof
every place that shows a pilot also contains
Tier 2action layer
Talk to your pilot the same component everywhere — the tail of a detail screen, never a destination 20-turn memory · 1 compute per turn
emits exactly two kinds of thing
Tier 3adirect effect
Standing race ordersupdate_race_orders · persisted · free of signature
Tier 3bproposals · 8
Race entryrace_entry
Loadoutloadout · 5 slots
Gear packpack · buy_and_open | open_owned
Repairrepair · mechanic discount
Recyclerecycle · scrap yield
Cloneclone · generation + 1
Stud listingstud_listing · list | unlist
Fabricatefabricate · two parents + foreman
the player signs · the chat itself never transacts
Tier 4settlement
MkIVExomintPublic · clone · setCloneFee · withdrawCloneEarnings
ExoGearrepair* · recycle* · burn
LoadoutVaultequip · unequip · unequipAll
RaceVaultenterRace · enterRaceWithCredit · claimPrize · claimRefund
GearStorebuyPack · buyAndOpen · openPack
Fabricatorfabricate — needs an orchestrator signature
Materialsscrap · burned by fabrication
CreditTopUpbuyCredits
read back through
Read pathone direction
Chain → indexer → Postgres → GraphQL → portal read-only · no mutations · every number on screen traces to a signed source
03

Where the current routes go

One test, applied to every route

Nothing is deleted — every capability survives. What changes is that a capability stops being a place you navigate to and becomes a thing you ask for.

The test applied to each row: does standing here, looking at a list, have value on its own? If the only reason to visit is to perform one action, it is a proposal, not a route.

9 → 7nav items
16routes reviewed
0capabilities removed
Route todayNav labelWhere it goes, and whyVerdict
/HomeBecomes On Air. A dashboard of links has no value when the live race is the product's best advertisement for itself.becomes On Air
/races
/races/:raceId
Race LobbyThe Card. Genuinely a place — you compare fields, venues and eligibility before committing money.keep
/garage
/garage/:pilotId
HangarPilots. Also genuinely a place — the dossier is reference material you read.keep, rename
/garage/:pilotId/loadout—Keep it, and back it with chat. It works — Save on-chain commits all five slots in one atomic LoadoutVault.equip. Direct manipulation is the better tool when you know which two pieces to swap; chat is better for "which of these is actually an upgrade". Both should emit the same loadout proposal so there is one settlement path.keep + chat
/gear/:tokenId—Stays as a deep-linkable page — a gear piece is a tradeable asset and needs a URL — but is reached as a dialog from a pilot.keep as detail
/inventoryInventoryKeep — it is wallet-scoped, not pilot-scoped. Unequipped gear, unopened packs, scrap, entry credits and compute all belong to the wallet (useScrapBalances, useEntryCredits and useComputeCredits all key on the account address). There is frequently no pilot to fold them into, so folding would leave them homeless.keep
/shopShopKeep — this one is load-bearing. Chat is gated on compute, so a chat-only shop cannot sell you compute; you would need compute to ask. It is also where revenue lives, and revenue must never depend on a metered feature. It sells compute directly — as its own SKUs and bundled into packs — so the storefront is also the recovery route. The pilot still advises which pack via a pack proposal, but the Shop stands alone and works at a zero balance. BuyCreditsModal.tsx is already this, narrowly.
Build cost: SKU tiers are free — CreditTopUp takes any amount and the backend converts at a configured rate, so pricing changes without a redeploy. Bundles need a backend rule, not a contract change: PackType has no compute field.
keep
/cloning
/studs → /cloning
CloningBloodline. The lineage itself is worth looking at; the two actions on it (clone, stud_listing) become proposals.keep, rename
/mintMintNot a nav item — a CTA on On Air. Nobody navigates to "Mint"; they see a race and want in. It stays a URL for campaign links.fold to CTA
/history
/leaderboards
History
Leaderboards
Merge into Records. Both answer "what has happened and where do I stand" — splitting them means neither answers it fully.merge
/studio—An asset/render tool. Real value, but for us, not players. Keep it out of the player IA and un-navved.internal
/admin—Operator surface.internal
Result: On Air · The Card · Pilots · Inventory · Shop · Bloodline · Records — seven, down from nine, and each one earns its place: five are phases of the loop (watch, choose, prepare, continue the line, verify) and two hold what the wallet owns rather than what a pilot owns. Inventory and Shop cannot be folded into chat — see §1 on metering. If Bloodline becomes a tab of Pilots (open question 1) this is six.
04

The ten highest-value flows

Ranked by what breaks if they are bad

Ranked by consequence of failure, not frequency. Flow 1 is first because nothing else can happen until it works; flow 2 is second because it is the only one players repeat, so it is the only one whose quality compounds.

Each step carries the layer it happens in and what it costs — a step that costs a signature is a step a player can refuse, and every one of those is a place the flow can die. Each flow ends in an explicit "dies if".

Place — a URL you can stand at
Watch — the broadcast, no wallet
Chat — costs compute, no signature
Sign — the player's wallet
Chain — settled, then readable
01Cold start — spectator to owneracquisition
Nothing else can happen until this works. The live broadcast is the product's own best advertisement, and it is watchable with no wallet, no account and no install. This is the only flow that creates a player, and its conversion rate multiplies every other flow on this list.
Open surfaceLands on On Air, race already running. No wallet prompt.free · no account
Open surfaceFollows one pilot through the field. Reads its dossier — a real page, shareable.free
PlaceSees the result settle, signed and checkable. The game did not just assert an outcome.free
SignConnects and mints a pilot from the CTA on the broadcast — not from a nav item called Mint.mint price · 1 signature
ChatFirst thing the new pilot does is speak, and propose its own first race.1 compute
Dies ifa wallet is demanded before anything is watchable, or the first screen is a dashboard of empty stats instead of a race in progress.
02The loop — race, debrief, adjust, re-enterretention
The only flow players repeat, so it is the only one whose quality compounds. Its job is to make the last race feel like it taught you something. The debrief is where a result stops being a dice roll and becomes evidence — and it is the moment the pilot earns the compute you spend on it.
WatchWatches its own race on On Air, knowing its orders.free
PlaceResult: placing, and the five things it moved — merit, wear, series points, prize, crate.free
ChatDebrief in place. The pilot names what cost the position and proposes one change.1 compute per turn
ChatOwner accepts or argues. Orders change on agreement — no form, no save button.1 compute · no signature
SignRe-enters, carrying the new orders.entry fee · 1 signature
Dies ifthe result screen shows a placing and nothing else, so the player cannot tell whether their coaching did anything — the loop then reads as a slot machine.
03First coaching changeactivation
The moment a player learns that talking is the control surface. A player who never does this has bought a lottery ticket; one who does has a pilot. It is also the cheapest possible first success — update_race_orders needs no wallet, so there is nothing to approve and nothing to lose.
PlaceOn the dossier, standing orders are readable prose, not a settings panel.free
Chat"You keep losing places on lap one." The pilot explains, in its own terms, why.1 compute
ChatIt proposes one specific change and says what it trades away.1 compute
ChatOwner agrees. Orders persist immediately, clamped server-side. Visibly changed on the dossier.no signature
PlaceNext result reports against that change, so the coaching is falsifiable.free
Dies iforders are presented as a form. The player then hunts for a save button that cannot exist, and the one function that is chat-only feels broken rather than deliberate.
04First paid entryfirst revenue
The first time the player is asked for money on a recurring basis. Banding runs off lifetime paid races, so this entry also silently sets the competitive ladder the player will live on — which means the screen has to be honest that the field gets harder, not just that the prize gets bigger.
PlaceOn The Card, eligibility shows as columns — what you qualify for and what bars you.free
ChatAsks the pilot which to enter. It proposes options with a stated reason per option.1 compute
SignReads entry fee, field size, podium cutoff and band consequence — then signs. Pays in ETH, or with a pre-bought entry credit.enterRace · or enterRaceWithCredit
ChainEntry held in RaceVault. Grid locks; orders and gear snapshot at lock.gas
Dies ifthe band consequence is invisible. A player who discovers after the fact that paid races moved them into a harder field will read it as a bait, and correctly.
05Gear up — pack, open, equipprimary spend
The main discretionary purchase, and the one with real randomness in it. Three separate costs hide in this flow — pack price, open fee, then a vault signature to equip — and a player who thought they had paid once will feel misled at the third. Naming all three up front is the whole design job.
PlaceThe Shop is browsable on its own — every pack, price, odds table and the compute each one includes, with no pilot and no compute needed.free
ChatOr ask: "what is holding you back?" The pilot names its weakest slot. Advice is the part compute pays for.1 compute
ChatProposes a pack: price, open fee, floor rarity, per-rarity odds, whether the slot is locked.1 compute
SignBuys and opens. Odds were stated before payment, not after.price + open fee · 1 signature
ChainVRF resolves. New gear appears on the pilot it was bought for.gas
SignPilot proposes the resulting five-slot loadout and what changes. Owner signs the vault.1 signature
Dies ifodds appear only after opening, or the equip signature is a surprise — "I already bought it, why am I signing again?"
06Repair before the grid locksprotects spend
The silent loss. Entering on worn gear wastes a fee the player already paid, and nothing in the current UI stops them. This flow exists to make wear impossible to miss at the one moment it is actionable — before lock. The mechanic discount also gives the pilot's craftsmanship a visible, cash reason to matter.
PlaceWear is on the gear row in the dossier, not behind a tab.free
ChatPilot raises it unprompted when an entry is pending. It is the party with the information.1 compute
ChatRepair proposal: per-item costs, the batch total, and the mechanic discount with who earned it.1 compute
SignOne signature for the batch, not one per item.repair cost · 1 signature
SignThen the entry — in that order, and the UI should enforce the order.entry fee · 1 signature
Dies ifwear is only visible on a gear detail page nobody opens. The player pays an entry, underperforms, and never learns why.
07Claim what you are owedtrust
The flow where players decide whether the game is honest. Winnings sit in the vault until claimed, so an unclaimed prize is indistinguishable from a prize that was never paid. Every owed thing must be visible, individually claimable, and individually priced — a summed "2 signatures" across two independent claims is a layout bug, not a saving.
PlaceResult names every consequence: prize, crate, merit, series points, wear.free
SignPrize — amount, why it is owed, that the vault holds it, and the one signature to take it.gas · 1 signature
SignCrate — separately, with its own reason and its own cost. Opens free of VRF fee.gas · 1 signature
SignTwo more the UI forgets. An abandoned race leaves a claimRefund; being cloned as a stud accrues an 80% owner share that needs withdrawCloneEarnings.gas · 1 signature each
PlaceMerit and points update in Records, traceable to this race.free
Dies ifowed value is aggregated into one badge somewhere else — or worse, never surfaced at all. Every payout here is pull-payment, so an unclaimed balance is indistinguishable from one that was never paid, and players do not go looking for money they were not told about.
08Keep the pilot talking — top up computegates everything
Compute meters the entire action layer. If it runs out, five of the other nine flows stop working, and they stop working at the layer the player was taught to rely on. This is the one flow whose failure looks like the product being broken rather than a limit being reached — which makes how it is worded more important than where it lives.
ChatRemaining compute is stated at the composer, next to the thing that spends it.free to read
ChatOn exhaustion the pilot does not go silent — it says it cannot answer and why.—
PlaceThe Shop, which needs no compute to reach. Not a dialog inside the conversation — at zero balance there is no conversation to be inside.free to reach
SignBuys a compute SKU, or a pack that includes compute. Same aisle as everything else you buy — topping up is not a special repair flow.ETH · 1 signature
ChatBack to the conversation, with the unanswered question still waiting rather than discarded.1 compute
ChainCreditTopUp credits the balance; the pending question is answered, not discarded.gas
Dies ifexhaustion reads as an error or a hang, or the unanswered question is lost — the player then distrusts the chat layer permanently, and it is the whole interface.
09Continue the line — clonelong retention + sink
The flow that gives a veteran a reason to still be here. It converts an ageing pilot's history into a next generation, and it is a genuine currency sink. It is also the emotional pivot of the product — the player is deciding to succeed the pilot they have been coaching, so the screen should treat that as a decision with weight, not a purchase.
PlaceBloodline shows the line: generations, cooldowns, what each ancestor achieved.free
ChatOwner asks about succession. The pilot answers about its own replacement.1 compute
ChatClone proposal: fee, child generation, cooldown, whether gen-0 is closed.1 compute
SignSigns. The child is minted with lineage recorded on chain.clone fee · 1 signature
ChatThe child speaks with no history — and that contrast is the reward for the parent's.1 compute
Dies ifcloning is presented as a purchase in a Cloning tab. The parent's record is the entire value being carried forward and must be on screen at the moment of signing.
10Make and unmake — fabricate, recycle, studplayer economy
The three flows that let players supply each other instead of only the store. Grouped because they share one shape: two inputs and a stated probability, or one input and a stated yield. All three hinge on the pilot's own craftsmanship changing the numbers, which is the clearest case in the product for why the proposal must show its odds before you sign.
ChatFabricate: two same-archetype parents plus a foreman. Odds shown — breakthrough, rarity upgrade, failure.1 compute
Co-signThe server signs the exact child it authorised; you pay and submit. Both parents take wear and scrap is burned — fabrication net-consumes materials by design.fee + scrap · 1 signature
SignRecycle: scrap yield stated per piece before signing, with salvage shown separately.gas · 1 signature
SignStud listing: setCloneFee against the cloneMinFee floor. Income then accrues and must be withdrawn.gas · 1 signature
PlaceAll three land back on the pilot that did the work — never in a detached bag of items.free
Dies iffailure odds are disclosed after the signature. Fabrication is the one action a form cannot start on its own — the outcome is authorised before it is paid for — so the card that shows the odds is the product here. One irreversible loss on undisclosed odds ends a player's participation in the crafting economy.
05

Open questions this raises

Decide before building
Is Bloodline a place, or a tab of Pilots? It only earns nav weight once a player owns a second-generation pilot. For a new owner it is an empty room, and an empty nav item teaches the wrong thing about the product's size.
RecommendShip it as a tab on Pilots. Promote it to top-level nav only when the account has more than one generation. Nav that grows with the player.
How does bundled compute stay auditable? A direct purchase emits CreditsPurchased(buyer, weiPaid) — an on-chain receipt the indexer mirrors. Compute bundled into a pack has no such event, because PackType carries no compute field, so it would arrive by a backend rule keyed on the pack purchase. That is the one number on a receipt that would not trace to a signed source, which cuts against the product's own claim.
RecommendState the included compute on the pack card before purchase, and show it as a separate line on the receipt attributed to the pack's tx hash. If bundles become a significant share of sales, give PackType a compute field so the grant is provable rather than asserted.
Where does the roster live when a player owns twenty pilots? Every flow here is written for one pilot and its chat. A twenty-pilot owner needs to know which of them needs attention, and that is a genuinely different screen — closer to a queue than a gallery.
RecommendA "needs you" queue on Pilots, ordered by what is actionable: unclaimed prize, worn gear before lock, entry open, cooldown expired.
Which actions deserve a direct form as well as chat? Settled for loadouts: both. The editor already works on chain, and chat is clumsy for "swap these two exact pieces" while being much better for "is this actually an upgrade". The open part is where else that applies — repair batches and recycling are the likely candidates, since both are bulk operations over things you can see.
RecommendDirect forms wherever the player can already see the exact objects and the choice is mechanical; chat wherever the answer needs judgement or the server must co-sign. Both emit the same typed proposal — one settlement path, two ways in.
What does a spectator see on a pilot page they do not own? Tier 0 claims pilot pages are shareable, which is how acquisition works — but the chat is the best part and it is owner-only. A page whose main feature is disabled converts badly.
RecommendShow the transcript read-only where the owner has made it public. Watching someone coach a pilot is the most persuasive thing on the site.
Is the five-item nav still right on mobile? Untested — every prototype in this set assumes a wide viewport, and the chat-plus-detail split does not survive a phone. Flow 1 is the one most likely to arrive on a phone, from a shared link.
RecommendDesign flow 1 for mobile first and separately. Watching and minting must work on a phone; coaching can stay wide.