Portfolio/Climou
❄ Product · Full-Stack · Owned end to end

Climou

Find a café or restaurant with real air conditioning near you, ranked by how well it actually cools. I own it end to end: the React front end, the NestJS API, the OpenStreetMap data pipeline, seven languages, the monetization, and the deploy.

Role
Solo: product, frontend, backend, ops
Timeline
2025 – Present
Type
Product I own
Platform
Web · React + NestJS · Fly.io
Cclimou.app
🌐 EN ▾
❄ Confirmed ACCuisine ▾≈ 10 min walk ▾
Working Coffee Lunch Dinner Escape Dogs
❄ Best cooling🚶 Distance✓ Verified

3 places · confirmed AC only · Cannes

🚶 4 min

restaurant · french · Open now

❄ AC comfortable❄ 92/100verified 2 days ago by 3
  • ✓Free Wi-Fi
  • ✓Non-smoking
  • –Dogs unknown
  • ✓Cards + tap
🌐 WebsiteReport AC
🚶 7 min

cafe · coffee · Open now

🧊 Cold inside❄ 81/100verified 5 hours ago by 2
  • ✓Free Wi-Fi
  • ✕Smoking area
  • ✓Dogs welcome
  • ✓Cards
🌐 WebsiteReport AC
🚶 6 min

fast food · burger · Closed now

🌡️ AC unknown❄ 46/100
  • –Wi-Fi unknown
  • ✓Non-smoking
  • ✕No dogs
  • ✓Cards
🌐 WebsiteReport AC

A product,
not a project.

Climou started as a heat-wave annoyance: every map app can find a café, none can tell you whether it has working air conditioning. The data is sitting in OpenStreetMap tags; it just is not surfaced anywhere useful.

The strategic bet: don’t compete with Google Maps on coverage, win on one question it answers badly, “where can I actually cool down right now.” That narrows the audience to people in a heat wave in a dense city, and it makes the product opinionated: the default sort is cooling, not distance or rating, and a place with no AC evidence simply doesn’t show in confirmed-AC results.

So I built the whole thing. A NestJS API that pulls places from Overpass, merges weather from Open-Meteo, resolves photos from Wikidata, and ranks results by a Cooling Score. A React front end that has to work on a phone in the sun. Seven languages. Ads and a sponsorship tier for revenue. Deployed on Fly.io.

There is no team and no client. Every product call is mine: what the score rewards, how stale a report can be, whether a paywall is on the table, where the ad slots go. I ship each one straight to production and judge it against a single question, did it make a hot afternoon easier.

TypeProduct I designed, built and run
OwnerMe, solo, end to end
Front endReact 19, TypeScript, Vite, plain CSS
Back endNestJS 11, Overpass, Open-Meteo, Wikidata
Reach7 languages, mobile-first
LiveFly.io · climou.app

Pick one question.
Answer it better than anyone.

A solo product only works if it is ruthless about scope. I spent the first fortnight deciding who Climou is for, who it is not for, and what it will never become.

01
The user and the moment
One person, in a heat wave, in a dense city, on a phone, deciding where to go in the next ten minutes. Every default is tuned for that moment: location first, cooling first, walk time in minutes, a heat-cost note on the walk.
02
Where it competes
Not on coverage or reviews. Maps and TheFork already win those. Climou owns the one question they answer badly, whether the place is actually cool inside, and treats that as the whole product rather than a filter bolted onto a directory.
03
What it will never be
Not a review site, not a social app, no user accounts. The only thing a visitor contributes is a six-tap AC report, because anything heavier does not get done in 35-degree heat.

How I judge it. There is no revenue target worth stating yet, so success is three things: a confirmed-AC search in a covered city returns something genuinely useful, the score holds up when a stranger asks why it is 92, and the whole thing loads fast on a mid-range phone on mobile data. Anything that fails one of those is a bug, not a backlog item.

Checked the idea
before building the stack.

First I checked the data existed. I pulled air-conditioning tag coverage from OpenStreetMap for a dozen European cities: dense in the south, thin in the north. That decided the launch markets and told me a community-report layer was not optional, it was the product.

Then a teardown of Maps, TheFork and Foursquare on the exact job to be done. None of them answer “is it cool inside” at all, which confirmed the gap was real and not just unglamorous.

During the 2025 heat wave I put a rough build in front of friends and watched what they tapped. Two things stuck: they wanted one answer, not a list, which became the one-tap “take me somewhere cool” button; and every single person asked “why that score”, which is why the breakdown is one tap away on every result.

Data checkAC tag coverage, 12 EU cities
TeardownMaps, TheFork, Foursquare
Live testFriends, 2025 heat wave
Insight 1One answer beats a list
Insight 2No trust without a visible score
ResultOne-tap search + score breakdown

The hard parts were
all engineering.

The idea is simple. Making it reliable, honest and self-funding was the work.

01
Data you don't control
Every result leans on free public APIs (Overpass, Nominatim, Open-Meteo) with rate limits, downtime and inconsistent tagging. A naive call fails constantly.
02
'Has AC' is fuzzy
The OpenStreetMap air-conditioning tag is often missing or stale. An honest answer needs the tag and fresh input from people who are actually there.
03
It has to pay for itself
A product with real server costs needs revenue without turning into an ad swamp or hiding the useful part behind a paywall.

Front end, API, data,
deploy: all mine.

01
An API that survives the internet
The backend fails over across three Overpass mirrors with a two-minute cooldown per endpoint, 20-second abort timeouts, a five-minute response cache snapped to a ~110 m grid, and request coalescing so a hundred people searching the same block hit the network once. Weather and geocoding degrade gracefully, so a weather outage never blocks results.
NestJSFailover & CachingRate LimitsGraceful Degradation
02
A stable contract for the UI
Every place comes back with every field present (null, 'unknown' or an empty list when a tag is missing), so the front end never has to branch on absent keys. Photos are resolved from a place's Wikidata entity in one batched, cached call.
API DesignTypeScriptDTOsWikidata
03
The Cooling Score
A transparent 0–100 score you can hover to see the maths: confirmed AC +45, verified this week +20, open now +15, reported very cold +10, smoke-free +5, no breakdown reports +5. A same-day 'broken today' report caps it at 15 and drops the place out of confirmed-AC results for 24 hours. 'Open now' is parsed from OpenStreetMap opening hours, never guessed.
Rankingopening_hours parsingCommunity Reports
04
Built for a phone in the sun
Mobile-first, hand-written CSS, no framework. One tap on 'Take me somewhere cool' chains geolocation, confirmed AC, open now, a sub-10-minute walk and best cooling into a single button. Distance is shown as walk minutes, with a heat-cost warning on hot days.
React 19Mobile-firstGeolocationi18n · 7 languages
05
Shipped and paid for
The backend runs on Fly.io in Docker; the front end is a static build. Revenue is two sponsorship tiers that boost a place in the ranking, always clearly labelled, plus ad slots every nine results, all gated behind a consent banner with real privacy and terms pages.
Fly.ioDockerMonetizationConsent & Legal

Four decisions
that shaped the product.

Owning it solo means every trade-off is visible and every one is mine. These are the ones that mattered.

01
A glass-box score, not a star rating
A five-star rating would have been simpler to build and instantly familiar. But nobody trusts an unfamiliar metric they can't inspect. I made the Cooling Score fully transparent (hover it and every point is itemised), which cost real UI work and a metric that takes a sentence to explain instead of none. Worth it: the score is the product, and it only works if people believe it.
TrustTransparencyRanking design
02
Freshness beats volume on reports
Community AC reports decay out of the score after 14 days. Keeping them forever would show more “data” and make quiet places look worse than unknown ones. But an AC unit that worked last summer tells you nothing today. I chose a short freshness window and accept that a good place with only old reports reads as unverified. Honest over flattering.
Data honestyRecencyCommunity input
03
Labelled ads, never a paywall
The useful part, confirmed-AC search and the score, is free and always will be. Revenue is sponsored boosts that are always labelled as sponsored and ad slots every nine results. A subscription would earn more per user; it would also gate the exact people the product is for during the exact hour they need it. The ceiling is lower on purpose.
MonetisationEthicsPositioning
04
OpenStreetMap over a commercial places API
Google Places would have given cleaner data and zero infra worry. It would also have meant per-call pricing, terms that forbid the ranking I wanted, and no AC tag anyway. Building on Overpass meant I own the reliability problem (three-mirror failover, caching, request coalescing) but also the freedom to rank however the product needs.
Build vs buyData ownershipCost

Six things,
one job: keep you cool.

❄️
Confirmed-AC search
Search restaurants, cafés and fast food near a point or your location, filtered to places with confirmed air conditioning.
📊
Cooling Score
Every result gets a 0–100 score for how well it cools, with a breakdown you can open. Best cooling is the default sort.
🌡️
Weather-aware advice
A heat banner over the results with the current feels-like, a heat level, and tips, plus a walk-time heat cost on hot days.
📣
Community AC reports
Anyone can report from a result: working, very cold, not keeping up, broken today. Reports feed the score and expire after 14 days.
🌍
Seven languages
Full UI translation in English, French, Dutch, German, Greek, Russian and Spanish, with a language selector in the nav.
💶
Sponsorship and ads
Owners can boost a place with a Gold or Silver tier, and ad slots fund the rest. Sponsored results are always labelled.

A closer look.

One person,
the whole stack.

Figures describe the build. The interface mockups on this page are reconstructions of the real UI, not live screenshots.

2
Services, one product
React front end and NestJS API, both mine
3
Overpass mirrors, auto failover
Per-endpoint cooldown, timeouts, retries
6
Inputs to the Cooling Score
Weighted, transparent, hover to see
7
Languages shipped
EN, FR, NL, DE, EL, RU, ES
14-day
Freshness window on reports
Stale verification decays out of the score
1-tap
'Take me somewhere cool'
Five filters chained into one button

What I’d change. The product is right; the distribution isn’t solved. Climou only matters during a heat wave in a city with dense OSM data, and I have no answer yet for being found in that 48-hour window. That is the real problem to work on next, not another feature. I’d also revisit “confirmed AC only” as the hard default: it’s honest, but on a first visit an empty result set reads as a broken app rather than a strict filter.

Next Project
RideMetri
A browser-only creator tool: Garmin telemetry drawn over your ride footage, exported as a 1080×1920 PNG sequence.
View project →