Inspiration

Every planning assistant I tried could reason, but none of them actually knew what I like. Ask for a Friday night and you get the same generic list everyone gets: a popular movie, a popular restaurant, a popular playlist — three good items that have nothing to do with each other, or with you.

A good evening isn't three good items. It's one coherent night: the film, the food, and the music all pulling in the same direction. And the only way to get that right is to know someone's taste — not as a vibe the model guesses, but as real data. That was the bet behind Cozy Night Planner: one prompt in, one whole evening out, where every pick is grounded in a taste graph instead of invented by a language model.

What it does

Type something like "Plan my Friday night, something cozy, under $60 CAD" and you get a movie, a Toronto dinner spot, and a playlist, each with a one-line reason tied to what you've liked before. Thumbs-down any pick and Re-plan replaces only that pick — the rest of the evening stays put.

It goes further than the first plan. You can build a taste profile from your own favourites with Qloo-backed autocomplete, or snap a photo of a bookshelf, record sleeves, or a meal and have it matched to real entities. Date night handles two different tastes at once: every candidate is scored for each person, and the planner keeps what rates highly for both. A Toronto heatmap shows where your taste concentrates across the city, and the dinner pick leans toward that hotspot. A grounding page measures the whole idea honestly: the same prompts run through Nemotron alone versus through the app, with every suggestion checked against Qloo.

How I built it

The frontend is React + Vite on Vercel; the API is Express on Render, holding both keys server-side. Every model call goes to Nebius Token Factory, and every pick comes from Qloo — the model never invents a title, place, or artist.

The pipeline for one plan looks like this:

  1. Mood agent. A Nemotron model reads the prompt and, through tool calls, searches Qloo's tag graph — so "rainy Sunday date night, romantic" steers each category with real tags like Rainy Day Music and Romantic Dinners.
  2. Candidates from Qloo. Insights requests fetch movies, Toronto places, and artists seeded by the profile's likes, with dislikes excluded. On date night, each candidate is scored for both people and ranked by the weaker score, so one person's enthusiasm can't overrule the other's dislike:

$$\text{score}(c) = \min\left(a_{\text{you}}(c),\, a_{\text{partner}}(c)\right)$$

  1. Budget filter before the model sees anything. Qloo's price level maps to an estimated CAD meal cost, and unpriced places are never picked:

$$\text{est. cost}(p) = \begin{cases} \$15 & p = 1 \ \$30 & p = 2 \ \$50 & p = 3 \ \$90 & p = 4 \end{cases}$$

  1. Selection with validation. Nemotron picks only from the candidate IDs it was given, under a strict JSON schema. The server checks every returned ID against the candidate set, retries once on failure, and rejects anything else — a category with no valid pick becomes a retry state, never a hallucinated fallback.
  2. Memory. After a few thumbs, Nemotron writes short notes about what you lean toward, each required to cite at least two of your actual thumbs. Taste, thumbs, and memory live in your browser only — no login, no database.

Each step runs on the Nemotron model that measured best for it on the app's real requests (benchmark in devpost/model-benchmark.md): Lightning for the mood agent's tool calls, Ultra for picks, Super VL for reading photos, Ultra again for background memory, Lightning as fallback. The plan streams its steps live, so you can watch the agent work instead of staring at a spinner.

What I learned

The biggest lesson is that grounding beats cleverness. The grounding scoreboard made it measurable: asked on its own, Nemotron repeated the person's own favourites in 24 of 32 movie/artist suggestions and named 7 of 24 restaurants that weren't in Toronto or were closed. With Qloo candidates and ID validation, both numbers dropped to zero, and the average taste match actually went up. The model didn't get smarter — the system around it got honest.

The second lesson is that model routing is a real engineering decision, not a config detail. Reasoning on helped the background memory task and the vision task, but on live picks it burned the whole token budget thinking and returned nothing, and on Ultra it once dropped an instruction entirely. Benchmarking each step on real requests — latency, valid JSON, valid IDs — was what made the routing defensible instead of vibes-based.

The third is that taste is cross-domain in a way a single-category recommender never shows. Qloo's compare analysis surfaced shared themes between two people that neither person's list stated outright, and the heatmap showed taste has geography. Those two features changed how I think about the product: it's not three recommenders in a trench coat, it's one taste, expressed three ways.

Challenges I faced

The Qloo hackathon key rate-limited parallel tag lookups, so lookups now run sequentially with backoff on HTTP 429. Toronto results skewed hard toward cafés at price level 1, so the selection prompt now explicitly prefers dinner-appropriate places among the candidates. Plain JSON mode looped on itself and reasoning-on returned nothing on live calls, which is how the strict-schema, thinking-off-for-live-steps setup came about — and why every reason must cite a liked item from its own category, after early replies cited the pick itself as something the user liked.

Date night was the hardest product problem: intersecting two people's top-15 lists overlapped too little and leaned toward one person, which forced the per-candidate dual-affinity scoring above. A "trending this month" feature got cut entirely when the trending endpoints returned empty lists and 404s — there was no real data to show, so I showed nothing instead of faking it. And the boring-but-real deployment lesson: Render's free tier sleeps after 15 idle minutes, so the demo needs a /health warm-up before anyone judges it.

What's next

The obvious next step is taste memory that survives across devices instead of living in one browser, and a "same vibe, but cheaper" remix of past evenings. The core, though, is already the point: an evening planned by what you actually love, with receipts — every pick traceable to the taste graph that produced it.

Built With

Share this project:

Updates

Submission history