Aggiunge design spec sito InsanityLab
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,130 @@
|
|||||||
|
# Sito web InsanityLab — Design
|
||||||
|
|
||||||
|
**Data:** 2026-07-01
|
||||||
|
**Dominio di destinazione:** insanitylab.tielogic.xyz (VPS Hostinger, porting in fase successiva)
|
||||||
|
**Stato:** approvato dall'operatore durante la sessione di brainstorming
|
||||||
|
|
||||||
|
## Obiettivo
|
||||||
|
|
||||||
|
Realizzare il sito vetrina di InsanityLab (centro di allenamento e benessere, Bologna) a partire dal design Figma fornito dal designer (`FigmaDoc/*.pdf`, `Web Insanity.fig`), che ristilizza il template WordPress "Prowess" (analizzato in `Dati/cassetta-me-analisi.md`) con una palette beige/marrone al posto del rosso originale. Il sito include un blog gestibile dal cliente tramite pannello protetto da login e un form contatti che invia email. La gestione degli acquisti online (pagina prezzi Performance Class) è rimandata a una fase successiva.
|
||||||
|
|
||||||
|
## Stack
|
||||||
|
|
||||||
|
| Livello | Scelta |
|
||||||
|
|---|---|
|
||||||
|
| Framework | Astro 5, output `server` con adapter Node |
|
||||||
|
| Pagine vetrina | Prerenderizzate (`prerender = true`) |
|
||||||
|
| Blog e admin | Server-rendered |
|
||||||
|
| Stile | CSS custom (palette estratta dai PDF Figma), nessun framework CSS |
|
||||||
|
| Font | Montserrat (titoli) + Open Sans (corpo), self-hosted |
|
||||||
|
| JS client | Vanilla, minimo indispensabile (slider, tab, accordion, header sticky) |
|
||||||
|
| Database | SQLite via `better-sqlite3`, file `data/insanitylab.db` |
|
||||||
|
| Editor admin | WYSIWYG TipTap, con upload immagini nel corpo articolo |
|
||||||
|
| Email | nodemailer → SMTP (credenziali via `.env`) |
|
||||||
|
| Test | vitest (logica) + smoke test su build |
|
||||||
|
| Versionamento | git dal primo commit, remote su GitLab |
|
||||||
|
| Deploy (fase 2) | Dockerfile multi-stage + compose, gestito poi via Komodo sul VPS |
|
||||||
|
|
||||||
|
Motivazione: sito prevalentemente statico con una sola area dinamica (blog). Un'unica applicazione Node leggera evita la manutenzione di un CMS completo, mantiene ottime prestazioni e SEO, e resta estendibile (pagamenti in fase futura).
|
||||||
|
|
||||||
|
## Route
|
||||||
|
|
||||||
|
### Pubbliche
|
||||||
|
|
||||||
|
| Route | Contenuto | Fonte design |
|
||||||
|
|---|---|---|
|
||||||
|
| `/` | Homepage: hero slider, 3 colonne Performance/Balance/Longevity, feature alternata, banner citazione, Training (4 card), Programmi (6 icone), Agenda con tab, Team trainer, Metodo (4 step), loghi partner (Ticket Welfare Edenred, Welbee, AON, Howden), footer con mini-form | Homepage.pdf |
|
||||||
|
| `/about` | Mission, direzione, approccio, about, timeline "Storylab" (2021-2024 aperta; +2025, +2026, +oggi ad accordion), convenzioni aziendali, team completo (9 persone), metodo, IN-SANITY STUDIOS, vision | Insanitylab.pdf |
|
||||||
|
| `/training` | 4 servizi (One to One, Small Groups, Performance Class, Fit Remote) con blocchi alternati, agenda, CTA "prenota la lezione di prova" | Training.pdf |
|
||||||
|
| `/programs` | Griglia 6 programmi con testi reali | Programmi.pdf |
|
||||||
|
| `/programs/[slug]` | Pagina dettaglio per ogni programma: `personal-training`, `performance-class`, `coaching`, `pilates-flow`, `rehab`, `nutrition` | Performance class.pdf |
|
||||||
|
| `/blog` | Blog & Edugo: intro, filtri per categoria, griglia articoli, paginazione | Blog & Edugo.pdf |
|
||||||
|
| `/blog/[slug]` | Articolo singolo con sidebar (autore, categorie, ultimi articoli, archivio) | Articolo.pdf |
|
||||||
|
| `/contact` | Form contatti (Nome, Cognome, Telefono, E-mail, Messaggio), mappa Google, recapiti | Contatti.pdf |
|
||||||
|
|
||||||
|
Dettaglio programmi: layout unico modellato su Performance class.pdf (FAQ ad accordion, descrizione, sidebar categorie + altri programmi). Il blocco pricing compare solo dove esistono prezzi — al lancio solo `performance-class` (3 piani semestrali: 130/234/300 € al mese, con varianti trimestrale e mensile ad accordion). I bottoni "acquista" puntano per ora a `/contact`. I testi degli altri cinque programmi partono dalle descrizioni di Programmi.pdf; il cliente li integrerà.
|
||||||
|
|
||||||
|
### Admin (richiedono sessione)
|
||||||
|
|
||||||
|
| Route | Funzione |
|
||||||
|
|---|---|
|
||||||
|
| `/admin/login` | Login user/password |
|
||||||
|
| `/admin` | Elenco articoli (pubblicati e bozze) |
|
||||||
|
| `/admin/new` | Nuovo articolo |
|
||||||
|
| `/admin/edit/[id]` | Modifica articolo |
|
||||||
|
|
||||||
|
### API
|
||||||
|
|
||||||
|
| Endpoint | Funzione |
|
||||||
|
|---|---|
|
||||||
|
| `POST /api/contact` | Invio email form contatti (honeypot antispam + rate-limit) |
|
||||||
|
| `POST/PUT/DELETE /api/admin/posts*` | CRUD articoli (sessione richiesta) |
|
||||||
|
| `POST /api/admin/upload` | Upload immagini (copertina e corpo articolo, salvate in `public/uploads/`) |
|
||||||
|
|
||||||
|
## Design system
|
||||||
|
|
||||||
|
- **Palette** (valori esatti da campionare dai PDF in fase di implementazione): accento beige/tan ~`#b8a98a` (bottoni, etichette), marrone scuro ~`#3a2e28` (sezioni dark: agenda, banner citazione, footer, card scure), fondi chiari `#f5f3f0`/bianco.
|
||||||
|
- **Tipografia**: Montserrat uppercase con letterspacing largo per titoli e bottoni; Open Sans per il corpo. File woff2 self-hosted (niente Google Fonts CDN, conformità GDPR).
|
||||||
|
- **Componenti chiave**: header sticky (trasparente sopra l'hero, bianco con ombra allo scroll), hero slider (scroll-snap CSS + JS vanilla), card programma testo/foto alternate, agenda settimanale con tab per disciplina, accordion FAQ e pricing, form con stati di validazione.
|
||||||
|
- **Responsive**: mobile-first; il Figma è solo desktop (1366 px), il comportamento mobile si deriva dalle convenzioni del template (menu hamburger sotto i 992 px, griglie che collassano a colonna).
|
||||||
|
- **Immagini**: estratte dall'archivio `Web Insanity.fig` (è uno ZIP con cartella `images/`; i file hanno nomi hash e vanno identificati visivamente e rinominati per sezione). Fallback: asset in `Dati/` e estrazione da PDF con `pdfimages`. Ottimizzazione con `astro:assets` (webp, lazy loading, srcset).
|
||||||
|
- **SEO**: title/description per pagina, Open Graph, sitemap, robots.txt, favicon dal logo.
|
||||||
|
- **Mappa contatti**: iframe Google Maps con click-to-load (consenso prima del caricamento, GDPR).
|
||||||
|
|
||||||
|
## Backend
|
||||||
|
|
||||||
|
### Database
|
||||||
|
|
||||||
|
SQLite in `data/insanitylab.db` (fuori da `src/`, montabile come volume Docker in fase 2). Schema creato da script SQL idempotente all'avvio.
|
||||||
|
|
||||||
|
```sql
|
||||||
|
posts (id, title, slug UNIQUE, category, excerpt, body_html,
|
||||||
|
cover, published_at, draft, created_at, updated_at)
|
||||||
|
users (id, username UNIQUE, password_hash)
|
||||||
|
sessions (token PK, user_id, expires_at)
|
||||||
|
```
|
||||||
|
|
||||||
|
Categorie blog fisse (da Figma): Articoli tecnici & scientifici, Contenuti educativi, LinkedIn / Insight, Eventi & Presidi.
|
||||||
|
|
||||||
|
Il corpo articolo è HTML prodotto da TipTap, sanitizzato lato server prima del salvataggio e del rendering.
|
||||||
|
|
||||||
|
### Autenticazione
|
||||||
|
|
||||||
|
- Password con hash bcrypt; utenti creati via script CLI (`npm run create-user`).
|
||||||
|
- Sessione: token random in cookie httpOnly, SameSite=Lax, scadenza 7 giorni, verificata da middleware su tutte le route `/admin` e `/api/admin`.
|
||||||
|
- Rate-limit sul login (protezione brute force).
|
||||||
|
|
||||||
|
### Email
|
||||||
|
|
||||||
|
`POST /api/contact` valida i campi, applica honeypot e rate-limit, invia via nodemailer con SMTP configurato in `.env` (host, porta, credenziali, destinatario — default `info@insanitylab.it`). Risposta JSON per feedback inline nel form.
|
||||||
|
|
||||||
|
### Dati statici
|
||||||
|
|
||||||
|
Agenda settimanale, prezzi, team, programmi, loghi partner: file TypeScript/JSON in `src/data/`, modificati dallo sviluppatore e versionati in git. Nessuna gestione da admin per questi contenuti al lancio.
|
||||||
|
|
||||||
|
## Deploy
|
||||||
|
|
||||||
|
- **Fase attuale (locale)**: `npm run dev`; build verificata con `npm run build && npm run preview`.
|
||||||
|
- **Versionamento**: repository git con remote su GitLab (namespace da confermare in fase di implementazione).
|
||||||
|
- **Fase 2 (VPS)**: Dockerfile multi-stage (build → `node:22-slim`), `compose.yaml` con volumi per `data/` e `public/uploads/`, porta interna 4321; aggancio a Komodo e reverse proxy per `insanitylab.tielogic.xyz` quando si porterà in produzione. Fuori scope di questa spec.
|
||||||
|
|
||||||
|
## Gestione errori
|
||||||
|
|
||||||
|
- Form contatti: validazione client + server, messaggi di errore inline, fallback se SMTP non risponde (errore esplicito all'utente, log lato server).
|
||||||
|
- Admin: redirect a `/admin/login` se sessione assente/scaduta; conferma prima dell'eliminazione articoli.
|
||||||
|
- 404 personalizzata coerente col design.
|
||||||
|
- Upload: limite dimensione (5 MB) e whitelist tipi immagine.
|
||||||
|
|
||||||
|
## Test e verifica
|
||||||
|
|
||||||
|
- vitest su: helper slug, validazione form, auth (hash/sessioni), query posts.
|
||||||
|
- Smoke test: build completa senza errori; fetch delle route principali con risposta 200 e contenuti attesi.
|
||||||
|
- Verifica visiva locale contro i PDF Figma pagina per pagina.
|
||||||
|
|
||||||
|
## Fuori scope (fasi future)
|
||||||
|
|
||||||
|
- Pagamenti online piani Performance Class (Stripe o simile).
|
||||||
|
- Gestione da admin di agenda, prezzi, team.
|
||||||
|
- Porting su VPS, DNS, TLS (fase 2 dedicata).
|
||||||
|
- Ricerca nel blog e ricerca globale (icona lente del template: omessa al lancio).
|
||||||
|
- E-commerce/carrello (icona carrello nell'header Figma: omessa al lancio, era ereditata dal template).
|
||||||
Reference in New Issue
Block a user