Paperopoli is an imaginary municipality, but it is not just digital scenery. It has offices, services, taxes, deadlines, an institutional portal, and citizens who can log in with a digital identity. It also has an assistant that answers questions using the content published by the municipality, and it will offer services through which those same people can submit requests, track their cases, and pay.
The names, places, and data are made up.
The architecture is not.
The idea behind the project is fairly simple: if I am going to build a demo of the public administration, I want it to be fake only where it absolutely has to be.
I am not interested in drawing an "Log in with SPID" button that opens a fake authentication screen, nor in simulating a payment by changing a label from "to be paid" to "paid." Likewise, I don't want to build a site that only vaguely resembles a municipality's.
Instead, Paperopoli tries to bring together, in the same environment, the different pieces of a digital public service, using as its reference what the Italian PA has already defined: the Digital Administration Code (CAD), the Design Guidelines, the Designers Italia Municipalities Model, the Three-Year Plan for IT in the PA, the national digital identity systems, and the contracts of platforms such as pagoPA.
So this is not an attempt to invent my own model of a digital municipality. It is almost the opposite: I want to see what happens when those models are taken seriously and made to work together, rather than merely being cited in project documents.
The Design Guidelines for PA websites and digital services, issued under the CAD, invoke principles such as accessibility, usability, clarity, reliability, simplicity, quality, and interoperability. The Designers Italia Municipalities Model translates part of these principles into information architecture, components, templates, and flows designed specifically for municipal services.
The 2024-2026 Three-Year Plan, in its 2026 update, broadens the picture further by introducing or reaffirming concepts such as digital and mobile first, cloud first, API-first, digital identity only, user-centric, once only, openness, and data protection by design. These are not words I added after the fact to describe Paperopoli: they are the reference I use to decide how its pieces should communicate and which constraints they must respect.
A single place where information is born
The first piece is the portal, because that is where information is produced, organized, and made available to citizens.
Paperopoli uses a content architecture based on the Municipalities Model. The CMS manages services, offices, deadlines, costs, requirements, and the other content that a municipal editorial team normally publishes on the website. The knowledge used by the assistant comes from this same content.
This point is fundamental to me. If the editorial team changes a tax deadline on the website, there should not be a second procedure in which someone has to remember to update "the artificial intelligence data" as well. When the same information is maintained in two different repositories, sooner or later they diverge, even if the duplication seems harmless at first.
So Paperopoli starts from the opposite principle: the editorial team writes once, and the other components use that source.
The portal exposes the published content through an HTTP contract. An adapter transforms it into a structured corpus, and the MCP server makes it available to assistants.
In simplified form:

Every populated field of a service page can become a citable passage: "How to apply," "What you need," "Deadlines," "Costs," and so on. Each passage carries an identifier, a version, and a hash, making it possible not only to retrieve the information but also to identify and verify it.
On the database used by the demo, this currently produces 44 areas and 333 passages. The editorial team, however, doesn't need to know any of this: they simply keep publishing the website, while the transformation and exposure of the content are handled by the underlying technical layers.
The technical boundary is intentional too. The MCP server doesn't know the portal's database and doesn't care whether behind it there is SQLite, SQL Server, PostgreSQL, or a completely different CMS. The corpus speaks the language of the domain, not that of my tables.
A deadline is a deadline whatever platform stores it, just as a cost remains a cost and a way of accessing a service keeps its nature even if the site is rebuilt in PHP. That is exactly what the adapter is for: separating the information model from the concrete implementation of the CMS.
It is also consistent with a more general principle of the Three-Year Plan: systems that are interoperable by design, API-first, and components that don't need to know the internal implementation of other systems. This way, each part can evolve without forcing all the others to know the details of how it was built.
The assistant is not the source
When a citizen asks a question, the Paperopoli assistant doesn't look for the answer inside a huge prompt containing regulations, rates, and deadlines. The prompt defines the assistant's behavior, while the content comes from the municipality.
The MCP server exposes the tools through which the model retrieves the relevant passages and builds its answer on them. The model can change, and so can the vendor or the technology used to query it, but the source stays the same.
This is a distinction I consider important even beyond artificial intelligence: the data belongs to the organization, not to the vendor of the assistant that happens to be using it at that moment. The assistant should therefore be regarded as a component for access and interpretation, not the place where information is stored or certified.
Moreover, only published content enters the corpus. A draft in the CMS must not be able to accidentally become an answer to a citizen, because the editorial status of information is part of its meaning, not a minor detail.
And not everything is reduced to text. A fee is an amount, a deadline is a date, possibly associated with a validity period, and whether a service can be booked can be represented as a structured value. When information exists in that form, the corpus preserves it. I don't try to infer it from prose using regular expressions or other heuristics and then call it "certified data."
If a piece of information doesn't exist in the source, the gap must remain visible. It is not the assistant's job to automatically fill every gap, especially when the result might look more precise than it really is.
The same goes for time. A piece of information can be authentic, correctly versioned, and have a perfectly valid hash, yet still be outdated. A deadline of April 30 with no year is a great example: its provenance is certain, but its usefulness to the citizen is far less obvious.
Errors must also be semantically clear. If the corpus is not yet available, the tool returns an error rather than an empty list. An empty list could be interpreted by the model as "this information doesn't exist" and turn into a wrong answer delivered with great confidence.
These are just a few lines of code, but in public services a few lines of code can make the difference between a technical state and a statement addressed to a citizen. That is why anomalous cases must be designed with the same care as the normal paths.
Digital identity, not a screen that looks like it
Paperopoli doesn't stop at the informational part, because to use a personal service you need to know who the citizen is, and you need to do it through an identity mechanism that is more than a graphical representation.
The project therefore includes an OpenID Connect Federation Relying Party using the SPID/CIE profile, written in .NET. The flow implements authorization code with PKCE, a signed request object, private_key_jwt authentication, encrypted UserInfo, refresh, logout, trust chain resolution, and federation registration.
The test environment uses the official AgID Docker images for the Trust Anchor and the CIE OpenID Provider, and the flow is verified end-to-end against this infrastructure. In this way, the integration is not represented merely by a login screen but is exercised along the technical path envisioned by the test environment.
This doesn't mean Paperopoli is connected to the production SPID/CIE federation. It isn't. The code implements the profile and is tested against the test infrastructure, but it has never been validated against a real SPID provider. It would therefore be wrong to write otherwise or to present it as an integration ready for production.
Here too the distinction is deliberate. The Three-Year Plan speaks of digital identity only: digital identity shouldn't be an accessory bolted onto the interface at the end, but one of the components on which to build the service from the very beginning.
After authentication, the citizen is transferred to the services area through a signed SSO handoff. That is when the part I find most interesting about Paperopoli begins, because identity only gains value when it enables a concrete activity.
After login, there must be real services
Authenticating a citizen just to show their name in the top right corner isn't very useful. The goal of Paperopoli is to arrive at complete services: starting a request, entering the necessary data, attaching documents when needed, submitting it, tracking its status, and, where applicable, making a payment.
This part, too, won't be designed starting from freely invented screens. Designers Italia provides a specific model for municipal digital services, built by studying the main interactions between citizens and the administration: services in which you complete an obligation, submit a request, or receive a benefit. The model includes flows, prototypes, components, and templates to use as a reference.
The idea is to use that grammar in Paperopoli as well, not to mechanically reproduce every element, but to build services that are recognizable, consistent, and understandable for the people who use them.
The first cases will be deliberately ordinary: TARI, certificates, and requests that a municipality handles every day. Precisely because I don't want to prove that a spectacular demo can be built, I want to see whether the least spectacular part of digital transformation can be built well: a citizen who logs in, finds what they need, submits a request, and reaches the end without having to understand how the administration is organized internally.
Another principle of the Three-Year Plan comes into play here: once only. When the municipality already knows a piece of information and can legitimately reuse it, the architecture should be designed so as not to needlessly ask the citizen for it again. This doesn't just mean prefilling a field, but designing the service so that citizens don't have to repeat information that is already available and usable.
Paperopoli is the place where these principles can become code and, for that very reason, be put to the test. Their validity is demonstrated not by declaring them, but by observing what happens when they have to support a complete flow.
And if the service has to be paid for?
This is where another project comes in: PagoPaDevKit.
PagoPaDevKit is an independent open-source project that I built to develop and test pagoPA integrations locally, without connecting to the real Node and without moving any money. It is not a graphical clone of the Checkout and doesn't aim to simulate payment merely at the interface level: instead, it reproduces the surfaces a Creditor Entity goes through, using the official OpenAPI and WSDL contracts as a reference, including GPD Debt Positions v3, the nodeForPsp and paForNode SOAP services, receipts, reconciliation flows, the FlussoRiversamento, and ApiConfig.
The goal is for Paperopoli to use this infrastructure as the basis for its paid services. When, for example, a service generates a debt position, I don't want the code to simply insert a row into the demo's Pagamenti table. I want it to go through the same kind of contract a Creditor Entity would.
The position is therefore created and published through GPD, the citizen can enter the Checkout flow, the Node and the Creditor Entity exchange the expected calls, the payment produces a receipt, and reconciliation follows its own flow. PagoPaDevKit already implements this cycle in the local environment, including receipt retrieval and the handling of reconciliation flows.
Of course, it isn't pagoPA. It doesn't connect to the real platform, doesn't move money, and isn't meant for production: it is an independent development environment. But it is precisely this separation that makes it useful for Paperopoli.
I can build a complete municipal service without pretending that a payment has taken place and without needing a real platform. The application code is developed against contracts modeled on the official ones, while the local infrastructure takes care of impersonating the necessary counterparts.
So when Paperopoli shows a TARI position to be paid, the path shouldn't be:
click → fake screen → successful payment.
It should be a real application flow within the demo environment, with a position that is created, managed, produces an outcome, and can be linked to the subsequent states of the case.
To me this is a substantial difference, because it makes it possible to verify not only how the service looks, but also the behavior of the components that make it possible.
A municipality that lets itself be audited
Paperopoli doesn't just want to claim that it uses the Municipalities Model: it also wants to be able to verify how closely it actually follows it.
The project therefore also integrates pa-website-validator-ng. The portal can launch a scan and display the results produced by the validator, making visible not only where it complies but also the areas where the project departs from the model.
Not every check has to pass. There is a page called "Declared deviations" that collects what Paperopoli doesn't comply with and explains why. Some deviations stem from deliberate choices of the demo, while others derive from the very simple fact that Paperopoli doesn't exist.
An imaginary municipality can't have a real institutional domain and can't file its accessibility statement with AgID. I don't try to hide it, because this too is part of an accurate description of the environment.
If the goal is to build a system based on verifiable sources and behaviors, the same rule must apply to the project itself. Saying what is missing is almost as important as showing what is there, especially when you want a demo to be read as a lab and not as an implicit promise of compliance.
Not a new PA architecture
The thing I most want to avoid is presenting Paperopoli as "my model of a digital municipality." It isn't, and it doesn't want to be.
The whole point is to use what already exists. The CAD provides the framework, while the Design Guidelines establish principles and rules for PA websites and digital services. Designers Italia offers municipalities a model built around citizens' needs, with information architecture, interfaces, code, and service models.
The Three-Year Plan indicates the architectural direction through concepts such as API-first, digital identity, user centricity, once only, openness, interoperability, and data protection by design. The 2026 update also reaffirms interoperability, simplification, measurability of results, and user centricity of digital public services.
SPID and CIE have their own protocols and rules, while pagoPA has its own contracts. Paperopoli tries to stay within these tracks, without replacing them with an architecture invented specifically for the demo.
It won't always succeed. When it doesn't, though, the deviation must be identifiable, describable, and, if possible, justified. That is why I prefer to call it a lab rather than a product: a place where existing rules are brought into relation with each other and subjected to practical verification.
So what is Paperopoli for?
It serves to make the architecture visible, especially the part that tends to disappear in diagrams.
In a diagram everything is easy: the citizen logs in with SPID, the service retrieves the data, a pagoPA position is generated, the user pays, the system updates the case, and the assistant helps when needed. Six rectangles and a few arrows.
When you try to build them, though, every arrow becomes a contract. You have to ask who owns the data, who updates it, how you know it is published, and how you tell a draft apart. You have to decide how to represent a deadline, how to truly authenticate the citizen, and how to pass that identity on to another service. You also need to figure out how a debt position is created, how its outcome is received, and how to prove that the site you built really follows the model you claim to have followed.
Paperopoli exists for this: to turn those arrows into something that runs, that can be observed, and that, when it doesn't work, lets you understand where the problem is.
For those who work in a municipality, it can be a way to see concretely what should be behind some words that recur constantly in digital transformation projects. For developers, it can become an environment in which to try integrations without having to replace every national platform with an if (demo). For me it is above all a way of testing a very simple idea: we don't need to reinvent, every time, how the digital PA should work.
Most of the rules, models, and contracts already exist. The hard part is making them work together, respecting each one's boundaries and making explicit the responsibilities that in theoretical projects often remain implicit.
Paperopoli tries to do this in a place where you can experiment, make mistakes, change code, and start over without involving a real citizen.
The municipality is fake, the citizens are fake, and the money is fake, but the way I am trying to make these pieces communicate is deliberately as un-fake as possible.
getElementById👉 Paperopoli: https://paperopoli.derrigo.it/
👉 Code: https://github.com/fderrigo/DuckburgSmartCity
👉 PagoPaDevKit: https://github.com/fderrigo/PagoPaDevKit