-
-
Culture Arbitrage: what one city already loves, another may be missing. (Illustration)
-
Trends travel: boba from Taipei to Tokyo, malatang to Tokyo via Seoul. The agent looks for the next one. (Illustration)
-
Taste twins: neighbourhoods in two cities whose people love the same things, and a shop one still lacks. (Illustration)
-
Live Tokyo run: taste twins on the map, two opportunities, and Claude's reason for every Qloo call.
-
Each card shows how many places Qloo lists on each side and how its confidence is computed.
-
Six scores, each linked to its Qloo call. The agent's own checks pull Korean fried chicken in Chūō-ku from 80% to 67%.
-
Seoul: a record store gap in Gangnam District, against its taste twin Sakuragaokachō in Tokyo.
-
New York, the benchmark city: no convincing gap in this run, and the agent says so.
-
Ideas the agent ruled out stay on screen, greyed out, with the reason.
-
How the agent decides: Claude picks the lookups, Qloo supplies the evidence, code computes every score.
Inspiration
I'm a student living in Japan. In 2019 bubble tea, a Taiwanese staple for decades, suddenly took over Tokyo, and "tapiru" (to go drink boba) became one of Japan's buzzwords of the year. Then malatang did it again, reaching Japanese Gen Z by way of Seoul and K-pop fans.
Both times, the demand was proven in another city long before it arrived here. Chains saw it early because they pay consultants to look. Someone opening one shop can't, so they find out last, when the queue is already outside someone else's door.
That is an information gap, not a talent gap. I built Culture Arbitrage so a small founder can see it too, and check whether a gap is real before signing a lease.
Site-selection tools start from a business you have already chosen and rank locations in one city. Culture Arbitrage starts from what the same taste audience already supports in another city, then tries to rule out each gap before it shows it.
What it does
Pick Tokyo, New York or Seoul and, optionally, a focus (dining, nightlife or retail). A Claude agent then works through Qloo, live on screen, across eight categories: malatang, bubble tea, Korean fried chicken, bagel shops, natural wine bars, jazz clubs, record stores, and comic and manga stores.
Two ways to ask. Scan a city and the agent looks for whatever it is missing. Or check one business: type what you want to open ("yoga studio", "ramen shop", "natural wine bar", or "瑜伽" in your own language) and the agent answers a narrower question: which neighbourhoods are short of it compared with their taste twins, or whether the city is already well supplied.
- Profiles neighbourhoods: the localities Qloo lists for the city, and the taste tags Qloo attaches to each ("trendy", "vintage stores", "cafe hopping").
- Finds taste twins in the other two cities. Qloo ranks the other city's localities with the home neighbourhood as the signal, and the agent scores each by the share of Qloo taste tags the two have in common, listing the tastes they share.
- Compares supply: how many places Qloo lists for each category within the same 2.5 km circle around each neighbourhood's centre, so both sides cover the same area. A gap needs at least 4 places in the twin and 3 times the home count.
- Argues against itself before submitting anything. Does the rest of the city already have it? Do the category's fans (Qloo demographics) lean to the same age bands as the people who live there? In Tokyo that is the official resident register of each ward, because Qloo describes the fans of a taste, not the residents of a place. Is the evidence thin, or cut off by Qloo's page size? Google Maps, a second and independent index, is asked whether it sees the same gap. After every Qloo lookup the gaps found so far are scored again, so you can watch a score fall as the checks come in.
- Returns opportunity cards, most convincing first, each with six scores and a score trail. Five scores are computed in code from Qloo answers (plus the ward statistics in Tokyo); product fit is Claude's judgment and is labelled that way. An idea that drops below 55% confidence, or where Google Maps lists as many places at home as in the twin, is ruled out and stays on screen, greyed out, with the reasons.
The business list holds 176 types, from cafés and izakayas to pilates studios, record stores and climbing gyms. We didn't pick them by hand: the agent's own tools counted, on live Qloo data, how many places Qloo lists for about 350 candidate types in Tokyo, New York City and Seoul, and kept the ones with enough data to compare. Anything not on the list is matched to a place category through Qloo's tag search, so the agent can still check it.
Every Qloo-based number on a card carries a Q chip that opens the exact Qloo call behind it. A live log shows each step with the agent's one-line reason, and a world map draws each taste twin and each gap as an arc between cities.
On live data, runs have found record stores missing in Seoul's Mapo District (84% confidence) and bagel shops in Gangnam District (81% in another run). New York is the benchmark city: its neighbourhoods already have most of what their twins in Tokyo and Seoul support. In the demo run the agent kept two gaps at 58% and ruled out two others with its own checks. When nothing survives, "nothing convincing here" is the answer, not an error.
How we built it
- Next.js (App Router) and TypeScript, one codebase deployed on Vercel. The exploration streams from a route handler as newline-delimited JSON, so the page renders each step as it happens. Source: https://github.com/Ebusoda/CultureArbitrage (MIT).
- Claude is the agent, through the Anthropic SDK: a streaming tool-use loop with adaptive thinking and strict-schema tools (list neighbourhoods, taste profile, find taste twins, compare supply, check city supply, audience profile, the Google Maps cross-check and submit opportunity). Every call carries a
reason, which is the line the viewer reads in the log. If Claude tries to give up after comparing fewer than 3 neighbourhoods, the loop asks it once to keep looking. - Qloo is the evidence layer. A server-side client sends the key as a header, times out, retries 429 and 5xx with backoff, caches identical requests, and counts every call against a hard budget of 40 per run. Within a run every lookup is memoised and numbered, so the agent never pays twice for the same question and every number can cite its call.
- Business types from Qloo's own index. Qloo's
/v2/tagssearch finds the place tag for a business type, and one place search per city tells us how many places Qloo lists for it. A type made the list only when at least two cities list 5 or more, because a gap needs at least 4 places in the twin neighbourhood. The page shows those counts next to each type and warns when the home city lists so few that a "gap" may be missing data rather than missing shops. Scores live in code, not in the model.submit_opportunityonly names the gap; the card is built from the Qloo responses already gathered for it. Confidence is the average of the measured scores, lowered 5% for each open doubt. It ranks the evidence; it is not a probability that a shop will succeed. A check the agent skips counts as its worst result, so skipping work never raises confidence. Claude must tag each doubt by topic, and a doubt about something a score already measures is not counted twice. A submission that fails the gap rule, or lands below 55%, goes back to the model with the reasons. A pair must be a real taste twin before any score counts: one sharing less than a fifth of its taste tags is held below 55% and sent back, whatever its other scores. - Two outside sources, labelled. Tokyo ward age data comes from the Tokyo Metropolitan Government's resident statistics (January 2026). The Google Maps cross-check uses Places API (New) Text Search, asks only for place ids, changes no score, can only rule a gap out, and shows its numbers in their own "Google Maps" box.
- The demo does not break. If Claude is unavailable, a fixed pipeline runs the same tools in a set order. If live runs are busy or a run fails before it found anything, the page plays a recorded run for that city under a "Recorded run, not live" banner.
- UI: React, Tailwind CSS and a d3-geo world map (Natural Earth data via world-atlas).
- Over 200 offline tests (
npm run verify) cover the Qloo client, the cache, input checks, business-type matching, scoring, full mock runs, a scripted Claude loop, the Google Maps cross-check and the recorded-run fallback, with no keys and no network.
Challenges we ran into
- Building before the data arrived. Qloo keys are issued by hand, and mine came late. I wrote the client and a mock with the same request and response shapes as the official hackathon kit, so switching to live data was one environment variable. Then live data broke half my assumptions: a tag signal scored every neighbourhood the same, location lookups returned theme parks, and place categories have no trend data. Each one changed the method, not just the code.
- Comparing like with like. Qloo's geocoding of a neighbourhood name is uneven: "Brooklyn, New York City" found 5 places, "Brooklyn, New York" found 50. So every count uses an equal 2.5 km circle around the centre Qloo gives for each neighbourhood.
- Keeping the model honest. A language model will happily write a plausible number, and it kept restating facts a score already counted as fresh doubts. So the model only chooses what to look up and which gap to submit, and code builds every number and decides which doubts count.
- "Missing" can mean "not indexed". A shop absent from Qloo may still exist on the street. The agent checks the whole city, flags thin or capped samples, asks Google Maps, and every count is shown as places Qloo lists, not a census.
- Free text is ambiguous. "Korean restaurant" first matched Korean barbecue, "ice" matched juice bars, and "bar" matched barbecue, because tag search returns everything that contains the word. Matching now compares whole words, prefers the tag that is exactly what was asked for, and refuses words that are too broad to be one business ("bar") instead of quietly checking something narrower.
- Coverage is uneven. Seoul is well covered for food and drink but thin for many shops, gyms and salons. The agent now skips twin cities where Qloo lists too few of the type to show a gap, and says so.
- Quota and watchability. Qloo asks for small requests and no bulk crawling, and a run makes 25 to 35 calls in one to two minutes. The log, the map and the caption had to tell one story at that pace.
Accomplishments that we're proud of
- Every Qloo-based number on a card can be traced to the request that produced it, one click away.
- The agent argues against its own ideas in the open. You can watch a score drop as its checks come in, the ideas it rules out stay on screen with the reasons, and "nothing convincing here" is an answer it is allowed to give.
- It runs on live Qloo data in three cities, and the public demo still shows a result when a live run can't.
- A sanity check with a known answer: asked whether Tokyo is short of ramen shops, the agent found no gap.
What we learned
- Taste data is good at "who would love this here" and silent on "is there already one on the street". Designing around that limit mattered more than any prompt.
- An agent's reasoning is only as honest as the arithmetic around it. Moving every number out of the model made the results less exciting and more believable.
- Results move from run to run, because Claude picks different neighbourhood pairs. Showing the score trail and the ruled-out ideas matters more than any single number.
What's next for Culture Arbitrage
- More cities, starting with US cities where Qloo's coverage is deepest.
- A hold-out sanity check: hide one category from a city's supply and see whether the agent still points to where it really clusters. On today's snapshot this is a consistency check, not a historical backtest.
- Free for the person opening one shop; paid for franchise brands, commercial landlords and promoters choosing their next neighbourhood or city.
- The same taste-twin engine works for people too: tell it the neighbourhood you love, and it finds the one in your new city whose people love the same things. (Taste match only: no listings or rent.)
Built With
- anthropic
- claude
- google-places
- next.js
- node.js
- qloo
- react
- tailwindcss
- typescript
- vercel