Public
Tuesday Delta fares + NYC boutique hotel finder
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.

NYC Trip Finder

Flight + hotel finder for one specific trip pattern: flying out of MSY on Tuesdays into JFK or LGA (nonstop, Delta preferred, cheapest refundable fare), and boutique/4-star hotels under $350/night in SoHo, Nolita, Lower East Side, Chelsea, or Greenwich Village.

Built for one person's use, not a general-purpose app.

Architecture: our own UI, Travelpayouts as a data source only

Earlier drafts of this app tried an embeddable Travelpayouts widget (Aviasales/Hotellook branded search boxes). That's not what this app does now — it uses Travelpayouts' plain JSON APIs as a data source and renders everything in our own UI. Given the budget, a custom flight/hotel pricing engine from full scratch (own scraper, own inventory) still wasn't the right trade — but "our UI, their data" is.

  • Flights tabflights.ts calls the Aviasales Data API (/v1/prices/calendar), a plain JSON endpoint returning the cheapest cached fare per day for a route. High confidence: single GET request, documented and tested against the real API shape.
  • Hotels tabhotels-live.ts calls the Hotellook engine API (engine.hotellook.com), a two-step MD5-signed search (start, then poll for results). This one is unverified — I built it against Travelpayouts' documented signature spec but couldn't load their full gated help article to triple-check it, and have no token to test against. Treat the first real run as the actual test; if /api/hotels/live returns an error, paste it back and I'll debug against the real response.

Both fall back cleanly (mock flight data / curated-list-only) when their env vars aren't set — nothing crashes either way.

The hand-curated neighborhood/boutique hotel list (data/hotels.ts) stays alongside the live hotel search, because Hotellook's citywide NYC results don't carry "SoHo vs. Nolita vs. boutique aesthetic" — that curation still isn't something any free API does for you. Each flight row also links out to a plain Google Flights search (no API, just a pre-filled URL) as a "verify the real price" check, since Google has better US-domestic fare coverage than Aviasales.

Current state

  • Flights tab: real data once TRAVELPAYOUTS_TOKEN is set (falls back to a mock table otherwise). No refundability field exists in this data source — that column shows "Check" and relies on the Google Flights link.
  • Hotels tab: live NYC search once HOTELLOOK_TOKEN + HOTELLOOK_MARKER are set (shows a config/error message otherwise, never crashes), plus the curated neighborhood list always.

Going live ($0/mo): Travelpayouts

  1. Register at travelpayouts.com (free, no minimum traffic). The marketing site is aimed at travel bloggers monetizing content, which reads oddly for "add search to my app" — but the underlying APIs work the same regardless of how they're marketed.
  2. Find your API token in your Travelpayouts Profile → API token section (this is separate from the widgets/Projects flow — you don't need to create a Project or set up any widget for this).
  3. 👉 Add it here: https://www.val.town/x/unlikelyarchivist/nyc-flight-hotel-finder/environment-variables?key=TRAVELPAYOUTS_TOKEN
  4. For hotels, you also need a marker (your partner/affiliate ID, findable in the same account area — it's used for attribution, distinct from the API token): 👉 https://www.val.town/x/unlikelyarchivist/nyc-flight-hotel-finder/environment-variables?key=HOTELLOOK_TOKEN 👉 https://www.val.town/x/unlikelyarchivist/nyc-flight-hotel-finder/environment-variables?key=HOTELLOOK_MARKER
  5. Reload the app. If the Hotels tab shows an error instead of live prices, send me the exact error text from the yellow box — that's the real signal for what to fix in hotels-live.ts.

JFK vs LGA — which is better for MSY?

Worth showing both rather than picking one:

  • LGA is Delta's home domestic hub in NYC — it usually has more Delta departures/day and connects to more of the network, so it's often the cheaper, more frequent nonstop option for domestic city pairs like MSY.
  • JFK is Delta's international/long-haul hub — still serves MSY nonstop, but with fewer daily frequencies; can occasionally undercut LGA on price depending on the week.

Roadmap / open design decisions

  • Combining flight + hotel dates into one trip cost. Flights and hotels query independently right now (hotels defaults to a generic 30-days-out date range). A v2 could pass the Tuesday she picks in the flight table as the hotel search's check-in date.
  • Round trip / return date. Her trip length varies trip to trip (not a fixed pattern). Not built into the flight data yet — /v1/prices/calendar as used here is one-way; a round-trip version would need a second call per candidate return date.
  • Refundability. Not available from the free flight data API. Stays a manual "Verify" click through to Google Flights.
  • Matching live Hotellook results to the curated list. Right now the live section and the curated list are two separate blocks, not merged — matching them by name would be fragile without Hotellook's internal hotel IDs, so they're kept apart rather than faked into one list.
  • Configurable origin/destination. Currently hardcoded to MSY and JFK/LGA. Fine for v1 (one person, one route).
  • Alerts. Not built — the plan is to fold this into a combined morning-brief automation across this app and the client-appointment-tracker app once both exist, rather than building separate notification plumbing here.

File structure

index.ts                          ← Hono backend: serves frontend + /api/flights + /api/hotels + /api/hotels/live
flights.ts                        ← Aviasales Data API (real once TRAVELPAYOUTS_TOKEN set; mock otherwise)
hotels-live.ts                    ← Hotellook signed search (untested — see "Architecture" above)
data/hotels.ts                    ← Curated neighborhood hotel list
frontend/
  root.tsx                        ← HTML shell (+ iOS home-screen meta tags)
  index.tsx                       ← React entrypoint
  components/
    App.tsx                       ← Tab layout (Flights / Hotels)
    FlightsPanel.tsx               ← Flight table + Google Flights verify links
    HotelsPanel.tsx                ← Live hotel results + curated picks list

Template updates and upgrade paths for existing remixes: CHANGELOG.md