Files
CRAPP/docs/ARCHITECTURE.md
T
davideandClaude Opus 5 822180bffc Riscrive AGENTS.md e riallinea la documentazione allo stato reale.
I riferimenti ai documenti in AGENTS.md erano rotti: una venticinquina di link
nella forma docs/[README.md](http://README.md), che spezzavano il nome del file
a meta e puntavano a domini inesistenti. Ora sono percorsi relativi verificati,
con CHANGELOG.md e DESIGN_DECISIONS.md sotto docs/ e PROJECT_STATE.md in root.

Tolte da AGENTS.md le sezioni Architettura, Documentazione e Struttura della
documentazione: duplicavano ARCHITECTURE.md e docs/README.md con uno stack ormai
parziale, contro la regola "ogni informazione ha una sola casa" che docs/README.md
stesso impone. Aggiunti invece i comandi, bun e la guardia minimumReleaseAge:
Codex e Cursor leggono solo AGENTS.md e non avevano modo di sapere come si
verifica una modifica. Scritta la checklist "Fine lavoro" che CLAUDE.md citava
senza che esistesse.

Nuova regola: chi aggiunge o modifica una funzione scrive o aggiorna il test nello
stesso lavoro, i test devono essere verdi e la doc del modulo va aggiornata se il
comportamento cambia (DD-020). Serve perche con main come branch di lavoro non
c'e piu un ambiente di prova tra il codice e i giocatori.

Il flusso git documentato non descriveva piu la realta: main e arrivato a 43
commit di vantaggio su develop, rimasto fermo. DD-003 e ora sostituita da DD-019:
il branch dei commit lo decide l'utente, l'assistente al massimo consiglia un
branch dedicato e non committa, non pusha e non apre PR di propria iniziativa.

Allineati di conseguenza ARCHITECTURE.md (sezione branch), README.md (flusso,
install con bun, comandi di test e lint), ROADMAP.md e TODO.md (le voci spuntate
sono in produzione, non su develop) e PROJECT_STATE.md (auth e profilo giocatore
in produzione, 20 migration fino a M9, passaggi 1-3 e 5 fatti).

Corretti poi sei disallineamenti tra documentazione e codice, ognuno verificato
sul sorgente:

- badge.md e obiettivi-squadra.md dicevano che le serie sono inerti e che
  serieAllenamenti e sempre 0, quindi badge e obiettivo "Continuita di squadra"
  non sbloccabili. Falso da 7237e8f: presenze.ts:48 le calcola e rosa.ts:64-67 le
  attacca al Giocatore. Il limite che resta e un altro, ora scritto: risposto_il
  non e ricostruibile prima di m9, quindi sulle risposte vecchie serieConferme e
  un'approssimazione.
- TODO.md e PROJECT_STATE.md davano il tracciamento tesseramento CSI come da
  fare, mentre ROADMAP, CHANGELOG e DATABASE lo davano per fatto. Lo e:
  admin.tsx:264-278 registra numero e data, :472 mostra Tesserato/Da tesserare,
  :676 il contatore.
- collegamento-csi.md indicava il check di parsing in src/lib/csi-core.test.ts;
  sta in test/unit/csi-core.test.ts, in src/lib non esiste nessun .test.ts.
- profilo-giocatore.md annunciava cinque aree del profilo e ne elencava sette.
- "Segnala un bug" e "Suggerisci una nuova funzionalita" (profilo.tsx:259-276,
  commit 72a9864) non erano documentati da nessuna parte, contro DD-002: ora
  stanno in profilo-giocatore.md e nel CHANGELOG.

npm run test: 28/28 file ok. npm run lint: 12 problemi, identici a prima di
questa modifica e tutti in src/, non toccato qui.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 23:24:22 +02:00

6.3 KiB

Architettura del progetto

Come è fatta CrAPP: stack, organizzazione del codice, flusso di sviluppo. È il documento di riferimento tecnico — CLAUDE.md non ripete questi contenuti, li richiama.

Stack

Livello Tecnologie
Frontend React 19, TypeScript, TanStack Start (SSR), Vite 8, Tailwind CSS 4, Radix UI / shadcn
Backend Supabase (PostgreSQL, Auth, Storage)
Hosting Vercel
Versionamento Git, GitHub

Le dipendenze sono installate con bun (bun.lock, bunfig.toml). bunfig.toml impone minimumReleaseAge = 24h come guardia supply-chain: aggiungere un pacchetto a minimumReleaseAgeExcludes richiede conferma esplicita.

Struttura del progetto

src/
  components/   componenti condivisi (crapp/, ui/, motion/)
  routes/       routing file-based
  lib/          logica di dominio, un file per modulo
  integrations/ client Supabase e integrazioni esterne
  hooks/
  assets/
supabase/       migration SQL
test/           suite di test (unit, integration, end-to-end)
docs/           documentazione ufficiale

Punti fermi

  • Routing: file-based in src/routes/. src/routeTree.gen.ts è generato, non si modifica a mano.
  • Configurazione Vite: vite.config.ts usa @lovable.dev/vite-tanstack-config, che include già devtools, tanstackStart, viteReact, tailwind, tsconfig-paths, nitro e l'alias @src/. Non ri-aggiungere questi plugin: l'app si rompe.
  • Entry point server: src/server.ts avvolge l'entry di TanStack Start per intercettare gli errori SSR che h3 trasformerebbe in un 500 JSON silenzioso, e renderizza renderErrorPage(). src/start.ts registra i middleware globali (error handler, CSRF sui server functions, attachSupabaseAuth).
  • Supabase: src/integrations/supabase/client.ts (browser/SSR, chiave publishable — file generato) e client.server.ts (supabaseAdmin, solo server). types.ts è generato dallo schema; finché non viene rigenerato, le tabelle introdotte da M1/M2 si usano tramite client-nuove-tabelle.ts, con i tipi di riga dichiarati nei moduli di src/lib/.
  • Autenticazione: login Google via Supabase Auth (src/lib/auth.ts, DD-011). È l'unica strada di accesso: __root.tsx rimanda a /benvenuto chi non ha sessione, e l'identità del giocatore è lo slot di giocatori_squadra collegato all'account. I permessi di amministrazione arrivano solo da user_roles (src/lib/ruoli.ts).

Livello dati

Tutta la logica di dominio sta in src/lib/, un file per modulo (presenze, eventi, pagelle, mvp-voti, palloni, cacche, badges, scout-*, infortuni, …). Il pattern ricorrente:

  • ogni modulo esporta hook TanStack Query (useX); i default globali stanno in src/router.tsx (staleTime 5 min, gcTime 30 min, refetchOnWindowFocus/Mount/Reconnect disattivati, retry: 1);
  • dopo una mutazione la cache si aggiorna con setQueryData, non con invalidateQueries: invalidare provoca una rilettura e costa una query in più (unica eccezione oggi: scout-live.ts);
  • le funzioni pure di calcolo sono separate dagli hook (es. palloni-core.ts vs palloni.ts, mediePagelle() vs usePagelle());
  • src/lib/rosa.ts è l'aggregatore: compone tutti gli hook e restituisce la rosa completa con le statistiche derivate, senza query aggiuntive rispetto a quelle già in cache. Le route consumano useRosa(), non i singoli moduli.

Nessun accesso al database dai componenti: solo attraverso i moduli in src/lib/, così il backend resta sostituibile in un solo punto (DD-013, PORTABILITA.md).

Vincoli di efficienza cloud — niente polling, cache lunga, setQueryData invece di invalidateQueries — in EFFICIENZA_CLOUD.md.

Badge e statistiche sono calcolati a runtime dai dati, non persistiti (DD-007). La gamification deve restare equa tra ruoli (DD-008).

La rosa vive nella tabella giocatori_squadra, letta tramite useRosa()/useGiocatoriSquadra() (DD-015, DD-016). src/lib/crapp-data.ts (rosaCSI) resta solo come seed storico e fallback quando il database non risponde.

UI

Componenti condivisi in src/components/crapp/ (ui-bits.tsx per PageHeader, Section, StatTile), primitive shadcn in src/components/ui/, animazioni in src/components/motion/. Mobile-first (DD-005): poche schermate, pochi click.

Comandi

npm run dev       # vite dev su http://localhost:8080
npm run build     # build di produzione (nitro)
npm run lint      # eslint (include prettier come regola)
npm run format    # prettier --write .
npm run test      # test unit (veloci, senza rete né database)
npm run test:integration  # route server vere
npm run test:e2e          # percorsi sull'app servita
npm run test:all          # tutto

Database di sviluppo in locale (Docker), alternativo al progetto Supabase cloud:

npx supabase start   # avvia lo stack locale e applica tutte le migration
npx supabase stop    # spegne i container
npx supabase db reset # ricrea il database da zero: migration + supabase/seed.sql
npx supabase db push  # applica le migration al progetto cloud

supabase/seed.sql popola qualche profilo di prova e gira solo in locale. Serve perché il progetto cloud è uno solo, condiviso tra sviluppo e produzione: lo stack locale è il posto dove provare le migration distruttive senza toccare i dati veri.

Branch e flusso di sviluppo

  • main → produzione, deploy automatico su Vercel. È anche il branch di lavoro corrente.
  • develop → preview Vercel; oggi indietro rispetto a main, non rappresenta lo stato attuale.
  • feature/…, fix/…, refactor/… → lavori rischiosi o paralleli.

Su quale branch va un commit lo decide l'utente (DD-019): un assistente AI può consigliare un branch dedicato, non sceglierlo. Poiché si lavora su main, la rete di sicurezza sono i test, che vanno scritti insieme al codice e devono essere verdi (DD-020, test/README.md).