CatalogPublic data ›Transparency

Public tenders in the open

Italy's public tenders, in the clear: search by topic, see what towns and public bodies procure, find out who tenders the most. This is official ANAC data (the CIG lot codes, over 2.6 million lots) and OpenCUP (the entire universe of public investment), cross-referenced with the registry of public administrations and ISTAT population.

🔎 Search📍 By town📊 Who tenders🏆 Who wins💶 Cohesion funds🗂️ All projects

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

▶ Open the suite (6 micro apps)

or open it as a single app

tendersprocurementcontractsanacopencoesioneopencupcupeu fundspublic investmenttransparencymunicipalitiespublic spendingitaly

What it records

  • Search a tender by topic…
  • Town's ISTAT code

Composed of 6 micro apps

One job each, over the same data: every micro app reads and writes the shared data space “appalti-trasparenti-en” (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
# 🏛️ Public tenders in the open

Italy's public tenders, in the clear: search by topic, see what towns and
public bodies procure, find out who tenders the most. This is official ANAC
data (the CIG lot codes, over 2.6 million lots) and OpenCUP (the entire
universe of public investment), cross-referenced with the registry of
public administrations and ISTAT population.

:::::page{title="Search" icon="🔎"}

## Search a tender

Describe what you are after in your own words — "school maintenance", "vaccine
supply", "canteen service" — and find the relevant lots even without knowing
their codes.

::od-search{into="trovate" table="anac_cig" placeholder="Search a tender by topic…"}

:::cards{path="trovate" search="false"}
**{oggetto_gara}**
{amministrazione} · {provincia} — amount: {importo_lotto} €
:::

:::::

:::::page{title="By town" icon="📍"}

## Tenders in your town

Enter the town's **ISTAT code** (six digits, e.g. `058091` for Rome, `015146`
for Milan): see the most recent lots above a chosen threshold.

::input[comune]{value="058091" placeholder="Town's ISTAT code"}
::range[soglia]{min="0" max="500000" value="50000" legend="Minimum amount (€)"}

::od-query{into="gareComune" sql="SELECT oggetto_gara AS subject, importo_lotto AS amount, amministrazione AS body, data_pubblicazione AS date FROM anac_cig WHERE luogo_istat = '{#comune}' AND importo_lotto >= {#soglia} ORDER BY data_pubblicazione DESC LIMIT 40" limit="40"}

:::table{path="gareComune" headers="Subject,Amount €,Body,Date" pagesize="10"}
{subject} | {amount} | {body} | {date}
:::

:::::

:::::page{title="Who tenders" icon="📊"}

## The most active bodies

The administrations with the most tenders, by kind of body. The count is robust;
ANAC amounts contain source errors, so here we rank by **number of tenders**,
not totals.

::od-query{into="enti" sql="SELECT i.denominazione AS body, i.categoria AS kind, count(DISTINCT a.cig) AS tenders FROM anac_cig a JOIN indicepa i ON i.cf = a.cf_amministrazione_appaltante GROUP BY 1, 2 ORDER BY tenders DESC LIMIT 25" limit="25"}

:::table{path="enti" headers="Body,Kind,Tenders" pagesize="12"}
{body} | {kind} | {tenders}
:::

:::::

:::::page{title="Who wins" icon="🏆"}

## Who wins the tenders

The companies that win the most lots in the town set on the "By town" page
(change the ISTAT code there). These are the official ANAC **awardees**: it
closes the loop administration → tender → winner.

::od-query{into="vincitori" sql="SELECT a.denominazione AS impresa, count(*) AS lotti FROM anac_aggiudicatari a JOIN anac_cig g ON g.cig = a.cig WHERE g.luogo_istat = '{#comune}' AND a.denominazione IS NOT NULL GROUP BY 1 ORDER BY lotti DESC LIMIT 25" limit="25"}

::chart-bar{data="vincitori" x="impresa" y="lotti" height="18rem"}

:::table{path="vincitori" headers="Company,Lots won" pagesize="12"}
{impresa} | {lotti}
:::

As with the bodies, here we rank by **number of lots** won: the awarded amounts
contain ANAC source errors and should not be summed blindly.

:::::

:::::page{title="Cohesion funds" icon="💶"}

## Who spends, not just who tenders

Tenders are half the circle: the other half is the **projects financed** with
cohesion funds (EU + national Development and Cohesion Fund) in the town set
on the "By town" page — same ISTAT code.

::od-query{into="fondiComune" sql="SELECT count(*) AS progetti, round(sum(finanz_totale_pubblico)) AS totale FROM opencoesione WHERE codice_istat = '{#comune}'"}

:::cards{path="fondiComune" search="false"}
💶 **{progetti}** financed projects, **€{totale}** total
:::

::od-query{into="progettiComune" sql="SELECT titolo AS title, tema AS theme, finanz_totale_pubblico AS amount, stato_progetto AS status FROM opencoesione WHERE codice_istat = '{#comune}' ORDER BY finanz_totale_pubblico DESC LIMIT 30" limit="30"}

:::table{path="progettiComune" headers="Project,Theme,Amount €,Status" pagesize="10"}
{title} | {theme} | {amount} | {status}
:::

:::::

:::::page{title="All projects" icon="🗂️"}

## The whole portfolio, not just tenders and EU funds

Cohesion funds are one slice of public spending. **OpenCUP** covers ANY
public investment project since 2003 — public works, business incentives,
grants, services — regardless of who funds it: same town set on "By town".

::od-query{into="cupComune" sql="SELECT count(*) AS progetti, round(sum(costo_progetto)) AS totale FROM opencup WHERE codice_istat = '{#comune}'"}

:::cards{path="cupComune" search="false"}
🗂️ **{progetti}** CUP projects, **€{totale}** total cost
:::

::od-query{into="areeComune" sql="SELECT area_intervento AS area, count(*) AS n, round(sum(costo_progetto)) AS costo FROM opencup WHERE codice_istat = '{#comune}' AND area_intervento IS NOT NULL GROUP BY 1 ORDER BY costo DESC LIMIT 10"}

::chart-bar{data="areeComune" x="area" y="costo" height="18rem"}

::od-query{into="progettiCup" sql="SELECT descrizione AS description, natura_intervento AS nature, costo_progetto AS cost, stato_progetto AS status FROM opencup WHERE codice_istat = '{#comune}' ORDER BY costo_progetto DESC LIMIT 30" limit="30"}

:::table{path="progettiCup" headers="Description,Nature,Cost €,Status" pagesize="10"}
{description} | {nature} | {cost} | {status}
:::

:::::

---

The data are the **CIG** lots and the **awardees** of Italy's National
Anti-Corruption Authority (CC BY-SA 4.0 licence), the **cohesion fund
projects** from opencoesione.gov.it (CC BY 4.0), the entire **OpenCUP**
universe from DIPE (CC BY), the **IndicePA registry** and the **ISTAT
demographic balance** (CC BY 4.0). The sources join on their own: the tender
knows the body's tax code and its winner's code, the body its town, the town
its population, the CUP links both tenders and cohesion funds. None of your
data leaves the device.