Dal dato all'autonomia reale. Una banca dati intelligente che collega i beneficiari in uscita dai progetti SAI ad alloggi disponibili e opportunità di lavoro sul territorio.
FAMI INTEGRA nasce da un'intuizione di Giovanni Campese, ex sindaco di Monteleone di Puglia, uno dei borghi dell'Appennino Dauno che ha fatto dell'accoglienza una leva concreta di rigenerazione territoriale.
L'osservazione di partenza è semplice ma decisiva: il momento più fragile del percorso di integrazione non è l'accoglienza, è l'uscita. Quando un beneficiario esce da un progetto SAI, le informazioni su di lui — competenze, nucleo familiare, comune di riferimento, data di uscita — sono già tutte disponibili. Ciò che manca è uno strumento che le metta in relazione con le opportunità reali del territorio: case sfitte, aziende che cercano personale, servizi welfare attivabili.
La piattaforma è stata ideata, avviata e sviluppata da paki81 sulla base di interlocuzioni con il Comune di Monteleone di Puglia e il Project Manager, parallelamente allo svolgimento dell'incarico professionale di counselor nel progetto. L'obiettivo: uno strumento operativo per migliorare l'efficienza dei servizi degli Sportelli Casa, Lavoro e Welfare verso i beneficiari e agevolare la co-progettazione dei Piani Individuali di Inserimento Socio-Economico. Non un semplice archivio, ma un motore che suggerisce abbinamenti, li misura con un punteggio e li traccia nel tempo.
FAMI INTEGRA è pensata per essere riutilizzata liberamente da enti locali, cooperative sociali ed enti gestori: l'obiettivo è che nessuno debba ripartire da zero.
Per questo la piattaforma è interamente personalizzabile — nome, logo, ente, testi dei documenti, server email — direttamente dal pannello Strumenti, senza toccare una riga di codice.
| Funzionalità | Descrizione | |
|---|---|---|
| 🏠 | Matching Alloggi | Suggerimenti automatici con score 0-100 su vani, comune, disponibilità e tipologia |
| 💼 | Matching Lavoro | Abbinamento beneficiario-azienda su competenze, comune, tirocinio e orario |
| 👥 | Anagrafica Beneficiari | Schede complete, nucleo familiare, competenze, date di uscita SAI |
| 🗺️ | Geolocalizzazione | Mappe Leaflet con geocoding automatico degli indirizzi |
| 📸 | Galleria Foto | Documentazione fotografica degli alloggi |
| 📋 | Registro Note | Diario di bordo per beneficiari, alloggi e aziende |
| 🤝 | Servizi Welfare | Consultazioni welfare con generazione PDF personalizzata |
| 📊 | Dashboard & Report | Statistiche in tempo reale, uscite imminenti, matching recenti |
| 📥 | Import / Export | Excel in ingresso, XLSX e CSV in uscita |
| 🔐 | RBAC + Audit Log | 5 ruoli con permessi granulari e tracciamento completo delle azioni |
| 🛠️ | Strumenti | Backup DB, personalizzazione branding, configurazione SMTP |
| Livello | Tecnologia |
|---|---|
| Backend | Node.js + Express, JWT auth, RBAC |
| Frontend | Next.js 14 (App Router) + Tailwind CSS + shadcn/ui |
| Database | MariaDB (utf8mb4) |
| Mappe | Leaflet + geocoding Nominatim |
| Generazione server-side con branding dinamico | |
| Nodemailer con configurazione SMTP da pannello | |
| Process Manager | PM2 (cluster mode) |
node -v # >= 18
mysql --version # MariaDB 10.4+
npm i -g pm2mysql -e "CREATE DATABASE fami_integra CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
mysql fami_integra < backend/migrations/001_schema.sql
mysql fami_integra < backend/migrations/002_seed.sql
mysql fami_integra < backend/migrations/003_welfare_consultazioni.sqlcd backend
npm install
npm startContenuto minimo di backend/.env:
PORT=4000
DB_HOST=localhost
DB_USER=root
DB_PASSWORD=
DB_NAME=fami_integra
JWT_SECRET=cambia-questa-stringa-con-una-casuale-molto-lunga
FRONTEND_URL=http://localhost:3000💡 Le credenziali SMTP non servono nel
.env: si configurano dall'interfaccia in Strumenti → Server Email (SMTP).
cd frontend
npm install
echo "NEXT_PUBLIC_API_URL=http://localhost:4000/api" > .env.local
npm run build
npm startpm2 start ecosystem.config.js
pm2 save
pm2 startupApri il browser su http://localhost:3000 e accedi con le credenziali di default.
| Ruolo | Password | |
|---|---|---|
| SuperAdmin | admin@fami-integra.it | admin123 |
| Tutor | tutor.casa@fami-integra.it | admin123 |
| Counselor | counselor.lavoro@fami-integra.it | admin123 |
| Viewer | viewer@fami-integra.it | admin123 |
🔴 Prima cosa da fare in produzione: cambiare tutte le password e sostituire il
JWT_SECRET.
Accedi come SuperAdmin e apri Strumenti. Tutto quello che segue è modificabile dall'interfaccia.
| Campo | Dove compare |
|---|---|
| Logo | Login, sidebar, intestazione dei PDF |
| Nome App | Titolo del login, header e oggetto delle email |
| Slogan | Sottotitolo del login e delle email |
| Organizzazione | Footer delle email |
| URL Portale | Link nelle email di notifica |
Il logo si carica con Carica Logo (PNG o JPG) e si può rimuovere con Rimuovi per tornare a quello di default.
| Campo | Esempio |
|---|---|
| Ente | COMUNE DI ... |
| Progetto | PROGETTO "INTEGRA_Azioni" |
| Sottotitolo | Descrizione estesa del progetto |
| Fondo | FONDO ASILO MIGRAZIONE E INTEGRAZIONE (FAMI) 2021-2027 |
| CUP | Codice unico di progetto |
Host, porta, connessione sicura, utente, password e indirizzo mittente si impostano da Strumenti → Server Email (SMTP).
| Provider | Host | Porta | Sicura |
|---|---|---|---|
| Gmail | smtp.gmail.com |
587 |
No (STARTTLS) |
| Outlook / M365 | smtp.office365.com |
587 |
No (STARTTLS) |
| SMTP generico SSL | host del provider | 465 |
Sì (SSL) |
⚠️ Con Gmail serve una App Password generata dall'account Google, non la password di login.
| Ruolo | Dashboard | Beneficiari | Alloggi | Aziende | Matching | Import | Utenti | Strumenti |
|---|---|---|---|---|---|---|---|---|
| SuperAdmin | ✅ | CRUD + Delete | CRUD + Delete | CRUD + Delete | Tutti | ✅ | CRUD | ✅ |
| Admin | ✅ | CRUD + Delete | CRUD + Delete | CRUD + Delete | Tutti | ✅ | Lettura | ❌ |
| Tutor | ✅ | CRUD (propri) | CRUD | Lettura | Alloggi | ❌ | ❌ | ❌ |
| Counselor | ✅ | CRUD (propri) | Lettura | CRUD | Lavoro | ❌ | ❌ | ❌ |
| Viewer | ✅ | Lettura | Lettura | Lettura | ❌ | ❌ | ❌ | ❌ |
Il motore assegna a ogni abbinamento un punteggio da 0 a 100: più alto, più l'abbinamento è coerente.
| Criterio | Punti | Logica |
|---|---|---|
| Vani | +40 | N_Vani >= N_Componenti × 0.5 (un vano ogni due persone) |
| Comune | +30 | Stesso comune del beneficiario |
| Disponibilità | +20 | Alloggio libero prima della data di uscita dal SAI |
| Tipologia | +10 | Adeguata al nucleo (es. appartamento per famiglie) |
| Criterio | Punti | Logica |
|---|---|---|
| Competenze | +30 | Match tra competenze del beneficiario e mansione richiesta |
| Comune | +30 | Stesso comune |
| Disponibilità | +20 | Azienda attualmente disponibile |
| Tirocinio | +10 | Bonus se l'azienda accetta tirocini |
| Orario | +10 | Full-time preferito |
fami-integra/
├── backend/
│ ├── src/
│ │ ├── index.js # Server Express
│ │ ├── models/db.js # Pool connessione MariaDB
│ │ ├── middleware/auth.js # JWT + RBAC
│ │ ├── routes/
│ │ │ ├── auth.js # Login, me, reset password
│ │ │ ├── beneficiari.js # CRUD beneficiari
│ │ │ ├── alloggi.js # CRUD alloggi
│ │ │ ├── aziende.js # CRUD aziende
│ │ │ ├── comuni.js # Anagrafica comuni
│ │ │ ├── comuniProgetto.js # Comuni aderenti al progetto
│ │ │ ├── matching.js # Suggerimenti + creazione matching
│ │ │ ├── dashboard.js # Statistiche
│ │ │ ├── utenti.js # Gestione utenti
│ │ │ ├── importExport.js # Import Excel / Export CSV-XLSX
│ │ │ ├── audit.js # Audit log
│ │ │ ├── contratti.js # Monitoraggio contratti
│ │ │ ├── fotoAlloggi.js # Galleria fotografica
│ │ │ ├── geocoding.js # Geocoding indirizzi
│ │ │ ├── registroNote.js # Registro note
│ │ │ ├── serviziWelfare.js # Catalogo servizi welfare
│ │ │ ├── consultazioniWelfare.js # Consultazioni + PDF
│ │ │ ├── config.js # Configurazione e branding
│ │ │ └── strumenti.js # Backup, logo, config protetta
│ │ ├── services/
│ │ │ └── matchingEngine.js # Algoritmo di matching
│ │ └── utils/
│ │ ├── auditLog.js # Logger audit
│ │ └── mailer.js # Invio email + template
│ ├── migrations/
│ │ ├── 001_schema.sql
│ │ ├── 002_seed.sql
│ │ └── 003_welfare_consultazioni.sql
│ └── tests/
│ └── matching.test.js # Test motore di matching
├── frontend/
│ └── src/
│ ├── app/
│ │ ├── login/
│ │ ├── forgot-password/
│ │ ├── reset-password/
│ │ └── (protected)/
│ │ ├── dashboard/
│ │ ├── beneficiari/
│ │ ├── alloggi/
│ │ ├── aziende/
│ │ ├── comuni/
│ │ ├── matching/
│ │ ├── servizi-welfare/
│ │ ├── report/
│ │ ├── import/
│ │ ├── utenti/
│ │ └── strumenti/
│ ├── components/
│ │ ├── Sidebar.tsx
│ │ ├── MappaLeaflet.tsx
│ │ ├── GalleriaFoto.tsx
│ │ ├── RegistroNote.tsx
│ │ └── ui/
│ ├── contexts/AuthContext.tsx
│ └── lib/api.ts
├── ecosystem.config.js
└── README.md
- Vai su Import / Export
- Scegli la tabella di destinazione (beneficiari, alloggi, aziende)
- Carica il file
.xlsx: le intestazioni delle colonne devono corrispondere ai campi della tabella - Verifica il report di importazione (righe inserite / scartate)
- Apri la scheda di un beneficiario
- Vai su Matching e scegli Alloggi o Lavoro
- La piattaforma mostra i candidati ordinati per punteggio
- Clicca Crea matching sull'opzione scelta: l'abbinamento viene registrato e tracciato
- Servizi Welfare → Consultazioni → Nuova
- Compila la consultazione e salva
- Dalla scheda della consultazione usa Scarica PDF
- L'intestazione del PDF usa automaticamente logo e testi impostati in Strumenti
- Strumenti → Backup
- Clicca Crea backup: viene generato un dump scaricabile
- I backup precedenti restano elencati e scaricabili in qualsiasi momento
- Dalla pagina di login clicca Password dimenticata?
- Inserisci l'email dell'account
- Arriva un'email con un link valido 1 ora
Se l'invio restituisce errore, controlla la configurazione in Strumenti → Server Email (SMTP).
pm2 list # Stato dei servizi
pm2 restart fami-backend fami-frontend # Riavvio
pm2 logs fami-backend # Log in tempo reale
pm2 stop fami-backend fami-frontend # Stop
pm2 save # Salva configurazione# Test del motore di matching
cd backend && npx jest --coverage
# Rebuild frontend dopo modifiche
cd frontend && npm run build && pm2 restart fami-frontend
# Reimportare lo schema del DB
mysql fami_integra < backend/migrations/001_schema.sqlTutte le rotte protette richiedono l'header Authorization: Bearer <token>.
| Metodo | Endpoint | Descrizione |
|---|---|---|
POST |
/api/auth/login |
Login |
GET |
/api/auth/me |
Utente corrente |
POST |
/api/auth/change-password |
Cambio password |
POST |
/api/auth/forgot-password |
Richiesta reset |
POST |
/api/auth/reset-password |
Conferma reset |
| Metodo | Endpoint |
|---|---|
GET / POST |
/api/beneficiari |
GET / PUT / DELETE |
/api/beneficiari/:id |
GET / POST |
/api/alloggi |
GET / PUT / DELETE |
/api/alloggi/:id |
GET / POST |
/api/aziende |
GET / PUT / DELETE |
/api/aziende/:id |
| Metodo | Endpoint | Descrizione |
|---|---|---|
GET |
/api/matching/suggerisci-alloggi/:idBen |
Suggerimenti alloggi |
GET |
/api/matching/suggerisci-aziende/:idBen |
Suggerimenti aziende |
POST |
/api/matching/alloggi |
Crea matching alloggio |
POST |
/api/matching/lavoro |
Crea matching lavoro |
| Metodo | Endpoint |
|---|---|
GET |
/api/dashboard/stats |
GET |
/api/dashboard/beneficiari-per-comune |
GET |
/api/dashboard/uscite-prossime |
GET |
/api/dashboard/matching-recenti |
| Metodo | Endpoint | Note |
|---|---|---|
POST |
/api/import/beneficiari |
multipart/form-data |
POST |
/api/import/alloggi |
multipart/form-data |
POST |
/api/import/aziende |
multipart/form-data |
GET |
/api/import/export/:tabella |
XLSX |
GET |
/api/import/export-csv/:tabella |
CSV |
| Metodo | Endpoint | Accesso |
|---|---|---|
GET |
/api/config |
Pubblico |
GET |
/api/config/logo |
Pubblico |
GET / PUT |
/api/strumenti/config |
SuperAdmin |
POST / DELETE |
/api/strumenti/logo |
SuperAdmin |
| Sintomo | Causa probabile | Soluzione |
|---|---|---|
| 502 Bad Gateway | Backend non avviato | pm2 restart fami-backend e controlla pm2 logs fami-backend |
| 500 su reset password | Credenziali SMTP errate | Verifica Strumenti → Server Email; con Gmail serve una App Password |
| Logo non aggiornato | Cache del browser | Ricarica con Ctrl+Shift+R |
| Mappa vuota | Indirizzi non geocodificati | Salva di nuovo la scheda per rilanciare il geocoding |
| Login rifiutato | Password cambiata o token scaduto | Usa Password dimenticata? |
- Intuizione: Giovanni Campese, ex sindaco di Monteleone di Puglia
- Sviluppo: paki81
Realizzato nell'ambito del Fondo Asilo Migrazione e Integrazione (FAMI) 2021-2027
Questo progetto è distribuito con licenza GNU Affero General Public License v3.0 (AGPL-3.0).
Chiunque può usare, modificare e distribuire il software, ma deve rendere pubblico il codice sorgente — anche se il software viene offerto come servizio web (SaaS).
Vedi il file LICENSE per il testo completo della licenza.