Skip to content

Latest commit

 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ScrutinioLive

Webapp open source per lo scrutinio in diretta delle elezioni comunali: React sul frontend, API PHP + SQLite sul backend (gira su qualsiasi hosting PHP condiviso, nessun database MySQL da configurare).

📖 Guida utente — come si usa, dalla configurazione alla sera dello scrutinio, con tutti gli scenari.

🚀 Demo online — prova l'app senza installare nulla.

Per quali elezioni

L'app è pensata per le elezioni di sindaco e consiglio comunale nei comuni italiani fino a 15.000 abitanti (sistema maggioritario, art. 71 TUEL):

  • ogni candidato sindaco è collegato a una sola lista di candidati consiglieri;
  • l'elettore vota la lista e può esprimere preferenze per i consiglieri (una; due con doppia preferenza di genere nei comuni sopra i 5.000 abitanti);
  • è eletto sindaco chi prende più voti (maggioranza semplice, turno unico: il ballottaggio esiste solo in caso di parità assoluta);
  • alla lista del sindaco eletto vanno 2/3 dei seggi del consiglio, i restanti alle altre liste in proporzione (i candidati sindaco sconfitti entrano in consiglio se la loro lista conquista almeno un seggio);
  • i consiglieri sono eletti in base alle preferenze; a parità vale l'ordine di lista;
  • con una lista unica, l'elezione è valida solo se vota almeno il 50% degli aventi diritto e la lista ottiene almeno il 50% dei voti dei votanti.

La dashboard applica queste regole in tempo reale: banner del candidato in vantaggio (o eletto, a scrutinio concluso), proiezione del riparto seggi con i nomi dei consiglieri eletti, e indicatore del quorum nel caso di lista unica. La proiezione è indicativa: non sostituisce i verbali ufficiali e non gestisce i casi particolari (ricorsi, ricalcoli, surroghe).

Cosa fa

  • Dashboard pubblica (/) — risultati live per maxischermo o browser, aggiornati automaticamente ogni 4 secondi e divisi in tre schede alternabili durante la proiezione: Risultati (totali, affluenza, barra percentuale, tabella per sezione, banner del candidato in vantaggio), Preferenze (classifica dei candidati per lista) e Proiezione (vincitore in grande, riparto seggi con i nomi degli eletti, quorum lista unica). La scheda attiva è nell'URL (es. /#proiezione), comodo per aprire il maxischermo sulla vista giusta. Tema chiaro/scuro con switch (default: segue il sistema).
  • Pagina operatore (/s/<token>) — l'incaricato in ogni sezione, dal proprio smartphone, incrementa/decrementa i voti di lista, le preferenze ai candidati (nell'ordine di lista), bianche e nulle, e imposta elettori e votanti. Per le correzioni non serve premere +/− tante volte: un tocco sul numero (✎) apre la modifica diretta del totale. L'URL contiene un token segreto: solo chi riceve il link può modificare i dati della sua sezione.
  • Pannello admin (/admin) — protetto da password. Al primo avvio parte un wizard di configurazione: dati dell'elezione, seggi del consiglio (tendina con i casi di legge, o valore manuale per le Regioni a Statuto speciale), numero variabile di sezioni, liste con numero ufficiale / candidato sindaco / colore / simbolo, candidati consiglieri con ordine di lista, e infine i link (con QR code) da distribuire agli operatori. In seguito: modifica della configurazione, rigenerazione token, flag "scrutinio concluso" (la proiezione diventa risultato), cambio password, azzeramento voti o reset completo, export CSV.

Struttura

scrutiniolive/
├── api/         API REST in PHP (router unico in index.php, PDO SQLite)
├── data/        creata al primo avvio: database SQLite + simboli caricati (protetta)
├── frontend/    sorgente React (Vite + Tailwind)
├── dist/        build del frontend (generata da `npm run build`)
└── deploy/      template .htaccess per la root del sito

Sviluppo locale

Servono PHP ≥ 8.1 (con estensioni pdo_sqlite e sqlite3, di solito incluse) e Node ≥ 20.

Dalla cartella del progetto:

# terminale 1 — API
php -S 127.0.0.1:8010 api/index.php

# terminale 2 — frontend (proxy /api → :8010 già configurato)
cd frontend
npm install
npm run dev

Apri http://localhost:5173/admin e segui il wizard.

Nota — dati demo locali: non esiste una password "di default" dell'app; la password admin viene creata da te al primo avvio del wizard. Il database demo incluso in questo repo (data/elezioni.sqlite, creato durante i test) usa però la password segreta1. Per ripartire da zero con una password tua, elimina data/elezioni.sqlite e ricarica /admin.

Deploy su hosting condiviso (Apache)

  1. cd frontend && npm run build → genera dist/
  2. Carica sul server, nella document root del sito:
    • il contenuto di dist/ (index.html + assets/)
    • la cartella api/ così com'è
    • deploy/htaccess-root.txt rinominato in .htaccess
  3. La cartella data/ viene creata automaticamente accanto ad api/ al primo accesso e contiene già un .htaccess con Require all denied; se la crei a mano, copia dentro quel file. Verifica che PHP possa scriverci (permessi 755/775 a seconda dell'hosting).
  4. Apri https://tuosito.it/admin, imposta la password e configura l'elezione.

Layout finale sul server:

public_html/
├── .htaccess        (da deploy/htaccess-root.txt)
├── index.html       (da dist/)
├── assets/          (da dist/)
├── api/             (.htaccess + index.php + src/)
└── data/            (creata da PHP: elezioni.sqlite, symbols/)

Installazione in una sottocartella

Se l'app non sta nella radice del sito ma in una sottocartella (es. https://miosito.it/ScrutinioLive), segui gli stessi 4 passi qui sopra, con due sole differenze:

  • al passo 1 la build va fatta indicando il percorso della sottocartella — altrimenti la pagina resta bianca, perché gli asset vengono cercati nella radice del sito:

    cd frontend
    VITE_BASE=/ScrutinioLive/ npm run build
  • al passo 2 carichi tutto dentro la sottocartella anziché nella document root:

    public_html/
    └── ScrutinioLive/
        ├── .htaccess        (da deploy/htaccess-root.txt)
        ├── index.html + assets/   (da dist/)
        ├── api/
        └── data/            (creata da PHP)
    

L'app sarà su https://miosito.it/ScrutinioLive (admin: https://miosito.it/ScrutinioLive/admin). Rotte, chiamate API e link QR degli operatori si adattano da soli al percorso indicato nella build.

Consigli per la sera dello scrutinio:

  • Usa HTTPS: i token di sezione viaggiano nell'URL.
  • Fai una prova generale qualche giorno prima, poi "Strumenti → Azzera i voti".
  • Backup = scaricare il file data/elezioni.sqlite.

Nuova elezione

Due strade dal pannello, tab Strumenti:

  • Azzera i voti — tiene sezioni, liste ed elettori, azzera solo i conteggi. Ideale dopo la prova generale.
  • Azzera tutto — elimina sezioni, liste, candidati, voti, impostazioni e simboli (resta solo la password admin) e riapre il wizard di configurazione. Ideale per un'elezione completamente nuova.

In alternativa elimina data/elezioni.sqlite: riparte tutto da zero, password compresa.

Licenza e credits

ScrutinioLive è distribuito con licenza MIT: puoi usarlo, modificarlo e ridistribuirlo liberamente, anche per scopi commerciali, a condizione di mantenere la nota di copyright e la licenza (i credits) in ogni copia o porzione sostanziale del software.

Il progetto è nato per lo scrutinio live delle elezioni comunali di Alessano (LE) del 2021 ed è stato riscritto e generalizzato nel 2026 per qualsiasi comune italiano fino a 15.000 abitanti.

Se lo usi per lo spoglio del tuo comune, un saluto o una segnalazione fa sempre piacere!

About

Scrutinio in diretta per le elezioni comunali nei comuni italiani fino a 15.000 abitanti: gli operatori inseriscono i voti dallo smartphone, la dashboard mostra risultati, preferenze e proiezione seggi in tempo reale su maxischermo. React + PHP/SQLite, gira su qualsiasi hosting condiviso. Wizard di configurazione, licenza MIT.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages