Inspiration
The idea came from a frustration most business travelers know well: you're stuck at Denver International for two hours, you have a contact at a company in Denver, and you only realize it after you've already boarded. The layover was long enough for a coffee meeting - but the moment passed. We wanted to build something that closes that gap. Not just a smarter flight picker, but a tool that treats every stop on your itinerary as a potential opportunity.
What it does
ConnectFlight is an AI-powered flight decision tool with two core ideas: Pick the right flight - search real flights via Google Flights (SerpAPI), rank them by what matters to you (cheapest or fastest), and let Groq AI explain why the top pick is the best choice in plain English. Never waste a connection - if your layover is more than or equal to 90 minutes and you have a business contact in that city, the app surfaces them and suggests a meetup.
How we built it
We used Kiro as our primary development environment throughout the hackathon, working in Autopilot mode with steering docs to keep the AI aligned with our decisions. Stack Frontend: React 19 + Vite + Tailwind CSS v4 Backend: Node.js + Express + TypeScript Flight data: SerpAPI (Google Flights engine) AI: Groq API (llama-3.3-70b-versatile) Routing: React Router v7 The Scoring Formula Flight ranking uses a deterministic weighted formula — no AI involved in scoring, only in explanation. For each flight $i$ across a result set of $n$ flights: score(i)=0.50⋅p^i+0.30⋅d^i+0.20⋅s^i Where each factor is min-max normalized: f^i=(max(f)-fi)/(max(f)-min(f)) This maps the best value (lowest price, shortest duration, fewest stops) to $1.0$ and the worst to $0.0$. When all values are equal, every flight scores $1.0$. Kiro-Driven Development We structured our work in three modes: Vibe coding for UI - shared a Figma screenshot and Kiro generated the full layout in one pass: card hierarchy, typography, button styles, spacing. Spec-driven for the backend - wrote requirements.md and design.md first, then Kiro implemented the API contract, scoring formula, and Groq integration exactly as specified. Steering docs to stay on track - an always-included steering.md kept Kiro from touching the backend during frontend fixes, enforced airline names in AI prompts, and maintained the 90-minute meetup threshold consistently across all features.
Challenges we ran into
Airport Matching Across Languages The hardest bug: a contact in "Manila" wasn't matching a layover at "Ninoy Aquino International Airport (MNL)". The city name simply doesn't appear in the airport's official name. We built a three-tier matching system: Direct substring - does the airport string contain the contact's city? IATA lookup - resolve the code (MNL) to a known city via airports.json Word extraction - strip "International", "Airport", etc... and match remaining significant words The Space Key Problem Typing "San Francisco" in the city autocomplete field was impossible - the space key was silently swallowed. The root cause: a
element with a focused type="submit" button intercepts the spacebar at the browser level before it reaches the input. The fix was converting both contact forms from to and making all buttons type="button" with explicit onClick handlers. Keeping AI in Its Lane Early Groq prompts referenced flights by index ("flight 0 is better than flight 2"), which was meaningless to users. We added a steering rule that will always use airline names, never index numbers, and it held consistently for the rest of the build.Accomplishments that we're proud of
- Shipping a full-stack app in a hackathon. Frontend, backend, two external APIs (SerpAPI + Groq), multi-page routing, shared state, and a contacts manager - all working together by the end of the event.
- The "Never Waste a Connection" feature actually works. Matching a contact in "Manila" to a layover at "Ninoy Aquino International Airport (MNL)" required real engineering - a three-tier matching system that handles the gap between how people name cities and how airlines name airports. It's not a demo trick; it works on real SerpAPI data.
What we learned
Steering docs are underrated. Writing down constraints before building saved more time than it cost. Every time Kiro tried to refactor working backend code while fixing a frontend bug, the steering doc caught it.
Spec-first pays off on the backend. Defining the API shape, error codes, and data types in design.md before writing a line of code meant the frontend and backend never drifted out of sync.
Real data is humbling. SerpAPI returns airport names, not city names. Layover data is inconsistent. Building robust matching for real-world flight data required more edge-case handling than any mock data scenario would have revealed.
What's next for ConnectFlight
- Persist contacts across sessions (localStorage or a simple backend store)
- Expand airport data to full worldwide coverage
- Push notifications when a contact is in your upcoming layover city
- Calendar integration to auto-detect upcoming trips
Built With
- express.js
- groq
- node.js
- react
- reactrouter
- serpapi
- tailwind
- typescript
- vite
Log in or sign up for Devpost to join the conversation.