How I took two municipal Drupal sites through PNRR measure 1.4.1, with services on Maggioli
Deep dive into the Municipal sites for PNRR measure 1.4.1 project
With I.T.Svil (opens in a new tab) I took two municipal sites built in Drupal 9 through the assessment for measure 1.4.1 of Italy's Recovery and Resilience Plan (PNRR), «Citizen experience: improvement of the quality and usability of digital public services». The work on the two municipalities took a year, and we closed the single sign-on part in 2025. The theme covered part of the conformity criteria; the rest was work on content, on services and on how citizens log in, and that is what this article is about. The names of the two municipalities stay out; the service platform was Maggioli (opens in a new tab)'s.
What does measure 1.4.1 ask of a municipal website?
Measure 1.4.1 funds Italian municipalities that adopt the municipal site model designed by Designers Italia, and the money arrives after an assessment: a check of the model's conformity criteria. The criteria are grouped in families, labelled C.SI.1.x and so on: look and structure of the site, features such as appointment booking and reporting a service failure, cookie, accessibility and privacy rules, performance measured with Lighthouse, and security of domain and protocol.
Many criteria go into the detail of the structure. The first-level menu entries are all there, in the exact order of the model (C.SI.1.6), second-level page titles follow its vocabulary (C.SI.1.7), and the topics that classify content come from the European vocabulary EuroVoc (C.SI.1.5). Every service page shows the mandatory items in the given order, including the administration's maximum response time (C.SI.1.3). On a site built before the model, criteria like these touch almost every page.
To check the criteria automatically there is the PA Website Validator, published by Developers Italia. An automatic tool checks the form, though: that a service page has certain fields, that the menu has certain entries. If the content behind those fields is empty or wrong, the site passes the check and stays useless to the people using it.
Is a Drupal theme for the municipal model enough?
The theme covers the visual side, and the content still has to be built. On both sites the base was the contrib theme bootstrap_italia, version 2.8, with a subtheme of ours adding the styles of the municipal model. On that base the visual criteria are met almost by themselves: the Titillium Web, Lora and Roboto Mono fonts (C.SI.1.1), the Bootstrap Italia library on every page (C.SI.1.2), the page structure.
The content criteria depend instead on how the site is built underneath: which content types exist, with which fields, which controlled vocabularies. On both sites that structure differed from the model's, and that is where the real work started.
How do you migrate a municipality's content to the model's content types?
I rebuilt the content structure from scratch and migrated the existing content onto it with a custom script. The municipal model defines the types: services, offices, documents, news, events, places, people in the administration, each with its own fields and links. I created the matching content types and vocabularies in Drupal, then the script reorganised the existing content onto the new types.
The starting structure of both sites was far from the model, and rewiring it was the complex part. Content types, fields, vocabularies, the menu tree and the links between pages all changed together: a service points to the office in charge, an event to the place where it is held, a document to the service it belongs to. With a script the sorting rules live in one place, and you fix them and run it again until every item lands where it should.
The migration was the least visible part and the one with the most decisions. An old article could become a news item, a document or an office page depending on what it told, and that choice is about content before it is about technology: so the migration went hand in hand with training the editorial teams, which I cover further down.
How do the Maggioli platform's services reach the site?
The two municipalities' online services lived on the Maggioli platform: pagoPA payments, applications and case files, appointment booking, which the model requires as a feature of the site (C.SI.2.1). The municipal model asks that citizens find them on the institutional site, each with its own page, and not only on a separate portal.
We exposed them as a mirror: every service has its page on the municipality's site, and the actual action, paying, submitting an application, booking, leads to the Maggioli platform.
Maggioli itself syncs and exposes the service pages through its APIs, and the municipality's site reads them and presents them with the structure the model asks for. The service catalogue stays in one place, on the platform that delivers the services, and a service updated there is updated on the site too.
The citizen starts on the municipality's site and reaches the service without searching elsewhere. For that step to avoid a second login, the two sites had to recognise the same user.
Why build single sign-on when the measure does not require it?
Because without single sign-on citizens log in twice, and without single logout they stay logged in on one of the two sites without knowing it. Maggioli's public specification for integrating the institutional site with its online service desk says so plainly: single sign-on is not a requirement of measure 1.4.1, but if you turn it on you need single logout too, because a session left open on a shared computer is a risk for personal data.
We built both, in both directions: whoever logs in on the municipality's site is already logged in on the Maggioli platform, and the other way round; whoever logs out of one is logged out of the other, through a remote logout at the identity provider. It was the most demanding part of the project and took us much of 2025, because of the number of systems that had to talk to each other. The work itself ran smoothly: Maggioli's documentation on the API integration was clear and thorough, and every step of the flow had a written reference to follow.
Why a Drupal module written from scratch?
The existing modules solve a simpler case than ours. For SPID on Drupal there are spid, which has no supported release today, and samlauth, a generic and well-maintained SAML module. Both assume that Drupal talks directly to the identity provider.
In our case Drupal sat at the end of a chain: SPID and CIE were handled by an external authentication intermediary, the flow went through Shibboleth, and the session had to hold on the Maggioli platform as well. The module I wrote does one thing: it receives the identity at the end of the chain, finds or creates the Drupal user and opens the session. The site's personal area is reached through a dedicated path, /auth-service/login, which is the module's front door.
Why Shibboleth in a separate container?
To keep the SAML Service Provider out of direct reach from the internet. Shibboleth is the component that concludes the SAML exchange and produces a session, with its own cookie. We put it in a dedicated container, with Traefik in front of everything routing the traffic: authentication requests reach the container, and only after authentication do they move on to Drupal.
As a result the session cookie generated by Shibboleth can be read only inside the container. Drupal receives an identity that has already been verified, and the Service Provider is not an exposed service to reach and attack directly.
How does a SPID or CIE identity reach the Drupal user?
Through a single piece of data: the tax code, the Italian codice fiscale. When a citizen logs in with SPID or the electronic identity card, the intermediary verifies the identity, Shibboleth completes the flow and the module receives the tax code. With it the module finds the matching Drupal user, or creates one at the first login.
The tax code was the only information the site needed to recognise the user. The other data a digital identity can carry, name, email, address, was of little use to the municipality's site, and every piece of data the site keeps out is one less to protect.
How do you meet the performance criterion?
Criterion C.SI.4.1 measures pages with Lighthouse, in mobile mode, and asks for a score of at least 50 on every page of the site. Below that threshold the municipality publishes a «site improvement plan», listing the planned action for each item that drags performance down and the time needed to carry it out.
The theme gives you a site that conforms in its look, and speed needs its own work. On both sites we did tuning and worked on caching, so that pages are served ready-made. The criterion covers every page, so it covers the news and event listings too, and the service pages that read their data from the Maggioli platform.
What does a municipality need after the assessment?
An editorial team that knows how to use the site. A site that matches the model on assessment day stops matching it if, a year later, the service pages are stale and events end up among the news. That is why we took the administrations through several training stages: how to create content of the right type, how to write a service page, and above all how to handle an event, with its dates, its venue and the link to the service or office organising it.
The staff who followed the training were skilled, and the sessions ran without a hitch: all the time went on the rules of the model, meaning which type to use, which fields to fill in and how to link a piece of content to the others.
What changes for a project starting today?
Two things, both documented. Since the 28 March 2025 revision of Maggioli's specification, logging in with the CIE on the platform goes through OpenID Connect and no longer through SAML2: a new bridge has to be designed on that flow. And Drupal 9 reached end of life on 1 November 2023: a project starting today starts from Drupal 10 or 11, with a version of bootstrap_italia that supports them.
Sources
All sources were checked on 1 October 2026.
- Conformity criteria of the municipal site model (opens in a new tab), Designers Italia. Primary source.
- PA Website Validator NG (opens in a new tab), Developers Italia. Primary source.
- Integrating the online service desk with the institutional site, rev. 6 (PDF) (opens in a new tab), Maggioli, 28/03/2025: single sign-on not required for 1.4.1, single logout, CIE over OpenID Connect. Primary source.
- Bootstrap Italia for Drupal (opens in a new tab), drupal.org. Primary source.
spidmodule (opens in a new tab) andsamlauthmodule (opens in a new tab), drupal.org. Primary source.- Drupal 9 end of life (opens in a new tab), drupal.org. Primary source.
- The work on the two sites with I.T.Svil, with the single sign-on part closed in 2025. Author's experience.
This text was translated by AI.
How was AI used?
Translated from the Italian original with AI assistance, then read and corrected by a person, who holds editorial responsibility.