“Rooftop over the whole valley, ten minutes from the mercado. Worth the walk uphill.” — Marco
Everyone plans. Everyone's aboard.
Marco invited you
Oaxaca
No install needed. You can vote from here.
60 seconds
What's your speed?
Oaxaca · Nov 14–18
The Board
Big decision · binds the split
Where are we staying?
“Cheaper, plainer, right on the zócalo. Everything is a two-minute walk.” — Ana
Pass takes you off this row's roster — and off its split.
5 of 5 responded · 4 in, 1 conceded
Why this one?
Rooftop over the whole valley, ten minutes from the mercado. Worth the walk uphill.
Required · big decisionsProposing is visible to everyone and can't be undone. Your Stash stays private.
This view is the Live Activity and the shareable poster.
Near Casa Zúñiga
Search
Stay is decided — results are filtered to a 15-minute walk.
No custody · ever
Ledger
Funding forward
Casa ZúñigaSettling backward
The Pass
The app takes a line on the board like anyone else, paid through the same rails.
Grounded in this trip
Chat
Group trip app · iOS
Two shells, one graph
A trip is a decision graph, not a wizard. Solid nodes exist in this prototype. Shared screens are reached from more than one place. Dashed nodes are proposed and not built — they carry the deck's numbering.STAY ——— ———NoneSTAY ——— 3 IDEASNoneVOTING 3/5 · 24HFull nudge ladderIdentity system · 01
Junto
Operating rules
Day color applies at decided and never before. Heat colors belong only to undecided things.
The split-flap animation fires on → decided and nothing else. Play it on refresh and it stops meaning anything.
Jet is the Solari surface. The rest of the app stands on penny tile.
STAY ——— ——— is a more legible to-do than an illustration.
Nothing in the Stash touches the board until Propose. That act is deliberate, visible, and irreversible.
Product UI is system SF. Futura and the Spanish vocabulary stay on brand surfaces.
Type tokens
--display · Futura Bold, caps
JUNTO
--sans · SF / system
1 decision is waiting on you
--mono · SF Mono → VOTING 3/5 · 24H
Color tokens
#211C18#C8102E#EC2789#F2921E#F5EFE3Exact — do not drift. Chili is primary actions and the fin. Sol is the VOTING state and every freshness stamp. Rosa is rings and the low end of heat.
Day codes & heat
FridayRuta RosaSaturdaySol NaranjaSundayDay-chili #F0506ATwo color systems that must never mix. Day codes are wayfinding for things that exist. Heat is temperature for things that don't yet.
Spacing tokens
--space-14px--space-28px--space-416px--space-624px--space-1248pxShape tokens
--radius-flap0px--radius-tile6px--radius-card18px--radius-round50%Flap cells are square. The Solari mechanism has no corner radius and neither does its rendering.
Icon tokens
18px · 1.75 stroke Feather only. An icon supports a label; it does not replace one.
Components
Voice
The group decided Casa Zúñiga without you. You're on the split at $180.
Not “Don't miss out!” and not “Sorry you missed this.” The consequence is the message. No guilt copy — the mechanic already carries the weight.Product model · the eight beats
One coherent path
A decision graph has no demo. The spine is the single path that touches every mechanic once, in the order a real trip hits them — the sequence we design against and test, without implying sequence in the data model. Each beat is grounded in a reference that already proves the pattern.If every member feels they can contribute to the plan, the trip belongs to everyone. The group never waits on agreement — only on you.
Contribution asymmetry. First-timers can't vote on options they don't know. Veterans propose; preferences weight the vote.
Price staleness. Live matching is hard — ship honesty. Every option carries a freshness stamp, re-checked when a vote opens.
The trip goes untracked. Ambient capture: receipts, bookings, and a chat grounded in the trip's whole history.
The join card lands in a thread that already exists. App Clip renders it. No install, no account.
The original iMessage bubble is rendered inside the join screen, code circled — continuity between the thread you were in and the app you're now in.
The accept sheet shows the actual trip contents before you commit. The invite reads as an ask, not an install prompt.
Makes you type 02VL-U83P. Junto never asks anyone to type a code — a keyboard means the link failed.
Fails when the invite is ignored — the modal outcome. The card must be complete in the thread, unopened.
Phone verify → Vibe Check → Passport reads travel history → role is inferred, not assigned.
“Do you promise to be active?” extracts a promise before the user has standing to promise from, and sets a chore framing on an app used three times a year.
⟨P⟩ Standing is shown, not stated. Vibe Check ends by naming what the answers bought: “You haven't been to Oaxaca. We'll carry the context on every vote.” Invisible role inference reads as the app deciding things about you.
Fails when Passport is empty — default to first-timer and lean on Vibe Check.
Land on PEEK with exactly one open decision. Vote. Then the install prompt — asking before contribution wastes the moat.
Four facts, one card: Asked by you · December hike! · No votes · Voting ends 21/11, 7.15 PM. Attribution, subject, participation, deadline.
“+ Add an option” sits inside the ballot. A voter becomes a proposer without leaving the vote — the cheapest path from consumption to contribution.
Full vote attribution, timestamped. ⟨P⟩ Junto splits it: in/pass are attributed because they change the split; concede is counted but not attributed. Naming conceders converts a lubricant back into a loss.
Fails when there's nothing to vote on. ⟨P⟩ An invite can't send from a trip with zero open decisions.
Private research → Propose → the Ideas layer. The only bridge between private and shared state, and the deck's most important missing screen.
The save sheet is the Propose sheet, essentially built: note field first and focused, then source URL, then who it's for, then which list. Maps one-to-one onto why / option object / decision / Ideas-vs-vote.
The note renders back on the row in quotes — not metadata behind a tap, but the row's subtitle. A why nobody reads is a why nobody wrote.
Save is a heart tap and a toast. Correct for Stash, wrong for Propose. The asymmetry between the two is the product.
⟨P⟩ The why is required on BIG decisions, optional on SMALL. Cost scales with stakes.
Fails when nobody proposes and the app is a prettier group chat. The in-ballot affordance is the mitigation.
Ambient reactions accrue on Ideas options. Free, no deadline, narrows without closing.
The library has polls (binding) and likes (meaningless). Nothing sits between them as a pre-vote signal layer. Vrbo comes closest and falls short: Like plus a comment box, with no mechanism to turn either into a decision.
⟨P⟩ Heat's job is to earn the vote, and that threshold must be visible. An Ideas row shows 3 IDEAS · TOP: CASA ZÚÑIGA, with one-tap open-a-vote for whoever holds permission.
Fails when heat accrues forever. Staleness surfaces to the organizer, not to everyone.
Deadline hits or everyone responds → the clatter → derived decisions unlock with NOW POSSIBLE.
Both keep resolved polls addressable, with the outcome inline. Junto gets this free: a decided board row is the ended poll. The board is the archive.
End poll — a manual kill next to Vote. An organizer who can end a vote early ends it the moment it's going their way, and “participation, not unanimity” becomes a slogan.
⟨P⟩ Result is a moment, not a destination. It fires the clatter, shows the unlock, returns to the board. A Done button would add a tap to the best moment in the app.
Fails when it ties. The organizer breaks it and the flap says so — a silent override is the trust-killer.
A big decision resolves and money binds. The Pass gates here — free through voting, charged when real money commits.
Per-member Paid/Unpaid with amounts, Mark paid sitting next to the unpaid member rather than in a menu, and Remind members who haven't paid yet as the footer. Self-attestation, shipped.
The best line in the whole pull, rendered as a button: “Why don't I have to pay everyone who paid for me?” → Explanation.
⟨P⟩ Simplify silently, but always offer the derivation. Simplification makes the math stop matching the receipts and users notice. One tap from any settle row to “why this number,” answered by the trip chat.
Fails on the Venmo round trip — no custody means no confirmation. Self-attest with social visibility; never a silent pending.
Settle up → the ledger freezes → poster exports → the trip lands in Passport and makes you been-before for the next one.
Settle-up as worked math in three numbered steps: how much → who paid most → who owes whom. It shows its work at the most fragile moment in the product.
“Is everyone finished adding expenses?” → Finish and calculate. An explicit close-the-books act with a plain-language check.
⟨P⟩ Settle up is a ritual, not a screen — the organizer proposes close, the group gets one “anything missing?” pass, then it freezes. Same consensus grammar, applied to money. ⟨P⟩ The poster is the trip's receipt and its distribution loop, shared back into the thread the summons came from. Beat 8 hands off to Beat 1.
Fails when the trip is abandoned mid-plan — the modal outcome. Archive gracefully, keep the Stash, generate no poster. A poster for a trip that never happened is a small cruelty.
Every group tool has polls or likes. Heat as a distinct narrowing, non-closing layer has no prior art. Junto's invention, and Junto's risk.
in / pass / concede exists nowhere. Pass changing the split is entirely novel and most needs testing.
Every save is one tap into a shared board or one tap into a private list. The Stash/Propose asymmetry has no precedent.
Polls live in poll archives; itineraries live in day lists. Collapsing them is the structural bet.
Receipts→rows, installments→stay. Nobody does it — carried from the Jul 2026 pull.
Revolut's Vault is closest and it's a bank account.