Skip to content
<Hyun/>
All projects

CityLink

Hackathon · Hackathon discovery

Pick a city. Start exploring.

A selected city connects recommendations, map markers and the conversation, with my front-end contribution called out.

Interactive explanation · not the live service

Loading interactive explanation…

Explore the architectureSystem diagrams, design decisions and detailed flows

System overview

  1. REACT FRONT ENDCity search pageGoogle Map, autocomplete
    Step 1, autocomplete
    Google Maps PlatformMaps JS + Places
  2. City search page
    Step 2, recommendations
    Flask AI servicerecommendations, chatbot
    fixed-format prompt
    OpenAI APIgpt-4o-mini
  3. City search page
    city + lists
    REACT FRONT ENDCity chat pageroom, lists, chatbot
    Step 3, ws ?placeId
    WebSocket serverNode, Express, ws
    push / range
    Redischat history per city

Other connections

  • City chat pagetoFlask AI servicechatbot
The React front end (1) finds a city with Google Maps, (2) gets recommendations from a Flask service backed by OpenAI, and (3) joins a per-city chat room on a Node WebSocket server backed by Redis. The chat page's chatbot also calls the Flask service.
View the diagram as text

Parts

  • City search page (Google Map, autocomplete): Client / UI
  • City chat page (room, lists, chatbot): Client / UI
  • Google Maps Platform (Maps JS + Places): External service
  • Flask AI service (recommendations, chatbot): Owned service
  • WebSocket server (Node, Express, ws): Owned service
  • OpenAI API (gpt-4o-mini): External service
  • Redis (chat history per city): Data store / broker

Connections

  • Step 1: City search page → Google Maps Platform: autocomplete
  • Step 2: City search page → Flask AI service: recommendations
  • Flask AI service → OpenAI API: fixed-format prompt
  • City search page → City chat page: city + lists
  • Step 3: City chat page → WebSocket server: ws ?placeId
  • WebSocket server → Redis: push / range
  • City chat page → Flask AI service: chatbot

From picking a city to joining its chat room

  1. Pick a city

    Places autocomplete is limited to cities, and clicking the map runs a nearby search for localities within 50 km and offers them as suggestions.

  2. Get AI recommendations

    The page asks the Flask service for recommendations; it requests exactly five places and five restaurants from gpt-4o-mini in a fixed format and parses the reply into two lists.

  3. Open the city page

    The app navigates to the chat page with the Google Place ID, city name and lists, and each item gets a Google Maps link.

  4. Join the room

    The page opens a WebSocket for that Place ID. The server adds the socket to the room, broadcasts the online count and sends saved history from Redis.

  5. Chat and refine

    Messages are pushed to the room's Redis list, trimmed to the most recent ones, and broadcast to the room. The chatbot can regenerate one of the lists or give a short answer.

The project & my contribution

Problem
Planning a city visit means looking up places, restaurants and other travelers' tips in separate apps.
Solution
A map app: pick a city to get AI picks for places and restaurants, and chat live with others viewing the same city.
Result
Built at a 2025 UVA hackathon, with every recommendation linking straight to Google Maps.

My part

  • Fixed city-suggestion clicks so they call the recommendation API
  • Added a dark Google Maps style, custom map markers and click-outside closing for the suggestion list
  • My teammate built the Flask recommendation service and the WebSocket chat server

How it's built

  • React front end with Google Maps and Places search
  • A Flask service asks gpt-4o-mini for five places and five restaurants in a strict format
  • Node.js WebSocket chat rooms keyed by Google Place ID, with history in Redis

Highlights

  • The chatbot regenerates only the list you ask about and keeps the other
  • Every recommendation links straight to Google Maps