# 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= SUPABASE_SERVICE_ROLE_KEY= ``` 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 `/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. **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. 4. **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`), e le chiavi `VAPID_*` reali (`npx web-push generate-vapid-keys`). 5. **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 3 lo espone via TLS sull'hostname app. 6. **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.