diff --git a/README.md b/README.md index c799104..b47411a 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ rebase/amend/squash di commit già pushati). ancora da implementare - **Notifiche push**: convocazioni, promemoria allenamento/partita, turno palloni, esito finale -## Sviluppo +## Sviluppo (locale) Package manager: **bun** ([installazione](https://bun.sh)). @@ -38,16 +38,67 @@ Package manager: **bun** ([installazione](https://bun.sh)). git clone https://github.com/ivancacciari1995-a11y/CRAPP.git cd CRAPP bun install -bun run dev # avvia il dev server su http://localhost:8080 ``` -Serve un file `.env` con le credenziali Supabase (`VITE_SUPABASE_URL`, -`VITE_SUPABASE_PUBLISHABLE_KEY`) ed eventualmente le chiavi `VAPID_*` per le notifiche push. +### 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 # build di produzione bun run build:dev # build in modalità development bun run preview # anteprima di una build bun run lint # eslint . @@ -56,6 +107,72 @@ 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):