{"id":50646851,"url":"https://github.com/feduh/bozza-bel-paese","last_synced_at":"2026-06-07T13:02:20.927Z","repository":{"id":357382619,"uuid":"1183995122","full_name":"feduh/bozza-bel-paese","owner":"feduh","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-30T22:52:41.000Z","size":1047,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-31T00:19:42.725Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/feduh.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-17T06:29:51.000Z","updated_at":"2026-05-30T22:52:46.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/feduh/bozza-bel-paese","commit_stats":null,"previous_names":["feduh/bozza-bel-paese"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/feduh/bozza-bel-paese","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/feduh%2Fbozza-bel-paese","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/feduh%2Fbozza-bel-paese/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/feduh%2Fbozza-bel-paese/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/feduh%2Fbozza-bel-paese/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/feduh","download_url":"https://codeload.github.com/feduh/bozza-bel-paese/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/feduh%2Fbozza-bel-paese/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34022032,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-07T02:00:07.652Z","response_time":124,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-07T13:02:17.645Z","updated_at":"2026-06-07T13:02:20.918Z","avatar_url":"https://github.com/feduh.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Mappatura Realtà Artistiche Italiane\n\nPiattaforma web per mappare, documentare e raccontare le realtà artistiche e culturali italiane: spazi con sede, collettivi nomadi e luoghi storici scomparsi. L'applicazione fornisce una mappa interattiva, schede di dettaglio, un blog editoriale e un'area amministrativa per la gestione collaborativa dei contenuti.\n\n---\n\n## Indice\n\n- [Funzionalità](#funzionalità)\n- [Stack tecnologico](#stack-tecnologico)\n- [Architettura](#architettura)\n- [Setup locale](#setup-locale)\n- [Script disponibili](#script-disponibili)\n- [Struttura del progetto](#struttura-del-progetto)\n- [Database \u0026 API](#database--api)\n- [Autenticazione \u0026 ruoli](#autenticazione--ruoli)\n- [Edge Functions](#edge-functions)\n- [Testing](#testing)\n- [Convenzioni di sviluppo](#convenzioni-di-sviluppo)\n- [Deploy](#deploy)\n\n---\n\n## Funzionalità\n\n- 🗺️ **Mappa interattiva** delle realtà artistiche (Leaflet + OpenStreetMap) con lazy loading\n- 🏛️ **Schede di dettaglio** per ogni realtà con storia, contatti, tag e collegamenti\n- ✍️ **Blog editoriale** con articoli categorizzati\n- 🔐 **Autenticazione email/password** tramite Lovable Cloud\n- 👥 **Gestione collaboratori** con ruoli `admin`, `moderator`, `user`\n- 🛡️ **RLS policies** per il controllo degli accessi a livello di riga\n- ⚡ **Performance** ottimizzate: code splitting, lazy loading immagini e mappa\n\n---\n\n## Stack tecnologico\n\n| Layer        | Tecnologia                                  |\n|--------------|---------------------------------------------|\n| Frontend     | React 18 + TypeScript + Vite 5              |\n| Styling      | Tailwind CSS v3 + shadcn/ui                 |\n| Routing      | React Router v6                             |\n| State/Data   | TanStack Query                              |\n| Mappe        | Leaflet + React-Leaflet (lazy loaded)       |\n| Backend      | Lovable Cloud (Supabase: Postgres + Auth + Edge Functions) |\n| Validazione  | Zod                                         |\n| Testing      | Vitest + Testing Library + jsdom            |\n\n---\n\n## Architettura\n\n```text\n┌─────────────────────────────────────────────────────┐\n│                  Browser (React SPA)                │\n│  ┌──────────┐  ┌──────────┐  ┌──────────────────┐   │\n│  │  Pages   │→ │  Hooks   │→ │ Supabase Client  │   │\n│  │ (Routes) │  │ (useAuth)│  │  (@/integrations)│   │\n│  └──────────┘  └──────────┘  └────────┬─────────┘   │\n└──────────────────────────────────────────┼──────────┘\n                                           │ HTTPS\n                            ┌──────────────▼──────────────┐\n                            │       Lovable Cloud         │\n                            │  ┌───────────────────────┐  │\n                            │  │ PostgreSQL + RLS      │  │\n                            │  │ - realities           │  │\n                            │  │ - reality_tags        │  │\n                            │  │ - profiles            │  │\n                            │  │ - user_roles          │  │\n                            │  │ - blog_posts          │  │\n                            │  └───────────────────────┘  │\n                            │  ┌───────────────────────┐  │\n                            │  │ Auth (email/password) │  │\n                            │  └───────────────────────┘  │\n                            │  ┌───────────────────────┐  │\n                            │  │ Edge Functions (Deno) │  │\n                            │  │ - invite-collaborator │  │\n                            │  └───────────────────────┘  │\n                            └─────────────────────────────┘\n```\n\n**Principi:**\n- **SPA client-side**: tutta la logica di presentazione è React; il backend è esposto solo via Supabase SDK ed Edge Functions.\n- **Sicurezza data-layer**: i ruoli sono in una tabella dedicata `user_roles` e validati lato DB tramite la funzione `has_role()` (SECURITY DEFINER) usata nelle policy RLS.\n- **Separazione ambiente**: variabili pubbliche in `.env` (auto-generato), secrets server-side gestiti da Lovable Cloud.\n\n---\n\n## Setup locale\n\n**Requisiti:** Node.js ≥ 20, npm (oppure bun).\n\n```bash\ngit clone \u003cREPO_URL\u003e\ncd \u003cPROJECT\u003e\nnpm install\nnpm run dev\n```\n\nIl server parte su `http://localhost:8080`.\n\n\u003e Il file `.env` con le chiavi pubbliche di Lovable Cloud è generato automaticamente e non va modificato manualmente.\n\n---\n\n## Script disponibili\n\n| Comando            | Descrizione                                  |\n|--------------------|----------------------------------------------|\n| `npm run dev`      | Avvia Vite in modalità sviluppo (porta 8080) |\n| `npm run build`    | Build di produzione in `dist/`               |\n| `npm run preview`  | Serve la build di produzione localmente      |\n| `npm run lint`     | Lint del codice con ESLint                   |\n| `npx vitest run`   | Esegue la suite di test una volta            |\n| `npx vitest`       | Test in watch mode                           |\n\n---\n\n## Struttura del progetto\n\n```\nsrc/\n├── components/        # Componenti riutilizzabili (Navbar, Footer, LazyMap, ui/)\n├── hooks/             # Custom hooks (useAuth, use-toast, use-mobile)\n├── integrations/\n│   └── supabase/      # Client e tipi auto-generati (NON modificare)\n├── pages/             # Route principali (Index, Mappatura, Admin, Login, ...)\n├── data/              # Mock data e costanti\n├── lib/               # Utility (cn, helpers)\n├── test/              # Setup Vitest\n└── index.css          # Design tokens (HSL semantic colors)\n\nsupabase/\n├── config.toml        # Config Edge Functions\n└── functions/\n    └── invite-collaborator/index.ts\n```\n\n---\n\n## Database \u0026 API\n\nL'accesso ai dati avviene **esclusivamente** via `supabase` client:\n\n```ts\nimport { supabase } from \"@/integrations/supabase/client\";\n\nconst { data, error } = await supabase\n  .from(\"realities\")\n  .select(\"*, reality_tags(tag)\")\n  .order(\"name\");\n```\n\n### Tabelle principali\n\n| Tabella         | Scopo                                              |\n|-----------------|----------------------------------------------------|\n| `realities`     | Realtà artistiche (nome, città, lat/lng, tipo, storia) |\n| `reality_tags`  | Tag associati (relazione N:1 con `realities`)      |\n| `blog_posts`    | Articoli del blog                                  |\n| `profiles`      | Dati pubblici utente (display_name, bio, social)   |\n| `user_roles`    | Ruoli (`admin` \\| `moderator` \\| `user`)           |\n\n### Enums\n\n- `reality_type`: `nomade` | `con-sede` | `scomparsa`\n- `app_role`: `admin` | `moderator` | `user`\n\n### Funzioni DB\n\n- `has_role(_user_id uuid, _role app_role) → boolean` — usata nelle RLS policy.\n\n---\n\n## Autenticazione \u0026 ruoli\n\nL'autenticazione usa email/password. La sessione è esposta tramite il context `useAuth`:\n\n```tsx\nimport { useAuth } from \"@/hooks/useAuth\";\n\nconst { user, session, loading, signIn, signUp, signOut } = useAuth();\n```\n\n**Controllo ruoli (lato client, solo per UX):**\n\n```ts\nconst { data: isAdmin } = await supabase.rpc(\"has_role\", {\n  _user_id: user.id,\n  _role: \"admin\",\n});\n```\n\n\u003e Il controllo autorizzativo reale è applicato dalle policy RLS lato database e dalle Edge Functions.\n\n---\n\n## Edge Functions\n\n### `invite-collaborator`\n\nPermette a un admin di creare un nuovo utente con ruolo assegnato.\n\n**Endpoint:** `POST {SUPABASE_URL}/functions/v1/invite-collaborator`\n\n**Headers:** `Authorization: Bearer \u003cuser_jwt\u003e`\n\n**Body:**\n```json\n{\n  \"email\": \"user@example.com\",\n  \"password\": \"Passw0rd!\",\n  \"display_name\": \"Nome Utente\",\n  \"role\": \"moderator\"\n}\n```\n\n**Validazioni (Zod):**\n- email valida, max 255 caratteri\n- password 8–72 caratteri, almeno 1 maiuscola e 1 numero\n- display_name 2–100 caratteri\n- role: `user` | `moderator`\n\n**Sicurezza:**\n- Verifica JWT chiamante e ruolo `admin` via `has_role`\n- Rate limiting in-memory: 5 richieste/minuto per admin\n- Service role key usata solo server-side\n\n**Risposte:**\n- `200` `{ success, user, message }`\n- `400` errori di validazione | `401` non autenticato | `403` non admin | `429` rate limit\n\n---\n\n## Testing\n\nSuite con **Vitest + Testing Library**:\n\n```bash\nnpx vitest run\n```\n\nCopertura attuale:\n- `useAuth` (gestione sessione, signIn/signUp/signOut, cleanup)\n- `Login` (form, errori, navigazione)\n- `Admin` (permessi, caricamento collaboratori)\n- `Navbar` (link, stato auth)\n\n**Pattern di mock:** il client Supabase è mockato per isolare i componenti (vedi `src/test/setup.ts` e i singoli `__tests__/`).\n\n---\n\n## Convenzioni di sviluppo\n\n- **Design system**: usa SOLO i token semantici definiti in `src/index.css` e `tailwind.config.ts`. Niente colori hardcoded (`text-white`, `bg-black`).\n- **Componenti shadcn**: estendi tramite varianti (`cva`), non duplicare.\n- **Tipi DB**: importa da `@/integrations/supabase/types` — il file è auto-generato.\n- **Path alias**: usa `@/` per `src/`.\n- **Validazione input**: Zod per Edge Functions e form critici.\n- **Lazy loading**: componenti pesanti (es. mappa) caricati con `React.lazy()` + `Suspense`.\n\n---\n\n## Deploy\n\nIl deploy è gestito da Lovable: apri il progetto su [lovable.dev](https://lovable.dev) e clicca **Share → Publish**.\n\nPer un dominio personalizzato: **Project → Settings → Domains → Connect Domain**.\n\n---\n\n## Licenza\n\nProgetto privato. Tutti i diritti riservati.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffeduh%2Fbozza-bel-paese","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffeduh%2Fbozza-bel-paese","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffeduh%2Fbozza-bel-paese/lists"}