README.it.md
Rama main · réplica de lectura del repositorio original.
<p align="center">
<img src="docs/img/social-preview.png" alt="IsItDown" width="880">
</p>
[](https://github.com/DevManfre/isitdown/releases)
[](.github/workflows/ci.yml)
[](LICENSE)
[](.nvmrc)
[](tsconfig.json)
[](docs/development.it.md#92-stack-tecnologico)
[](docs/development.it.md#92-stack-tecnologico)
[](docs/docker.it.md#4-docker)
[](docs/theming.it.md#82-localizzazione)
[English](README.md) · **Italiano**
Monitoraggio self-hosted e containerizzato delle status page **degli altri**.
Interroga le status page pubbliche dei provider da cui dipendi — GitHub, Cloudflare,
Anthropic, npm, qualunque cosa giri su Atlassian Statuspage — e ti avvisa quando uno
di loro cambia stato.
Esiste perché un singolo sviluppatore o un piccolo team abbia un preavviso sui
problemi upstream senza tenere aperte cinque dashboard di stato. Notifica sulle
*transizioni*, mai a ogni poll: una settimana tranquilla è una settimana silenziosa.
Due edizioni dallo stesso codice: **Light** (solo polling e notifiche, nessun
server) e **UI** (lo stesso core più una dashboard locale, configurabile a runtime).
## Indice
In questa pagina: [1. Cosa fa](#1-cosa-fa) · [2. Avvio rapido](#2-avvio-rapido) ·
[10. Client da terminale](#10-client-da-terminale) · [11. Roadmap](#11-roadmap) · [12. Layout dei branch e politica di merge](#12-layout-dei-branch-e-politica-di-merge)
Il manuale, un file per sezione:
- [3. Configurazione](docs/configuration.it.md) — `config.yml`, impostazioni a runtime, segreti, provider, canali, instradamento, politica di consegna
- [4. Docker](docs/docker.it.md) — immagini, profili Compose, volumi e probe, Kubernetes, outpost
- [5. Verificare un deployment](docs/verifying.it.md) — controlli rapidi, la dashboard, una notifica end-to-end, risoluzione dei problemi
- [6. API HTTP](docs/api.it.md) — ogni route, le metriche, gli aggiornamenti live, i badge
- [7. Come funziona](docs/how-it-works.it.md) — flusso dei dati, componenti, quando scatta una notifica, resilienza, consenso degli outpost
- [8. Tema e localizzazione](docs/theming.it.md) — temi, le sei lingue della dashboard, accessibilità
- [9. Sviluppo](docs/development.it.md) — struttura, stack tecnico, sviluppo live, test, rilasci
- [10. Client da terminale](docs/cli.it.md) — `isitdown watch`, una vista di sola lettura della flotta per il terminale, `isitdown discover`, una prima flotta letta dai file di un progetto, e `isitdown import`, una flotta portata da Uptime Kuma, Gatus, Statping o StatusGator
Ogni pagina ha accanto la sua gemella inglese (`docs/<nome>.md`).
## 1. Cosa fa
Ogni pochi minuti IsItDown recupera la status page di ogni provider, normalizza
la risposta, la confronta con quella precedente e invia un messaggio solo se è
cambiato qualcosa davvero.
```
GitHub operational ████████████████████████████ 99.98%
Cloudflare degraded ███████████████▁▁▁▁▁████████ 99.61% ← ti arriva un messaggio
Anthropic operational ████████████████████████████ 99.93%
```
### Principi di base
- **Nessuna dipendenza esterna a runtime.** Nessun database server, nessun broker,
nessun account cloud. A questa scala bastano un file JSON o un SQLite embedded.
L'unica eccezione è opt-in: gli outpost ([Docker §4.7](docs/docker.it.md#47-outpost--un-secondo-punto-di-vista-per-le-sonde))
sono container che gestisci tu per una seconda lettura delle sonde, e senza
nessuno configurato non se ne cerca nessuno.
- **Guidato dalla configurazione.** Aggiungere un provider non significa mai
toccare codice: una voce in `config.yml` (Light) o un dialog nella dashboard (UI).
- **Notifiche idempotenti.** Notificano solo le *transizioni* di stato: operational
→ degraded, degraded → outage, outage → resolved. Un restart non notifica nulla.
- **Indipendente dal provider.** La maggior parte gira su Atlassian Statuspage e non
richiede codice; per tutto il resto serve un piccolo adapter.
- **Segreti solo dall'ambiente.** Un token si legge da una variabile d'ambiente e
non viene mai scritto in un file di configurazione, in un database, in una
risposta API o in una riga di log. L'edizione UI può salvarne uno in un file
`0600` accanto al database, sempre come variabile, così la dashboard imposta
una credenziale senza riavvii.
### Le due edizioni
| | Light | UI |
|---|---|---|
| Immagine | `ghcr.io/devmanfre/isitdown:light-latest` | `…:ui-latest` (costruita `FROM` light) |
| Poller · Adapter · Diff Engine · Notifier | condivisi | condivisi |
| Configurazione | `config.yml`, riletto a ogni ciclo | SQLite, modificata dalla dashboard |
| State store | file JSON, scritture atomiche | SQLite (contiene anche la cronologia) |
| Server HTTP | assente | Express sulla :3000 |
| Cronologia uptime e grafici | — | viste 7/30/90 giorni, più un calendario annuale per provider |
| Tema | — | chiaro / scuro / sistema, più varianti ad alto contrasto, per daltonici e OLED e un accento personalizzato |
| Localizzazione | testo delle notifiche | testo delle notifiche **e** tutta la dashboard, in sei lingue (`en`, `de`, `es`, `fr`, `it`, `pt`) |
| Impronta | immagine 264MB, nessuna porta in ascolto | 267MB: l'immagine Light più un layer |
Entrambe le edizioni eseguono lo stesso core. Differiscono solo per ciò che viene
iniettato: da dove arriva la configurazione e dove viene tenuto lo stato.
### La dashboard
La dashboard dell'edizione UI è una single-page app React servita dallo stesso
processo dell'API, su `http://localhost:3000`. Le sue viste, tutte raggiungibili
dalla rail, dalla command palette (`⌘K` / `Ctrl+K`) e dalle scorciatoie da tastiera:
| Vista | A cosa risponde |
|---|---|
| **Overview** | Qualcosa è giù adesso? Un titolo calmo, la lista dei provider e una griglia componibile di widget che puoi disporre e salvare come dashboard con nome. |
| **Providers** · **Components** | La flotta, una riga per provider, e la stessa flotta vista componente per componente; ogni provider ha una pagina propria con uptime, calendario annuale, latenza, incidenti, una mappa e il suo runbook. |
| **Incidents** | Ogni incidente come lista sotto una timeline Gantt, ciascuno con la propria pagina. |
| **History** | Uptime su 7, 30 o 90 giorni, in al massimo cinque tab: trend, affidabilità, pattern, confronto e latenza. |
| **Delivery log** | Cosa è stato inviato, a quale canale, e cosa diceva o perché è fallito. |
| **Settings** | Provider, canali, instradamento, politica di consegna, aspetto e dati, applicati al ciclo successivo senza restart. |
| **Wallboard** | Una vista a schermo intero, senza cornice, per uno schermo libero, con un QR code verso il provider nei guai peggiori. |
È chiara, scura o di sistema, con varianti ad alto contrasto, per daltonici e OLED,
e tradotta in sei lingue. Ogni route che ci sta dietro è documentata nell'
[API HTTP](docs/api.it.md); il percorso guidato è in
[Verificare un deployment](docs/verifying.it.md).
---
## 2. Avvio rapido
### 2.1 Con Docker
**Edizione UI, senza clone** — un file, due comandi. Le immagini sono pubblicate
su GHCR per `linux/amd64` e `linux/arm64`, quindi questo è anche il percorso per
Raspberry Pi, Unraid, Portainer e Synology:
```bash
curl -O https://raw.githubusercontent.com/DevManfre/isitdown/main/docker-compose.yml
docker compose --profile ui up -d
# poi apri http://localhost:3000
```
Tutto ciò che serve all'edizione UI si configura nella dashboard, credenziali
comprese: **Settings → un canale → Valore → Salva** ha effetto subito. Se
preferisci che sia il container a possederle, mettile in un `.env` accanto al
file compose: è opzionale, e viene letto se presente.
```bash
printf 'TELEGRAM_BOT_TOKEN=...\nTELEGRAM_CHAT_ID=...\n' > .env
docker compose --profile ui up -d # ricrea il container con i token
```
**Edizione Light** — polling e notifiche, niente in ascolto. Questa ha bisogno di
un `config.yml` da montare, quindi si parte da un clone:
```bash
git clone https://github.com/DevManfre/isitdown.git && cd isitdown
cp .env.example .env # compila solo i canali che abiliterai
cp config.example.yml config.yml # modifica: provider, intervallo, canali
docker compose --profile light up -d
docker logs -f isitdown-light
```
Possono girare entrambe insieme: usano volumi dati separati.
Chi sviluppa dal sorgente aggiunge `--build`, che ignora il pull e costruisce
l'immagine in locale:
```bash
docker compose --profile ui up -d --build
```
### 2.2 Senza Docker
Richiede **Node 24** sia per la build sia per il runtime: `.nvmrc` lo fissa e
`npm install` rifiuta versioni più vecchie, perché il driver SQLite integrato nel
runtime e il suo supporto TypeScript nativo sono fondamentali anche in fase di
build. `build:ui` in più esegue Vite per pacchettizzare la dashboard; `build:light`
salta questo passaggio, dato che Light non distribuisce nessuna dashboard.
```bash
nvm use # oppure: nvm install 24
npm install
cp config.example.yml config.yml
cp .env.example .env
npm run build:light && node dist/light/index.js # Light
npm run build:ui && node dist/ui/server.js # UI, poi apri :3000
```
Variabili utili in locale: `CONFIG_PATH`, `DATA_PATH`, `DB_PATH`, `PORT`,
`LOG_LEVEL` (vedi [3.3](docs/configuration.it.md#33-variabili-dambiente)).
---
## 11. Roadmap
Consegnato:
- **v1 — edizione Light**: polling, diff engine, notifiche Telegram e webhook
generico, `config.yml` con segreti referenziati dall'ambiente, state store JSON con
scritture atomiche, `ghcr.io/devmanfre/isitdown:light-latest`.
- **v1.1 — prototipazione UI**: la dashboard esplorata in Claude Design e conservata in
`design/claude-design-prototypes/`. L'opzione `3a`, la console navigabile, è il
riferimento per l'implementazione; la palette scura e le etichette italiane più
lunghe sono state validate lì invece di essere scoperte dopo.
- **v1.2 — edizione UI**: quel design come dashboard Express (scritta all'inizio come moduli ES
semplici, poi sostituita da quella React qui sotto) su SQLite, con la configurazione gestita a runtime e applicata al ciclo successivo senza
restart. `ghcr.io/devmanfre/isitdown:ui-latest`, costruita `FROM` l'immagine Light.
- **v1.3 — cronologia**: uptime e cronologia incidenti per provider con le barre
giornaliere in stile status page e le viste 7/30/90 giorni, aggregate lato server e
servite da `/history`.
- **v1.4 — tema scuro e i18n**: tema chiaro/scuro/sistema basato su token con
preferenza persistita, e dashboard localizzata (`en`, `it`) sopra i messaggi di
notifica localizzati che entrambe le edizioni già condividevano.
- **v1.5 — la dashboard React**: la dashboard vanilla portata su React 19, Vite,
Tailwind v4 e shadcn/ui, compilata in `dist/ui/public` e servita dallo stesso server
Express; il client legge gli aggregati del server tramite TanStack Query e non
ricalcola mai una percentuale.
Dopo la v1.5 (su `dev`): adapter per AWS, Google Cloud e Azure, richieste
condizionali così che la maggior parte dei cicli sia un `304`, una cadenza di
polling per provider, la vista del log invii, una rimozione di provider
annullabile entro una finestra di ripristino, ntfy e Gotify accanto agli altri
canali, un calendario annuale per provider, la readiness separata dalla
liveness, una verifica di integrità con vacuum su richiesta e una dashboard
Grafana committata, poi:
- **Notifiche**: oltre trenta canali tenuti a un unico contratto — chat, push,
strumenti di reperibilità e di incidenti, email, SMS e chiamate — con una
politica di consegna (riepilogo dei guasti condivisi, accorpamento degli
aggiornamenti, un periodo di silenzio per le interruzioni note, un report
periodico, una rotazione di reperibilità e un test settimanale di consegna).
- **Dashboard**: una Overview componibile costruita da un catalogo di widget, con
dashboard con nome, un riepilogo «mentre eri via» e numeri che rimandano alle
loro righe; un Gantt degli incidenti, percentili di latenza, confronto a cinque,
cronologia con zoom, una vista Components, un ordine manuale della flotta, una
command palette con ricerca testuale, scorciatoie da tastiera, filtri conservati
nell'indirizzo, una procedura guidata al primo avvio con tour guidato e un passaggio
di accessibilità (axe) su ogni frame.
- **Wallboard e feed**: un codice QR che apre il provider nei guai peggiori, un
impulso e un suono opzionale quando una tile cambia, e la flotta servita come
PNG a 1 bit e SVG per cornici e-ink e chat.
- **Qualità della vita per l'operatore**: un runbook Markdown per provider,
mostrato nella sua pagina e citato in ogni avviso; tag accanto al gruppo,
filtrabili e instradabili come `tag:<nome>`; silenziamenti pianificati,
settimanali o una tantum; finestre di manutenzione dichiarate dall'operatore,
che silenziano e vengono disegnate come quelle del provider; modifica in blocco
di cadenza, gruppo, tag, silenziamento e interrogazione su una selezione; e
Duplica su ogni provider ([3.25–3.29](docs/configuration.it.md#325-runbook--cosa-fare-se-è-giù)).
- **Redesign calmo**: un compito per vista — una Overview che risponde a «c'è
qualcosa di giù?» e ripiega il resto, una sola lista di provider invece di due,
History divisa in cinque tab, Settings elencato per categoria, un'intestazione su
una riga, spaziature e movimento su token di design, e gli effetti decorativi
ritirati. Nulla è stato eliminato; le funzioni secondarie sono passate dietro tab,
disclosure e menu.
- **Rete di sicurezza della configurazione**: ogni scrittura di configurazione
registrata in una cronologia da cui ripristinare un valore, snapshot con nome
dell'intera configurazione, un'anteprima in diff prima di applicare l'import di un
`config.yml`, e un provider letto da un form non salvato prima di salvarlo
([6. API HTTP](docs/api.it.md#6-api-http)).
- **Hardening**: la dashboard ascolta di default solo sul loopback, rifiuta
scritture cross-origin e con host rebound, limita le dimensioni delle risposte e
rifiuta i target link-local.
- **Catalogo e strumenti**: un catalogo di 205 provider, i comandi `isitdown
discover` e `isitdown import` e una CI divisa in job paralleli.
Ancora aperto:
- Una revisione madrelingua delle stringhe italiane.
La roadmap che ha portato il progetto fin qui è finita — ogni riga spedita.
**Cos'è IsItDown.** Sia un aggregatore di status page sia un monitor di cose che
non ne pubblicano nessuna — e ogni provider dichiara quale delle due risponde per
lui. Un provider con status page è `declared`: fa fede la sua pagina, e una sonda
che non concorda viene riportata come disaccordo, non come scavalcamento. Una
sonda è `observed`: fa fede la nostra misura, e una pagina che la contraddice è
un'opinione. Il default viene dall'adapter e non richiede configurazione; il
campo `authority` esiste solo per i casi in cui l'operatore non è d'accordo con
quel default. Questa domanda è rimasta aperta per due roadmap, ed è il motivo per
cui "cosa significa 93% qui" aveva due risposte sulla stessa schermata.
Non-obiettivi espliciti: autenticazione multi-utente (questa è una dashboard locale per
un singolo operatore), status page dietro login, e un'app mobile pacchettizzata.
---
## 12. Layout dei branch e politica di merge
Il tooling di Claude Code (`.claude/`, `CLAUDE.md`) e il filtro di merge stesso
(`.mergeexclude`, `.githooks/`, `scripts/`) sono versionati **solo su `dev`**. Su
`main` nessuno di quei percorsi esiste, né nel commit né nel working tree. Tutto il
resto (sorgenti, documentazione, configurazione) passa normalmente da `dev` a `main`.
Poiché il filtro non è leggibile da `main`, viene installato nella directory `.git` di
questo clone, che tutti i branch condividono.
### Setup, una volta per clone
```bash
git switch dev
scripts/setup-hooks.sh
```
Copia:
| Da (`dev`) | A (condiviso da ogni branch) |
|---|---|
| `scripts/git-merge-clean` | `$GIT_DIR/merge-clean` |
| `.githooks/*` | `$GIT_DIR/hooks/*` |
| `.mergeexclude` | `$GIT_DIR/merge-exclude` |
e installa l'alias `git mergeclean`. Rieseguilo dopo aver modificato `.mergeexclude`
o `scripts/git-merge-clean`.
### Merge verso `main`
```bash
git switch main
git mergeclean dev # non `git merge dev`
```
`git mergeclean` fa il merge del branch, elimina i percorsi elencati nella lista di
esclusione, committa col formato di subject `🔀` del repository e rimuove quei percorsi
dal working tree. Si rifiuta di partire su un albero sporco. I conflitti veri fuori dai
percorsi esclusi fermano l'esecuzione così puoi risolverli e fare `git commit` come al
solito.
### Cosa lo fa rispettare
| Pezzo | Ruolo |
|---|---|
| `$GIT_DIR/merge-exclude` | la lista dei percorsi |
| `$GIT_DIR/merge-clean` | il wrapper di merge (`--sync` elimina, `--guard` controlla) |
| `$GIT_DIR/hooks/post-checkout` | elimina i percorsi esclusi dopo un cambio di branch |
| `$GIT_DIR/hooks/pre-merge-commit`, `pre-commit` | interrompono qualunque commit che aggiungerebbe un percorso escluso a un branch che non lo traccia |
Un `git merge dev` semplice su `main` viene rifiutato dagli hook di guardia: esegui
`git merge --abort` e usa `git mergeclean`. `git commit --no-verify` aggira la guardia
se ti serve davvero.
### Conseguenze del tenere il filtro fuori da `main`
- **Il setup è per clone e non può essere automatico.** Git non esegue mai hook presi
da un clone, e un clone che fa checkout solo di `main` non ha nulla da cui
installare. Su una macchina nuova, fai checkout di `dev` ed esegui il setup prima di
fare merge verso `main`.
- **Finché il setup non viene eseguito, non è imposto nulla.** Un `git merge dev`
semplice su un clone appena fatto porterà `.claude/` e `CLAUDE.md` dentro `main`
appena risolvi i conflitti che solleva.
### Regole pratiche
- Modifica `.claude/`, `CLAUDE.md`, `.mergeexclude`, `.githooks/` e `scripts/` solo
stando su `dev`: su `main` non esistono.
- L'eliminazione cancella solo i file che anche `dev` ha e che sono identici byte per
byte, quindi i file locali della macchina (`.claude/settings.local.json`) e le
modifiche locali non vengono mai toccati.