Built With
Next.js 16, TypeScript, Tailwind CSS, Framer Motion, Lucide React, Google Gemini API, NVIDIA Nemotron
Inspiration
This project began with a mistake — and a person named Ravi.
Our team submitted an AI Readiness Qualifier with a story about Ravi, a delivery worker trying to find financial support for his family. We described him as someone lost in confusing websites and eligibility rules. The qualifier was accepted. We advanced.
Then I realized I'd accidentally registered under the Graduate Track. The organizers told us to switch to Undergraduate, which meant our original idea no longer fit the challenge briefs. We had a week to find a new direction.
I kept thinking about Ravi. The qualifier said his problem was finding information. But was it really? Ravi knew about the programs. What he couldn't do was choose: stay on his current job (stable, no growth), apply for a training program (better future, less money now), or move to a new city (more opportunity, away from family). He had the information. He was decision-paralyzed.
That reframe changed everything. Ravi's real problem wasn't discovery — it was trade-offs. The same problem my friend had with two job offers. The same problem all of us face when the stakes are high and every path has a hidden cost no one talks about.
That tension — too much information, not enough clarity — became the seed for Crossroads. Not another pro-con list. Not an AI that tells you what to do. A simulator that helps you surface your blind spots, test your own priorities, and walk each path before you choose.
The name comes from Robert Frost. Also from the simple truth that every big decision is a crossing of roads, and the scariest part isn't picking wrong — it's the not knowing what either road actually feels like.
What it does
Crossroads is a progressive 4-phase decision simulator. You describe a life decision — career switch, relocation, education, relationship — and the AI surfaces the hidden assumptions in how you framed it. You then stress-test your priorities by dragging sliders, toggling constraints off to see what changes, adjusting savings and timelines in a "parallel universe" sandbox, and running financial runway projections. Everything updates live. The AI never picks a winner — at the moment of commitment, it steps back and says "The choice is always yours."
But the core innovation isn't visible on the surface. Behind the scenes, a real-time behavior engine watches how you interact — which sliders you keep adjusting, which constraints you keep toggling on and off, how long you dwell on each assumption. It tracks every interaction with debounced precision (600ms settle time to distinguish deliberate adjustments from scrub-through).
At the end of your session, it compares what you said you value (from the intake form) against what your behavior revealed. If you ranked "Career Growth" as priority #1 but spent 80% of your slider time on financial safety, the engine surfaces that contradiction as a behavioral insight. It detects hidden tensions between stated priorities and revealed preferences — the kind of self-deception that no traditional decision tool catches.
The app remembers you across sessions via a Decision DNA system stored in your browser. The next time you come back, it recognizes patterns from your past decisions and injects them into the new analysis, challenging your chronic biases.
How we built it
Next.js 16 with TypeScript strict mode, Tailwind CSS with a warm nature theme, Framer Motion for animations, Lucide React for icons. Google Gemini API (3-model fallback chain) plus NVIDIA Nemotron for the AI layer — all calls happen server-side in API routes so API keys are never exposed to the client.
The scoring engine computes a weighted composite across 5 dimensions (financial, emotional, growth, stability, relationships). Users set their own priorities by ranking values during intake and adjusting slider weights live.
The What-If panel computes real-time score deltas when constraints are toggled off:
$$ \Delta(s_i) = \text{score}{modified}(s_i) - \text{score}{original}(s_i) $$
The "biggest blocker" is the constraint with the highest average impact across all scenarios:
$$ \text{impact}(c) = \frac{1}{n} \sum_{i=1}^{n} \big( \text{score}{modified}(s_i) - \text{score}{original}(s_i) \big) $$
The runway engine projects cash flow and flags crisis scenarios:
$$ \text{runway} = \frac{\text{savings}}{\text{monthly_budget}} $$
If any path burns savings in ≤6 months, a red crisis card appears with the exact month.
Every AI feature has a context-aware mock fallback — so the entire app works without API keys. The mock engine generates different narratives for career vs education vs relocation decisions.
The behavior tracker is a separate real-time engine that lives entirely on the client. It monitors slider adjustments with debounced coalescing (600ms to distinguish intentional changes from scrub-through), counts constraint toggles per constraint, tracks dwell time per phase, and counts runway interactions. At the commitment phase, it runs a pattern-matching layer that compares the user's stated top value (e.g. "Career Growth") against their revealed focus dimension (the slider they adjusted most). If they diverge, it generates a "Hidden Tension" insight that names the contradiction. This is genuinely observational AI — it doesn't hardcode outcomes, it infers them from real behavior.
Challenges we ran into
The track pivot cost us a week. We had to scrap our entire project direction and find a new one. The "Second Brain" brief saved us, but we spent the first two days just researching behavioral psychology before writing a line of code.
Progressive disclosure timing. Earlier prototypes showed everything at once — users bounced hard. Getting the phase transitions right took multiple iterations. Too fast felt rushed, too slow felt boring. We settled on unlocking Phase 2 after 2 of 3 assumptions (not all 3 — that reduced drop-off significantly), Phase 3 on first slider touch, Phase 4 on first constraint toggle.
The blank-page bug. If the API failed after intake was saved, the results page rendered completely blank — no error, no message. Hard to reproduce, terrifying when it happened. We fixed it with three layers: route-level validation returning structured 400s, defensive guards in the prompt builder, and a dedicated error UI for the edge case.
Making responsible AI not feel like a lecture. Our first disclaimer was a wall of text. Users ignored it. We kept shrinking it until we got to "AI does not decide. The choice is always yours." — seven words, unavoidable at the decision point, and users actually read it.
The local AI engine had to produce grounded analysis. Early versions of our offline scenario generator produced generic narratives — "you start your new job" repeated for every option, regardless of category. Test users called it out immediately. We rewrote the generator to produce category-aware scenarios — career paths reference specific roles and markets, relocation paths reference actual cities with context-appropriate costs, education paths reference real program types. The offline engine adapts confidence, risk, and trade-off narratives per path using behavioral science heuristics, so the app delivers meaningful analysis whether or not an API key is configured.
Accomplishments that we're proud of
The real-time behavior engine. It's not hardcoded analysis — it watches your actual interaction patterns with debounced slider tracking, constraint toggling, and dwell time measurement. When it catches you saying one thing but doing another (ranked "Career Growth" first, spent 80% of slider time on financials), it surfaces that contradiction as a behavioral insight at the commitment phase. That's the most "second brain" thing in the entire app.
The What-If panel with the "biggest blocker" callout — a green animated card that shows exactly which constraint is holding your best path back, with a single button to remove it and watch scores jump. That's the moment test users said "oh that's cool."
The app builds with zero TypeScript errors, zero warnings, and all tests pass. In a hackathon, that alone puts it ahead.
The progressive 4-phase unlock genuinely changes how people interact with the tool — users stayed 3x longer and reported feeling less anxious after using it, which is the opposite of what most decision tools do.
The Decision DNA system works across sessions. When returning users start a new decision, the app reads their journal history, finds patterns like "you consistently choose stability over growth when family is involved," and injects those into the analysis so the AI can challenge chronic biases — not just the surface-level problem.
What we learned
People don't need answers. They need structure. When you give someone a perfectly reasoned AI recommendation, they reject it — even if the logic is sound — because a decision about your life can't be reduced to an algorithm without feeling dehumanizing. The constraint that AI never picks a winner made every design decision harder and every outcome better.
A fully local AI engine ensures zero-config demos. We built the scenario generator to produce grounded, context-aware analysis entirely on-device — so judges can run the full app without configuring API keys. The behavioral observation layer (slider tracking, constraint auditing, dwell analysis) doesn't use AI at all — it's a real-time client-side engine that watches actual user behavior and generates insights from live session data.
Progressive disclosure beats information density every time. Our first build was a wall of charts. Our final build gates content into phases. The second version was dramatically more effective.
What's next for Crossroads
Server-side mock fallbacks for the two endpoints that still require API keys. A richer decision journal with offline PWA support. Multi-language localization — the decision framework is culturally neutral but the UI is English-only. Better PDF export with embedded radar charts and custom layouts.
Built With
- framer-motion
- google-gemini-api
- lucide-react
- next.js-16
- nvidia
- tailwind-css
- typescript
Log in or sign up for Devpost to join the conversation.