Skip to main content
TripLoom provides destination search for trip creation, flight booking, and general exploration.

Features

City search

Find cities worldwide with autocomplete

Airport search

Search by IATA code or airport name

Instant suggestions

Results appear as you type (2+ characters)

SerpAPI integration

Powered by Google Flights autocomplete

How destination search works

The search input debounces user input (280ms) and queries the API when you type 2 or more characters. Endpoint: GET /api/destinations/search?q=berlin Response:
{
  "ok": true,
  "data": [
    {
      "id": "ChIJAVkDPzdOqEcRcDteW0YgIQQ",
      "name": "Berlin",
      "displayName": "Berlin - Germany",
      "type": "city",
      "iataCode": "BER",
      "cityName": "Berlin",
      "countryCode": null
    },
    {
      "id": "BER",
      "name": "Berlin Brandenburg Airport",
      "displayName": "Berlin Brandenburg Airport (BER), Berlin",
      "type": "airport",
      "iataCode": "BER",
      "cityName": "Berlin",
      "countryCode": null
    }
  ]
}
City results include the primary airport’s IATA code. This allows seamless switching between “Berlin” (city) and “BER” (airport) in flight searches.

Airports-only mode

When searching for flight origins and destinations, use airports_only=1 to exclude city results: Request: GET /api/destinations/search?q=lon&airports_only=1 Response:
{
  "ok": true,
  "data": [
    {
      "id": "LHR",
      "name": "London Heathrow Airport",
      "displayName": "London Heathrow Airport (LHR), London",
      "type": "airport",
      "iataCode": "LHR",
      "cityName": "London",
      "countryCode": null
    },
    {
      "id": "LGW",
      "name": "London Gatwick Airport",
      "displayName": "London Gatwick Airport (LGW), London",
      "type": "airport",
      "iataCode": "LGW",
      "cityName": "London",
      "countryCode": null
    }
  ]
}

Using the search component

The DestinationSearch component provides:
  • Autocomplete dropdown with keyboard navigation (arrow keys, enter, escape)
  • Value prop to control the input externally
  • onChange callback triggered on input change
  • onSelect callback when user picks a suggestion
  • airportsOnly prop to filter results
Example:
import { DestinationSearch } from "@/components/dashboard-home/destination-search"

function FlightForm() {
  const [origin, setOrigin] = useState<string>("")

  return (
    <DestinationSearch
      value={origin}
      onChange={setOrigin}
      onSelect={(suggestion) => {
        console.log("Selected:", suggestion.iataCode)
      }}
      airportsOnly
      placeholder="Where from?"
    />
  )
}
Set airportsOnly={true} for flight search forms to ensure users select valid IATA codes.

Suggestion structure

Each suggestion from SerpAPI is transformed into:
  • City: The city name with the first airport’s IATA code
  • Airports: Each airport in the city as a separate suggestion
SerpAPI raw response:
{
  "name": "Berlin",
  "id": "ChIJAVkDPzdOqEcRcDteW0YgIQQ",
  "type": "city",
  "airports": [
    {
      "name": "Berlin Brandenburg Airport",
      "id": "BER",
      "city": "Berlin"
    },
    {
      "name": "Berlin Tegel Airport",
      "id": "TXL",
      "city": "Berlin"
    }
  ]
}
Transformed:
[
  {
    "id": "ChIJAVkDPzdOqEcRcDteW0YgIQQ",
    "name": "Berlin",
    "displayName": "Berlin - Germany",
    "type": "city",
    "iataCode": "BER",
    "cityName": "Berlin",
    "countryCode": null
  },
  {
    "id": "BER",
    "name": "Berlin Brandenburg Airport",
    "displayName": "Berlin Brandenburg Airport (BER), Berlin",
    "type": "airport",
    "iataCode": "BER",
    "cityName": "Berlin",
    "countryCode": null
  },
  {
    "id": "TXL",
    "name": "Berlin Tegel Airport",
    "displayName": "Berlin Tegel Airport (TXL), Berlin",
    "type": "airport",
    "iataCode": "TXL",
    "cityName": "Berlin",
    "countryCode": null
  }
]

Debounce and caching

The component:
  • Debounces input for 280ms to reduce API calls
  • Shows “Searching…” while loading
  • Returns up to 20 results (API default)
  • Clears results when input is less than 2 characters

Error handling

If the API fails:
  • The dropdown shows “No destinations found. Try a city or airport name.”
  • The search can be retried by continuing to type
Search errors are logged client-side but do not block the UI. Users can still type and retry.

API configuration

Destination search requires:
  • SERPAPI_API_KEY (or SERPAPI_KEY)
Without this key, the endpoint returns:
{
  "ok": false,
  "error": "Destination search requires SerpAPI key. Set SERPAPI_API_KEY or SERPAPI_KEY in env."
}
Status code: 503 Service Unavailable

Build docs developers (and LLMs) love