Files
CRAPP/README.md
T
davideandClaude Sonnet 5 3f61b32219 Aggiungo CMS Strapi self-hosted per gestire rosa, classifica e storico partite
Introduce lo stack Strapi dockerizzato (infra/strapi/), sullo stesso Postgres
dello stack Supabase con un database logico separato, dietro Caddy su /cms/*.
L'editing dei dati avviene solo nel pannello admin nativo di Strapi.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-28 15:39:20 +02:00

216 lines
9.4 KiB
Markdown

# CrAPP — CRAP Volley Hub
App mobile-first per la gestione della squadra amatoriale di pallavolo **CRAP Volley**:
presenze, partite/allenamenti/eventi, scouting live, statistiche giocatori, badge,
classifica CSI, notifiche push.
Progetto avviato con [Lovable](https://lovable.dev): i push su `main` sincronizzano l'editor
Lovable, quindi si evita di riscrivere la history già pubblicata (niente force-push,
rebase/amend/squash di commit già pushati).
**Live app**: https://volley-cronos-app.lovable.app
## Stack
- [TanStack Start](https://tanstack.com/start) (React 19, routing file-based) + Vite
- Tailwind v4 + componenti shadcn/radix
- [Supabase](https://supabase.com) (`@supabase/supabase-js`) per dati e auth
- TanStack Query per la cache client
## Funzionalità
- **Presenze**: RSVP rapido (presente / assente / forse / in ritardo / infortunato) su ogni evento
- **Eventi**: partite, allenamenti, eventi sociali, con calendario e lista
- **Scouting live**: registrazione azioni punto-per-punto durante la partita (riservato agli
admin)
- **Statistiche giocatori**: presenze totali/consecutive, badge, obiettivi squadra, medie pagelle
- **Votazioni post-partita**: MVP, pagelle 1-10 tra compagni, voti "social"/goliardici
- **Turno palloni**: rotazione automatica di chi porta i palloni, con promemoria push
- **Classifica CSI**: al momento un dato demo hardcoded (vedi [CLAUDE.md](CLAUDE.md)), sync reale
ancora da implementare
- **Notifiche push**: convocazioni, promemoria allenamento/partita, turno palloni, esito finale
## Sviluppo (locale)
Package manager: **bun** ([installazione](https://bun.sh)).
```sh
git clone https://github.com/ivancacciari1995-a11y/CRAPP.git
cd CRAPP
bun install
```
### 1. Avvia un backend Supabase
Serve un'istanza Supabase (cloud o self-hosted) a cui puntare. Per lavorare in locale senza
toccare dati reali, nel repo c'è uno stack self-hosted pronto in `infra/supabase/docker/`:
```sh
cd infra/supabase/docker
cp .env.example .env
sh utils/generate-keys.sh --update-env # genera JWT_SECRET, ANON_KEY, SERVICE_ROLE_KEY, ecc.
```
Poi avvia lo stack (con `docker-compose.prod.yml` si tengono su solo i servizi che CrAPP usa
davvero — vedi la sezione Produzione più sotto):
```sh
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
docker compose ps # verifica che tutti i container siano "healthy"
```
Applica le migrazioni del progetto al database appena creato:
```sh
cd ../../.. # torna alla root del repo
for f in supabase/migrations/*.sql; do
docker exec -i supabase-db psql -U postgres -d postgres -v ON_ERROR_STOP=1 < "$f"
done
```
### 2. Configura `.env` di CrAPP
Nella root del repo, crea `.env` con le chiavi lette da `infra/supabase/docker/.env`:
```
VITE_SUPABASE_URL=http://localhost:8000
VITE_SUPABASE_PUBLISHABLE_KEY=<ANON_KEY dello stack self-hosted>
SUPABASE_SERVICE_ROLE_KEY=<SERVICE_ROLE_KEY dello stack self-hosted>
```
Facoltative per testare le notifiche push (senza non si rompe nulla, semplicemente niente push):
```
VAPID_PUBLIC_KEY=...
VAPID_PRIVATE_KEY=...
VAPID_SUBJECT=mailto:tuamail@esempio.it
```
### 3. Avvia l'app
```sh
bun run dev # http://localhost:8080
```
Le tabelle sono vuote al primo avvio: crea un giocatore/evento dall'app stessa per avere dati di
test. Dashboard Supabase Studio raggiungibile su `http://localhost:8000` (credenziali
`DASHBOARD_USERNAME`/`DASHBOARD_PASSWORD` in `infra/supabase/docker/.env`).
Altri comandi:
```sh
bun run build:dev # build in modalità development
bun run preview # anteprima di una build
bun run lint # eslint .
bun run format # prettier --write .
```
Non è configurato un test runner.
## Produzione (self-hosted, Node + Docker)
`bun run build` usa Nitro (tramite `@lovable.dev/vite-tanstack-config`), che di default
compilerebbe per Cloudflare Workers — in [vite.config.ts](vite.config.ts) il preset è forzato a
`node-server` per generare un server Node standard, deployabile su qualunque host (coerente con
[docs/PORTABILITA.md](docs/PORTABILITA.md)).
Passo passo, sul server di produzione:
0. **Dominio/DNS**: un solo hostname pubblico basta — `Caddyfile.example` instrada `/api/*`
verso il gateway Supabase (path stripped) e tutto il resto verso l'app, sullo stesso dominio.
- Con un dominio vero (DNS proprio): `tuodominio.it`.
- Con un dominio **gratuito No-IP** (`ddns.net`, ecc.): un hostname singolo basta e avanza
(il piano free ne dà fino a 3, ma qui ne serve uno solo), es. `crapp.ddns.net`.
- Serve un client DDNS attivo sul server (o supporto nel router) che aggiorni l'IP: gli
hostname No-IP gratuiti scadono dopo ~30 giorni di inattività se non confermati.
- Verifica di non essere dietro **CGNAT** (IP pubblico condiviso dall'ISP): in quel caso
nessuna porta è raggiungibile da internet e serve un tunnel (es. Cloudflare Tunnel) al
posto dell'esposizione diretta.
1. **Stack Supabase self-hosted**:
```sh
cp infra/supabase/docker/.env.production.example infra/supabase/docker/.env
cd infra/supabase/docker
sh utils/generate-keys.sh --update-env # secret NUOVI, non riusare quelli di sviluppo
```
Modifica nel `.env` appena creato: `SUPABASE_PUBLIC_URL`/`API_EXTERNAL_URL` (dominio del
punto 0 + `/api`), `SITE_URL` (dominio del punto 0), `DASHBOARD_PASSWORD`, e l'SMTP se
servono email vere. Poi avvia:
```sh
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
```
`docker-compose.prod.yml` fa due cose, pensate anche per girare su hardware limitato (es.
Raspberry Pi 4): non espone porte pubblicamente (solo `127.0.0.1`, dietro il reverse proxy —
vedi `Caddyfile.example` nella stessa cartella), e disattiva i servizi Supabase che CrAPP non
usa (Realtime, Storage, imgproxy, Edge Functions, pooler) — restano solo `db`, `auth`, `rest`,
`api-gw`, più `studio`+`meta` per guardare/gestire il database via interfaccia grafica
(raggiungibile su `<dominio>/api`, con le credenziali `DASHBOARD_USERNAME`/
`DASHBOARD_PASSWORD`). Da 11 container si scende a 6.
2. **Migrazioni**:
```sh
cd ../.. # root del repo
for f in supabase/migrations/*.sql; do
docker exec -i supabase-db psql -U postgres -d postgres -v ON_ERROR_STOP=1 < "$f"
done
```
3. **Stack Strapi** (CMS admin per rosa, classifica, storico partite, scout finalizzato — vedi
`infra/strapi/`): usa lo stesso Postgres dello stack Supabase, in un database logico separato:
```sh
docker exec -i supabase-db psql -U postgres -c "CREATE DATABASE strapi;"
docker exec -i supabase-db psql -U postgres -c "CREATE USER strapi WITH PASSWORD '...';"
docker exec -i supabase-db psql -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE strapi TO strapi;"
cp infra/strapi/.env.production.example infra/strapi/.env
```
Compila in `infra/strapi/.env` i secret (`APP_KEYS`, `JWT_SECRET`, ecc. — genera ognuno con
`openssl rand -base64 32`) e `DATABASE_PASSWORD` (la stessa scelta sopra), poi:
```sh
cd infra/strapi
docker compose up -d --build
```
Al primo accesso su `<dominio>/cms/admin` crea l'utente amministratore Strapi. Da lì, un solo
giro di setup manuale (nessuna automazione: i permessi Strapi si abilitano solo dall'admin UI):
in Settings → Users & Permissions Plugin → Roles → Public abilita `find`/`findOne` per
`Giocatore`, `Riga-classifica` e `Match-storico`; poi in Settings → API Tokens genera un token
con permesso `create` solo su `Scout-match-finale` (va in `STRAPI_WRITE_TOKEN` nell'env
dell'app, punto 5). Infine inserisci a mano rosa/classifica/storico nelle rispettive collezioni
(i valori di partenza sono nella cronologia git di `src/lib/crapp-data.ts`, prima che venissero
spostati qui).
4. **Reverse proxy TLS**: copia `infra/supabase/docker/Caddyfile.example` in `Caddyfile`,
sostituisci il dominio del punto 0, poi `caddy run --config Caddyfile` (o come container).
Gestisce automaticamente il certificato Let's Encrypt.
5. **Env dell'app**:
```sh
cp .env.production.example .env
```
Compila `VITE_SUPABASE_URL` (dominio del punto 0 + `/api`),
`VITE_SUPABASE_PUBLISHABLE_KEY` (= `ANON_KEY` dello stack), `SUPABASE_SERVICE_ROLE_KEY`
(= `SERVICE_ROLE_KEY`), `VITE_STRAPI_URL` (dominio del punto 0 + `/cms`), `STRAPI_WRITE_TOKEN`
(il token generato al punto 3), e le chiavi `VAPID_*` reali
(`npx web-push generate-vapid-keys`).
6. **Build e avvio**:
```sh
bun run build
node .output/server/index.mjs # ascolta su PORT (default 3000)
```
Tienilo vivo con un process manager (pm2/systemd) — il Caddy del punto 4 lo espone via TLS
sull'hostname app.
7. **Job pianificati** — gli endpoint `src/routes/api/public/promemoria-palloni.ts` e
`sollecita-presenze.ts` vanno richiamati periodicamente via HTTP POST da un cron di sistema o
`pg_cron`: non partono da soli.
## Continuare da Lovable
Il progetto resta modificabile anche dall'[editor Lovable](https://lovable.dev/projects/8d07b0e4-6bd2-4a17-9dd2-bb2cf13f9f7c):
le modifiche fatte lì vengono committate direttamente su questo repository, e viceversa i push
su `main` sincronizzano l'editor.
## Portabilità
Il progetto è pensato per restare deployabile su un normale server **Node.js + PostgreSQL**,
senza dipendenze esclusive da Lovable Cloud — vedi [docs/PORTABILITA.md](docs/PORTABILITA.md)
per lo stato attuale e le regole da rispettare.
## Note per chi sviluppa con Claude Code
Vedi [CLAUDE.md](CLAUDE.md) per architettura dettagliata, convenzioni del repo e vincoli di
efficienza sul piano cloud a consumo.