CatalogPublic data ›Reference

Your municipality in numbers — a portrait from official data

A portrait of your municipality built from official data: population and age structure (ISTAT), average declared income (MEF), pharmacies (Ministry of Health) and state schools (MIUR). The sources join on their own through the municipality's ISTAT code. Plus a map of Italy and the rankings.

🔎 Your municipality🏫 The schools🗺️ The map🏆 Rankings

data space «comune-in-cifre» — the suite’s glue: on your device, multi-user with one invite (link or QR), end-to-end encrypted.

▶ Open the suite (4 micro apps)

or open it as a single app

municipalitiespopulationincomeistatmefdemographicsforeign residentspharmaciesschoolswastebusinesseselectionsinvalsivehiclesacimapchoroplethterritory

What it records

  • Municipality's ISTAT code

Composed of 4 micro apps

One job each, over the same data: every micro app reads and writes the shared data space “comune-in-cifre” (with your consent, asked on first open). Everything stays on your device — and with a single invite the whole suite goes multi-user, end-to-end encrypted.

How it works

This is a Reactive app: a plain text document that your browser turns into a working app — forms, live data, tables, statistics and even charts, with nothing to install or configure.

  1. Use it right away. Hit “Use this app”: it opens right in your browser, ready to go, with data saved only on your device.
  2. Your data stays yours. Everything is stored locally on your device, kept separate for each app: no account, no server, nothing to set up.
  3. Make it your own. The text below is the entire app: copy it, tweak fields, views and words, and your changes become interactive instantly.
  4. Share it as a file. An app is a simple file: save it, export it or share it with a link; and with encrypted collaboration several people edit the same data in real time.
The app’s source
# 🏘️ Your municipality in numbers

A portrait of your municipality built from official data: population and age
structure (ISTAT), average declared income (MEF), pharmacies (Ministry of
Health) and state schools (MIUR). The sources join on their own through the
municipality's ISTAT code. Plus a map of Italy and the rankings.

:::::page{title="Your municipality" icon="🔎"}

## Find your municipality

Enter the **ISTAT code** (six digits): e.g. `058091` Rome, `015146` Milan,
`037006` Bologna, `063049` Naples.

::input[comune]{value="037006" placeholder="Municipality's ISTAT code"}

::od-query{into="profilo" sql="SELECT p.comune AS comune, p.popolazione AS popolazione, r.reddito_medio AS reddito_medio, i.eta_media AS eta_media, i.perc_stranieri AS perc_stranieri, i.indice_vecchiaia AS indice_vecchiaia FROM istat_popolazione p LEFT JOIN mef_redditi r ON r.codice_istat = p.codice_istat LEFT JOIN istat_indicatori i ON i.codice_istat = p.codice_istat WHERE p.codice_istat = '{#comune}'"}

:::cards{path="profilo" search="false"}
### {comune}
**{popolazione}** inhabitants — average income **{reddito_medio} €**, average age **{eta_media}** years, foreign residents **{perc_stranieri}%**, old-age index **{indice_vecchiaia}** (over-65s per 100 under-15s).
:::

::od-query{into="servizi" sql="SELECT (SELECT count(*) FROM farmacie WHERE codice_istat = '{#comune}') AS farmacie, (SELECT count(*) FROM scuole WHERE codice_istat = '{#comune}') AS scuole"}

:::cards{path="servizi" search="false"}
🏥 **{farmacie}** pharmacies · 🏫 **{scuole}** state schools
:::

::od-query{into="ambiente" sql="SELECT percentuale_rd AS percentuale_rd, anno AS anno FROM rifiuti WHERE codice_istat = '{#comune}' ORDER BY anno DESC LIMIT 1"}

:::cards{path="ambiente" search="false"}
♻️ Separate waste collection **{percentuale_rd}%** (year {anno})
:::

::od-query{into="economia" sql="SELECT unita_locali AS unita_locali, addetti AS addetti, anno AS anno FROM imprese WHERE codice_istat = '{#comune}' ORDER BY anno DESC LIMIT 1"}

:::cards{path="economia" search="false"}
🏢 **{unita_locali}** active local units, **{addetti}** employees (year {anno})
:::

::od-query{into="voto" sql="SELECT affluenza AS affluenza, lista_vincente AS lista_vincente, percentuale_vincente AS percentuale_vincente FROM elezioni WHERE codice_istat = '{#comune}'"}

:::cards{path="voto" search="false"}
🗳️ Turnout **{affluenza}%** — top list **{lista_vincente}** ({percentuale_vincente}%) — 2022 general election
:::

::od-query{into="invalsiComune" sql="SELECT round(avg(punteggio_medio), 1) AS punteggio_medio, anno AS anno FROM invalsi WHERE codice_istat = '{#comune}' GROUP BY anno"}

:::cards{path="invalsiComune" search="false"}
📊 Average INVALSI test score **{punteggio_medio}** (year {anno}, municipalities above the student threshold)
:::

::od-query{into="veicoliComune" sql="SELECT autovetture AS autovetture, totale AS totale FROM aci_veicoli WHERE codice_istat = '{#comune}'"}

:::cards{path="veicoliComune" search="false"}
🚗 **{autovetture}** cars, **{totale}** registered vehicles in total (ACI)
:::

Income is the average per taxpayer (MEF, latest available year); age, foreign
residents and old-age index are ISTAT figures as of 1 January. The waste,
business, election, INVALSI and vehicle cards only appear if the municipality
has that data available (INVALSI and election data don't cover every
municipality; vehicles are counted where they are REGISTERED, not where their
owners live — large rental/leasing fleets concentrate in a few cities).

:::::

:::::page{title="The schools" icon="🏫"}

## The municipality's state schools

The list of state schools by level, from the ISTAT code entered on the first
page.

::od-query{into="scuoleComune" sql="SELECT nome AS nome, grado AS grado, indirizzo AS indirizzo FROM scuole WHERE codice_istat = '{#comune}' ORDER BY grado, nome" limit="200"}

:::table{path="scuoleComune" headers="School,Level,Address" pagesize="15"}
{nome} | {grado} | {indirizzo}
:::

:::::

:::::page{title="The map" icon="🗺️"}

## Average income by region

The same Italy seen from above: each region coloured by average declared
income. Hover for the value.

::od-query{into="mappa" sql="SELECT r.regione AS regione, r.geojson AS geojson, m.reddito AS reddito FROM istat_confini_regioni r JOIN (SELECT c.cod_reg, round(sum(x.reddito_complessivo) / sum(x.dichiaranti)) AS reddito FROM istat_confini_comuni c JOIN mef_redditi x ON x.codice_istat = c.codice_istat GROUP BY c.cod_reg) m ON m.cod_reg = r.cod_reg" limit="30"}

:::map{path="mappa" geojson="geojson" fill="reddito" height="30rem"}
**{regione}** — average income {reddito} €
:::

The colour runs from light (lower incomes) to dark (higher): the classic
North-South divide, in a map that draws itself from the data.

:::::

:::::page{title="Rankings" icon="🏆"}

## The municipalities with the highest income

Only municipalities above 10,000 inhabitants, so the small towns don't dominate.

::od-query{into="ricchi" sql="SELECT r.comune AS comune, r.sigla AS sigla, r.reddito_medio AS reddito_medio FROM mef_redditi r JOIN istat_popolazione p ON p.codice_istat = r.codice_istat WHERE p.popolazione >= 10000 ORDER BY r.reddito_medio DESC LIMIT 20" limit="20"}

::chart-bar{data="ricchi" x="comune" y="reddito_medio" height="20rem"}

:::table{path="ricchi" headers="Municipality,Prov,Average income €" pagesize="10"}
{comune} | {sigla} | {reddito_medio}
:::

:::::

---

The data are official and open: **population and indicators** from ISTAT
(demo.istat.it, CC BY 4.0), **IRPEF income** from the MEF — Department of
Finance (CC BY 3.0), **pharmacies** from the Ministry of Health and **schools**
from the MIUR (IODL 2.0), **separate waste collection** from ISPRA,
**businesses and employees** from ISTAT ASIA, **2022 general election
results** from the Ministry of the Interior, **INVALSI test results**
(INVALSI, CC BY 4.0 IT), **registered vehicles** from ACI — Autoritratto (CC
BY 4.0), **boundaries** from ISTAT. They join on their own through the
municipality's ISTAT code. None of your data leaves the device.