Files
InsanityLab-web/docs/superpowers/specs/2026-07-01-insanitylab-website-design.md
2026-07-01 23:11:45 +02:00

8.4 KiB

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.

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