- Go 36.1%
- Svelte 28.4%
- Python 16.2%
- TypeScript 10%
- CSS 4.5%
- Other 4.8%
| agents | ||
| consensus | ||
| deploy | ||
| nix | ||
| web | ||
| .env.example | ||
| .gitignore | ||
| docker-compose.yml | ||
| EXECUTIVE_SUMMARY.md | ||
| flake.lock | ||
| flake.nix | ||
| GOALS.md | ||
| justfile | ||
| README.md | ||
Left On Bread
Don't leave the cart on bread.
DubHacks · Visa track · Reimagine Shopping
Shared-cart commerce for households: private preference vaults, agent-assisted voting, loaf-gated checkout, and an HMAC crust seal on the decision receipt.
Live: leftonbread.club
Problem
Households already shop together, but the “cart” lives in Slack, iMessage, or one person’s Instacart.
- Budgets and hard-nos stay unspoken until checkout
- Someone vetoes late; the cart dies
- Merchants lose the basket; roommates lose the evening
Classic left-on-bread energy: the group chat went quiet, and so did the checkout.
Solution
A grocery-shaped shared cart that settles like a household decision.
| Pillar | What it does |
|---|---|
| Shared shelf + cart | Everyone sees the same catalog and line items in real time |
| Private vaults | Budgets, hard-nos, likes, and agent prompts never hit the shared wire |
| Loaf-gated checkout | Majority under $50; unanimous at/above $50 (or checkout) |
| Ask my agent | Hard rules always bind; optional Gemini soft-ballots from a private prompt |
| Deadlock → recover | Split votes surface as deadlock; mediate instead of abandoning |
| Crust seal | HMAC over the vote receipt for audit / merchant metrics (not card auth) |
Visa-adjacent story: a sealed household decision receipt that could inspire future group authorization, without pretending this build charges cards.
How voting works
Same order in the Go server and the Python kitchen brigade:
- Hard vault rules: hard-no tags + max-item always veto (LLM cannot override)
- Private agent prompt + Gemini (optional): soft approve / veto / abstain
- Tag prefs fallback: likes match → approve; otherwise abstain (no rubber-stamp)
Project structure
leftonbread/
├── web/ SvelteKit + DaisyUI + Tailwind
│ └── src/routes/ UI surfaces (see below)
├── consensus/ Go API: rooms, propose/vote/settle, vaults, WS, seals
│ ├── cmd/server/ HTTP + WebSocket entrypoint
│ └── internal/ protocol, store, LLM soft-ballots
├── agents/ Python kitchen brigade (Maya / Jordan / Sam)
├── deploy/ Weekend Docker image (UI + API in one process)
├── docker-compose.yml Homelab / live demo stack → :3040
├── justfile setup, dev, demo, deploy recipes
└── GOALS.md Longer product / hackathon notes
Product surfaces
| Route | Purpose |
|---|---|
/ |
Create or join a household; featured shelf |
/r/[code] |
Live cart, private vault, propose, vote, checkout |
/product/[id] |
Product landing (price, specs, confirm pick) |
/demo |
Scripted kitchen: three roommates → deadlock → seal |
/merchant |
Sealed volume, recovered carts, local metrics |
Tech stack
| Layer | Choice |
|---|---|
| Frontend | SvelteKit 5, DaisyUI, Tailwind 4 |
| Consensus API | Go 1.22, Gorilla WebSocket |
| Agents | Python 3.11+, httpx (optional Gemini / xAI / OpenAI) |
| Deploy | Multi-stage Docker (deploy/Dockerfile.weekend) |
| Tooling | just, Bun (web), uv (agents) |
Quick start (laptop)
just setup
just dev # API :8080 + UI :5173
# open http://127.0.0.1:5173/demo
Optional soft ballots (copy .env.example → .env):
GEMINI_API_KEY=...
LEFTONBREAD_LLM_MODEL=gemini-3.1-flash-lite
just gemini-smoke # one-call check
just agents-llm # CLI kitchen with LLM ballots
Without a key, hard rules + abstain-default still run the full demo.
Homelab / live host
git pull
just weekend-up # http://127.0.0.1:3040 → leftonbread.club
just weekend-down
just agents-weekend is optional CLI automation against :3040. The /demo UI already runs negotiate server-side.
Judge demo script (~3 minutes)
/demo→ Run the kitchen: Maya, Jordan & Sam negotiate; vaults stay private- Deadlock: blender fight; mediate to recover the cart
- Checkout & crust seal: HMAC receipt (integrity bind, not a card charge)
/merchant: sealed volume + recovered checkout metrics- (Optional)
/: create a household, share/r/CODE, set a private vault, Ask my agent
What we are honest about
- Not a payment processor; the crust seal is a demo integrity HMAC
- Soft ballots are one-shot, not multi-turn negotiators
- Catalog is a mock Homestead Market shelf
- Agents work without an LLM key via rules alone
Why this fits Reimagine Shopping
- Reimagine group shopping as consensus, not one person holding the card
- Merchant value: fewer abandoned group carts after preference fights
- Household value: preferences stay private until the loaf is proofed
Judging rubric: why we earn full marks
Innovation (25%)
Group shopping today is not a product. It is a group chat with a credit card at the end. We reimagine the settlement of shopping, not just the shelf:
- New primitive: loaf-gated checkout (majority / unanimous rules) so the cart is a household decision, not a hostage of whoever holds the phone
- Right ingredients: shared grocery UX + private preference vaults + agent ballots + recoverable deadlock + a merchant-visible crust seal
- Visa-shaped twist: a sealed decision receipt that points at future household authorization without faking an acquirer charge
- Memorable framing: “left on bread” names the real failure mode (carts abandoned after silence) and makes the demo stick
User Experience (25%)
Built to survive a noisy judging floor:
- Grocery-native UI: Instacart-shaped shelf, product pages, shared cart, merchant console in one visual system
- Zero-friction rooms: display name → create/join by code; no email wall before the aha moment
- Live under pressure: WebSocket ticket rail shows votes as they land;
/demoruns the full kitchen in three clicks - Private by default in the UI: vaults show “sealed,” never leak budgets onto the shared cart
- Deadlock is a feature: clear mediate path instead of a frozen spinner and a dead basket
- Ship polish: motion on the landing page, cohesive brand, production host at leftonbread.club
Technical Execution (20%)
AI is wired into a real consensus loop, not a chatbot bolted on:
- Hard → soft → fallback: hard-nos and max-item always veto; Gemini soft-ballots only when a private prompt is set; tag prefs abstain instead of rubber-stamping
- Same policy twice: Go server (
Ask my agent) and Python kitchen brigade share the vote order (no “demo lies”) - Real-time stack: Go consensus API + WebSockets; SvelteKit UI; optional Gemini / xAI / OpenAI via env
- End-to-end deploy: multi-stage Docker image (static UI + API + WS), live on a public domain
- Works offline of the model: full demo path without an API key proves the system is not vaporware when the LLM blips
Commerce Impact (15%)
We attack the abandoned group cart, a silent merchant killer:
- Recovered checkouts: deadlock → mediate → settle is measured on
/merchantas carts pulled back from the crumb tray - Sealed volume: decision seals give merchants an audit trail of household intent (engagement that actually finishes)
- Faster group conversion: vote in-product instead of negotiating in iMessage until someone gives up
- Loyalty-shaped habit: private vaults make shared shopping feel safe enough to repeat weekly
- Clear merchant story: fewer left-on-bread baskets, more settled households, metrics on a console judges can open
Trust & Responsibility (15%)
We designed for privacy and honest AI, not “agents spend your money”:
- Vault privacy: budgets, hard-nos, and agent prompts never appear on the shared cart / WebSocket wire; peers only see that a vault is sealed
- Transparency: crust seal is explicitly an HMAC integrity bind, not Visa/acquirer authorization; UI copy says so
- Hard limits over the model: LLM cannot override hard-nos or max-item caps
- No rubber-stamp AI: unsure / no-key paths abstain instead of auto-approving spend
- Responsible scope: one-shot soft ballots, mock catalog, no pretend card network; judges see what is real and what is story