Inspiration

Every budgeting app tells you the same flat, guilt-trippy thing: "you spent $286 on food delivery this month." That number means nothing on its own — it's abstract, it's shame-flavored, and it doesn't change behavior. We kept asking each other: what if that same $286 was reframed as something you actually want? Not "you overspent," but "you're 71% of the way to a weekend in Banff."

That reframe is the whole idea behind Yonder: stop tracking spending as a scoreboard of regret, and start tracking it as proximity to a real, live, bookable trip. Once we had that hook, the rest of the hackathon became "how weird can we make this feel without breaking the trust of the numbers?" That's where the bigger idea landed: if Stay22 gives us live accommodation prices across four suppliers, that's not just hotel search — that's a market. Destinations become tickers. Suppliers become market makers. Price gaps between suppliers become arbitrage. Your cut spending becomes buying power. We built Yonder around that one-liner: hotel inventory as a stock market where your bad habits fund the deposits.

What it does

Yonder is an AI-powered savings app that turns everyday spending into live, bookable travel opportunity costs, wrapped in a small constellation of features that all share one backend brain:

Dashboard — a departure-board view of your active savings goals. Each row is a spending category mapped to a destination, showing the live cheapest nightly rate (pulled from Stay22), a price-history sparkline we build ourselves, a progress bar toward "funded," and an AI coach message grounded in your real numbers. Yonder Exchange — the "WTF moment." Every destination is a ticker (YBNF, YMTL, YPEC...). The four Stay22 suppliers (Booking.com, Vrbo, Expedia, Hotels.com) quote the same room like market makers, and when their prices diverge past 15% we surface it as a live arbitrage alert ("same room, cheaper on Vrbo"). A scrolling tape, day-range highs/lows, and a real order book per ticker complete the illusion — except none of it is fake, it's real Stay22 inventory. Market Map — the same live inventory pinned on a Leaflet map of any city, colored by price tercile, with an arbitrage-spread layer and filters for type, price, and rating. Concierge — a conversational trip-planning assistant. A Groq-hosted LLM chats naturally about itineraries, timing, and budget, and calls a search_stays tool to ground any hotel recommendation in real Stay22 data (never invented prices), backed by voice input/output and a custom BM25 retrieval engine for grounded RAG search. Nowcast — a "Hotel Demand Index" inspired by the Jane Street Costco-parking-lot proxy: since we can't see real occupancy, we infer heating/cooling demand signals from median price shifts, free-cancellation rate, and instant-book rate across snapshots, plus a naive forecast band and event case studies (like FIFA 2026 in Toronto). A shared Auth0 login, a green/carbon layer comparing your destination's footprint to a nearer alternative, and a brand-new landing page with a scroll-driven photo-ring animation that gates the whole app behind a light/dark themed sign-in. Every "BUY" and "Book now" button is a real Stay22 affiliate link — the fun framing is also the actual business model.

How we built it

Yonder is a four-service system with one locked contract layer so a four-person team could build in parallel without stepping on each other:

Frontend — React + Vite, Framer Motion for the landing page's scroll-hijacked card animation, Leaflet for the map, and a small currency/theme layer shared across every view. Backend (Node/Express) — the orchestrator and source of truth for every number. It owns the Stay22 client, a 10-minute cache (matching Stay22's own snapshot cadence), and — since Stay22 only returns a single point-in-time price — a hand-rolled price-history engine that seeds backdated points and appends a new one every fetch, so sparklines and the exchange's day range actually mean something. It also runs a background repricer that keeps every known destination's series moving even when nobody's actively polling. AI service (Python/FastAPI) — hosts a FreeSolo-trained SFT adapter for the coaching tone/timing layer, with a deterministic stub fallback so a flaky endpoint never breaks a demo. The backend hands it already-computed facts (recoverable spend, goal price, months-to-goal); the model narrates, it never calculates. Payment service (Chexy-aligned) — categorizes and reconciles synthetic transactions into a stable spend summary the backend consumes. Concierge LLM layer — Groq-hosted Llama with OpenAI-style tool calling, plus a from-scratch BM25 search index over the hotel corpus for the RAG fallback, so hotel answers are always grounded in indexed inventory rather than hallucinated. Every cross-service call has a graceful, contract-shaped fallback (mock Stay22 data, template coach messages, local persona generation) so any single service being down degrades the experience instead of crashing it — a deliberate decision given how easy it is for one teammate's service to be mid-deploy during judging.

Challenges we ran into

The biggest technical wall was that Stay22 is snapshot-only — it has no historical price API — but our entire "stock exchange" metaphor depends on price movement. We solved it by building our own time-series layer server-side: seed a plausible backdated walk on first fetch, append one point per fresh price, and keep a background job repricing every known destination on the same cadence as Stay22's cache, so the chart is always moving even between user-triggered fetches.

Coordinating four people across four services on a tight hackathon clock was its own challenge — we locked API contracts in CONTEXT.md up front (exact JSON shapes for /api/opportunity, /coach, /spend-summary) specifically so nobody blocked anybody else, and it mostly worked, but reconciling shapes when live Stay22 nested fields differently than our mocks (e.g. rating and capacity as objects instead of primitives) caused a few last-minute normalization passes.

We also had to keep the "fun" layer from undermining trust: an LLM that's allowed to riff about trip planning cannot be allowed to invent a hotel price. We enforced that with a hard rule (grounded tool calls only, backend does all arithmetic, the model narrates) and it held up, but it meant extra plumbing to make sure every AI-facing surface only ever received facts that were already computed.

Finally, because different features were prototyped by different people in parallel, the app ended up with two competing visual identities — a monospace "departure board" aesthetic on the dashboard and a completely different Inter/sans-serif landing page — and unifying that into one coherent, human-feeling design system (fonts, copy tone, animation style) was its own late-stage push.

Accomplishments that we're proud of

Turning a snapshot-only hotel search API into something that behaves like a real market data feed, complete with arbitrage detection, day ranges, and movers — without ever faking a number. Landing a genuinely novel product framing (hotel inventory as a securities exchange) that's fun enough to demo but never stops being financially honest. Shipping six distinct, fully working feature surfaces (Dashboard, Exchange, Map, Concierge, Nowcast, Suite Hearts) in one hackathon window, all sharing one backend and one set of live prices. A fine-tuned FreeSolo coaching model layered on top of deterministic math, with a stub fallback good enough that judges can't tell when the real model isn't reachable. Building resilience in from day one: every external dependency (Stay22, the LLM, the AI service, the payment service) has a real fallback path, so the demo degrades gracefully instead of breaking.

What we learned

We learned that a "backend computes, AI narrates" split is the right pattern for any product that mixes real money math with a language model — it let us get the personality and encouragement benefits of an LLM without ever risking a hallucinated price or a broken calculation. We also learned how much value locked API contracts create early in a multi-service hackathon project: the fifteen minutes spent agreeing on a JSON shape up front saved hours of integration debugging later. On the frontend side, we learned that building features fast and unifying design later is a real cost — keeping one shared design language (fonts, tone, motion) from the start would have saved a late scramble to make Yonder feel like one product instead of five stitched-together demos.

What's next for yonder

Real bank-linking through Chexy so recoverable spend is calculated from actual transactions instead of synthetic data. More goal types beyond travel — concerts, gadgets, debt payoff — using the same opportunity-cost engine. A production FreeSolo persona-chat model for Suite Hearts (currently stubbed) trained on our persona dataset. Price-drop alerts and a watchlist notification system so the "market" metaphor extends to push notifications, not just a live dashboard. Expanding the Market Map and Exchange beyond our current city catalog to any city Stay22 covers, plus deeper Deloitte-style sustainability comparisons (rail vs. flight, off-peak pricing) baked into every route. A native mobile app, since a "check your portfolio" habit loop is much stickier on a phone than a browser tab.

Built With

Share this project:

Updates