davideandClaude Sonnet 5 c2667b3bfe Sostituisco l'admin per nome con un login vero (account Strapi)
Le azioni da referente (/scout, /eventi, sollecito presenze, export CSV
scout) non dipendono più da quale giocatore hai scelto di essere in
/benvenuto (chiunque poteva scegliere "Ivan Cacciari" senza password), ma
da un login reale contro l'account admin di Strapi (già usato per gestire
rosa/classifica/storico), verificato via /admin/login.

Nuovi src/lib/admin-auth.ts (loginAdmin/logoutAdmin/useAdminSession, sessione
locale di 8h) e src/components/crapp/AdminLogin.tsx (form riutilizzabile),
raggiungibile da /profilo e dalle schermate riservate. Rimossi adminNomi/
isAdmin da crapp-data.ts.

Resta un limite noto: questo protegge solo la UI dell'app, le tabelle
Supabase coinvolte hanno ancora RLS aperta e restano scrivibili in diretto
con la chiave anon — un fix più ampio (Supabase Auth + RLS reale) è
documentato ma non ancora fatto.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-28 16:17:05 +02:00
2026-08-06 08:36:47 +02:00
2026-08-06 08:36:47 +02:00

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: 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 (React 19, routing file-based) + Vite
  • Tailwind v4 + componenti shadcn/radix
  • Supabase (@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), sync reale ancora da implementare
  • Notifiche push: convocazioni, promemoria allenamento/partita, turno palloni, esito finale

Sviluppo (locale)

Package manager: bun (installazione).

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/:

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):

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:

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

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:

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 il preset è forzato a node-server per generare un server Node standard, deployabile su qualunque host (coerente con docs/PORTABILITA.md).

Passo passo, sul server di produzione:

  1. 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.
  2. Stack Supabase self-hosted:
    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:
    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.
  3. Migrazioni:
    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
    
  4. 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:
    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:
    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).
  5. 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.
  6. Env dell'app:
    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).
  7. Build e avvio:
    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.
  8. 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: 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 per lo stato attuale e le regole da rispettare.

Note per chi sviluppa con Claude Code

Vedi CLAUDE.md per architettura dettagliata, convenzioni del repo e vincoli di efficienza sul piano cloud a consumo.

S
Description
App del CRAP, ottimizzazione di sporteasy adattata alle esigenze della squadra, campionato e extra
https://crapp-iv11.vercel.app
Readme
2.3 MiB
Languages
TypeScript 94.4%
PLpgSQL 3.5%
CSS 1.8%
JavaScript 0.3%