Public data product

An air-quality assistant that shows its sources

A free, bilingual map and chat advisor that turns Jakarta's official air-quality readings into plain answers, each one tied to a source and a time. It is built as a public good: information that helps people breathe safer should be free.

Type
Personal project, built end to end
My role
Solo: product, design, engineering and evaluation
Status
Live, free for everyone, no login
Running cost
Free at low traffic, about $15 a month at scale
A short walkthrough of the live app: a station on the map, then a question to the advisor.
Open the live site
What it costs
$0
A month at today's low traffic
About $15
A month, estimated, even with many users

An AI product does not have to come with a big bill. Small services on shared hosting, a data refresh every hour instead of constant polling, plain code for the number work, and limits on the chat keep it cheap, and that is what keeps it free for the public.

A private view tracks model use and estimated cost for every answer, so the bill is never a surprise.

Why it matters to you: I build for the budget you have, and I show you where the money goes.

The problem

Jakarta's air is a serious public-health issue, and the official readings arrive as index numbers and station names. Turning those into an answer to "is it safe to run outside today?" is left to the reader.

A general-purpose chatbot is no fix. It can sound confident while quoting an old number, or one it made up. For air quality, a wrong number that looks current is worse than no answer.

The gap: official numbers on one side, a person with a question on the otherIndex numbers and station namespublished by the city monitoring networkJargon: ISPU, PM2.5, PM10what does 142 mean for me?A resident with a question"Is it safe to run outside today?"??The numbers exist. Turning them into something a person can act on is left to the reader.
The gapIndex numbers, station namesfrom the city monitoring network?Jargon: ISPU, PM2.5, PM10what does 142 mean for me??A resident with a question"Is it safe to run outside today?"The numbers exist. Turning them intosomething a person can act on isleft to the reader.

Two hard rules: a number must never be older than it looks, and the assistant must say it does not know rather than guess.

The solution

I designed, built and deployed the whole product: the data pipeline, the map, the assistant, the evaluation and the hosting.

Live official readings

Straight from the official monitoring network, refreshed every hour, each with its observation time. Anything older than 24 hours is marked stale, not shown as current.

An interactive map

Station detail, district filters and a heatmap view, on desktop and mobile.

A chat advisor in English and Bahasa Indonesia

Switchable without reloading the page. Ask what the numbers mean, compare areas, or get practical guidance.

Numbers come from code, not the model

Readings, comparisons and history use fixed data tools. Explanations come from a curated library of 29 documents, including WHO guidance and Indonesian regulation, with a citation on each answer.

Clear labels

A station reading, city-level context, modelled history and a fallback snapshot are each marked as such. A missing reading is reported as unavailable, never as zero.

No account and no login

Chat is cleared on refresh, anonymous records are deleted after 30 days, analytics load only after a visitor opts in, and the model key stays on the server.

Found by search and AI

SEO, AEO and GEO built in: separate English and Indonesian pages, structured data on the guides and an llms.txt file, so search engines and AI tools can read and cite it.

Built to run

Scheduled data refresh, structured logs with request IDs, and a private view of latency, model use and estimated cost, so the service is visible while it runs. Next.js and FastAPI on PostgreSQL and Railway.

Deliberately kept out

No diagnosis or predictions

It will not diagnose, predict for an individual, or say what caused a spike.

Not a warning service

It is an information tool, not a medical or official alert service.

No logins or billing

This is a public-information product, and information that helps people breathe safer should be free. It is a public good, so there is nothing to sign up for or pay.

How a question gets answeredA questionEnglish or Bahasa IndonesiaRouterpicks the right toolNumbers: plain codereadings, comparisons, historyExplanations: documents29 curated sources, searchedAnswerwith source and timeNo evidence found? It says so instead of guessing.The model never supplies the numbers. Every figure comes from a data tool, with its observation time.
How a question gets answeredA questionEnglish or Bahasa IndonesiaRouterpicks the right toolNumbersplain code: readings,comparisons, historyExplanations29 curated documents,searchedAnswerwith source and timeNo evidence found?It says so instead of guessing.The model never supplies the numbers.Every figure comes from a data tool,with its observation time.
How the data stays freshOfficial monitorsDKI Jakarta networkScheduled ingestevery hour, validatedDatabasecurrent readingsMap and advisorone workspace, EN and IDOver 24 hours old? Marked stale, never shown as current.Database unavailable? A labelled snapshot, never passed off as live.Station readings, city-level context, modelled history and the fallback snapshot are each labelled separately.
How the data stays freshOfficial monitorsDKI Jakarta networkScheduled ingestevery hour, validatedDatabasecurrent readingsMap and advisorone workspace, EN and IDOver 24 hours old?Marked stale, never shown as current.Database unavailable?A labelled snapshot, never passed off as live.Station readings, city context, modelledhistory and the fallback snapshot areeach labelled separately.
How it is built
Architecture of NAPAS Jakarta: a resident reaches the Next.js web app through Cloudflare; inside one Railway project the web app talks to a private FastAPI service and a PostgreSQL database; an hourly Python job loads validated readings from the official DKI Jakarta network; a router sends number questions to plain-code data tools and explanation questions to document search that feeds the language model; a labelled snapshot is used only if the database is down
The whole system on one page: small services, one project, one database.
More of the site

The map is the front door, but the site also explains the numbers in plain language, in English and Bahasa Indonesia.

The About page of Napas Jakarta, explaining who it is for, where the data comes from and how old readings are handled
About: who it is for, where the data comes from, and how stale readings are handled.
Napas Jakarta guide explaining what ISPU is, with the five ISPU categories
A guide to the ISPU index and its five categories.
Napas Jakarta guide to PM2.5, PM10 and ISPU
A guide to PM2.5, PM10 and ISPU.
The Indonesian version of the Napas Jakarta map and chat advisor
The same map and advisor in Bahasa Indonesia.
Napas Jakarta map and advisor on a phone
The map and advisor on a phone.
How it is kept honest

For an AI assistant, looking right in a demo is not enough. It has to be right about where its answers come from, so the checks go beyond a few good examples.

130+
Automated tests across data, citations, security and logging
29
Curated source documents behind the explanations
1 hour
How often the official readings are refreshed

Other checks cover the data tools, safety and out-of-scope refusals, follow-up questions, and whether a repeated data refresh behaves the same each time. It works in both English and Bahasa Indonesia.

Where it stands

It is live at napasjakarta.com, on its own domain, and refreshing from the official network every hour. I built it as a product in its own right and as a working example of an AI assistant that can be trusted with numbers.

Free by design: air-quality information is a public good, so there is no login, no billing and no paywall.

Known limit: a station reading describes one station at one time, not the whole city. The product says so.

Why it matters to you: if you want an assistant on your own data, this is how I build it. Numbers come from code, explanations come from your documents, every answer shows where it came from, and it stays cheap to run.

Want an assistant your customers can trust?

Book a free 30-minute call and we will work out the simplest version that does the job.