# Pane di Triora, rifacimento sito: design

Data: 17 settembre 2026
Cliente: Panificio Asplanato Angiolino SAS, Corso Italia 37, 18010 Triora (IM)
Sito attuale: https://www.paneditriora.it (Umbraco, one-page, solo IT, realizzato da Sintesi)

## 1. Obiettivo

Sostituire il sito attuale con un sito statico moderno, multilingua, leggero, ottimizzato per SEO e per i motori generativi (GEO), ospitato gratis su Cloudflare Pages. Nessun CMS: le modifiche future le fa Paolo nel codice.

Il cliente sceglierà tra due versioni grafiche costruite sullo stesso codice e sugli stessi contenuti: **Notte** (scura, cinematica) e **Farina** (chiara, editoriale con l'arco). Vengono pubblicate entrambe su URL `*.pages.dev`; la vincente prende il dominio.

## 2. Vincoli e decisioni prese

| Tema | Decisione |
|---|---|
| Manutenzione | Nessuna da parte del cliente. Sito statico puro. |
| Lingue | IT, EN, FR, DE, ES, NL. Traduzioni fatte con AI da Paolo, revisione al cliente. |
| Lingua di default | EN (fallback del redirect). |
| Selettore lingua | Solo nel footer, tendina minimale con bandierina SVG + nome lingua nella propria lingua. Nessun selettore in testata. |
| Form contatti | Nessuno. Telefono, WhatsApp (347 7675695), email (da chiedere al cliente), mappa, social. |
| Social | Instagram https://www.instagram.com/paneditriora/ e Facebook https://www.facebook.com/paneditriora/. TikTok da verificare col cliente. |
| Video hero | Self-hosted, solo desktop, solo tema Notte. Su mobile foto statica. Farina usa la foto nell'arco anche su desktop. |
| Analytics | Cloudflare Web Analytics. Niente GA4, niente cookie, niente banner. |
| Shop | Link esterno a nuovabottegaitalia.com, come oggi. |
| Hosting | Cloudflare Pages, piano gratuito. |
| Dominio | Trasferimento di `paneditriora.it` da Aruba Business a IONOS. DNS su Cloudflare. |

## 3. Stack

- **Astro 7** (7.3 al 17/09/2026), output `static`, TypeScript strict. Compilatore Rust: tutti i tag vanno chiusi.
- Nessun framework UI. CSS puro con custom properties, un file globale + CSS scoped per componente.
- JS client minimo, vanilla, in tre punti: menu mobile, lightbox gallery (`<dialog>`), facade YouTube. Tendina lingua in CSS/HTML puro (`<details>`).
- Immagini via `astro:assets` (`<Image>` / `<Picture>`), formati AVIF + WebP + JPEG fallback.
- Integrazione `@astrojs/sitemap` con i18n per il `sitemap-index.xml` con hreflang.
- Deploy: `@astrojs/cloudflare` non serve (output statico). La root `/` è una Pages Function in `functions/index.ts`.
- Node 24 (minimo 22.12), pnpm. Font self-hosted tramite i pacchetti `@fontsource-variable/*` (woff2 con `unicode-range`, niente subsetting manuale).

## 4. Routing e i18n

Tutte le lingue con prefisso. La root smista.

```
/                      -> Pages Function: cookie `lang` > Accept-Language > /en/  (302)
/it/                   home
/it/prodotti/          elenco prodotti
/it/prodotti/<slug>/   scheda prodotto (7)
/it/panificio/         storia + gallery laboratorio
/it/triora/            territorio + gallery + come arrivare
/it/parlano-di-noi/    rassegna stampa
/it/contatti/          contatti
/it/privacy/           privacy
/it/note-legali/       note legali
```

Configurazione Astro i18n: `defaultLocale: "en"`, `locales: ["en","it","fr","de","es","nl"]`, `routing.prefixDefaultLocale: true`.

Slug delle sezioni tradotti per lingua (es. `/en/products/`, `/fr/produits/`, `/de/produkte/`, `/es/productos/`, `/nl/producten/`). Slug dei prodotti invariati in tutte le lingue (`pane-di-triora`, `pane-multicereali`, `grissini`, `pane-d-orzo`, `bruschette`, `biscotti-di-triora`, `biscottate-di-triora`): sono nomi propri e aiutano la coerenza degli URL.

Ogni pagina emette `<link rel="alternate" hreflang="xx">` per tutte le 6 lingue più `x-default` che punta alla versione EN. Il `<html lang>` è quello della pagina.

Il selettore nel footer scrive il cookie `lang` (1 anno, `SameSite=Lax`) e porta alla stessa pagina nell'altra lingua. La Pages Function legge il cookie prima di `Accept-Language`, così chi ha scelto a mano non viene rispedito indietro.

Totale pagine: 6 lingue × 15 = 90 pagine HTML più la root.

## 5. Contenuti

Cartella `src/content/`:

```
src/content/
  products/<lang>/<slug>.md     frontmatter: title, tagline, weight, ingredients, allergens, formats, image, order
  pages/<lang>/{panificio,triora,parlano-di-noi,contatti,privacy,note-legali}.md
  ui/<lang>.json                stringhe interfaccia, nav, footer, FAQ home
```

I 7 prodotti con i testi originali (in `_assets_originali/sito_originale/home.html`) come base per IT, tradotti nelle altre 5 lingue. Ingredienti e allergeni restano una lista strutturata nel frontmatter, non prosa, così vanno anche nello schema.

Testi hero e claim, allineati a ciò che il vecchio sito comunicava: "l'unico produttore", "da oltre sessant'anni", "aria e acqua di Triora", "controllate che sia quello con il marchio". La durata del pane resta riga di supporto ("nata per durare giorni"), non claim principale, finché il cliente non conferma un dato preciso.

Dati azienda in un unico `src/data/business.ts` (nome, indirizzo, P.IVA, telefoni, email, social, coordinate, orari) usato da footer, contatti e schema.

FAQ home: 5-6 domande (dove si compra, quanto dura, ingredienti, orari del pane caldo, spedizioni, differenza biscotti/biscottate), per lingua in `ui/<lang>.json`.

## 6. Pagine e SEO/GEO

| Pagina | Schema.org | Note |
|---|---|---|
| Home | `Bakery` (con `sameAs`, `geo`, `openingHours`, `telephone`), `FAQPage` | Hero, griglia 7 prodotti, teaser storia, fascia "marchio", FAQ, contatti rapidi |
| Prodotti | `ItemList` | |
| Scheda prodotto | `Product` + `BreadcrumbList` | Foto, descrizione, ingredienti, allergeni, formati, dove trovarlo, link shop, PDF tabelle nutrizionali |
| Panificio | `AboutPage` | Storia, gallery |
| Triora | | Territorio, gallery, come arrivare |
| Parlano di noi | | 3 link: YouTube (facade), Rai TG1, Striscia |
| Contatti | | Tel, WhatsApp, email, indirizzo, orari, mappa, social |
| Privacy, Note legali | | Testo minimo |

Trasversale: un solo H1 per pagina; `title` e `description` per pagina e lingua; Open Graph e Twitter card con immagine 1200×630 generata dal poster hero; `canonical`; `robots.txt`; `sitemap-index.xml`; `llms.txt` in radice con riassunto azienda, prodotti e link alle pagine EN e IT; `manifest.webmanifest` con le icone recuperate.

Orari di apertura: da chiedere al cliente. Finché non arrivano, lo schema non include `openingHours` e la pagina contatti mostra solo "pane caldo nel tardo pomeriggio, eccetto il sabato" (dal sito attuale).

## 7. Due temi, un codice

Tema scelto a build time da `THEME=notte | farina` (variabile d'ambiente, letta in `astro.config` e esposta come `import.meta.env.THEME`).

Cosa cambia tra i temi:

| Elemento | Notte | Farina |
|---|---|---|
| Colori | bg `#140C0A`, testo `#F2E6D3`, oro `#E0A43C`, bordeaux `#7A2E2A` | bg `#F4ECDC`, testo `#2B1A14`, bordeaux `#340005`, oro `#FCD255`, crosta `#B5541C` |
| Font display | Bricolage Grotesque | Fraunces |
| Font testo | DM Sans | Instrument Sans |
| Testata | marchio oro + wordmark bianco su trasparente sopra l'hero | marchio bordeaux + "Pane di Triora" in Fraunces, riga sotto |
| Hero home | full-bleed video (desktop) / foto (mobile), titolo grande in basso a sinistra, testo verticale "Valle Argentina" | griglia 2 colonne: testo a sinistra, foto nell'arco con sigillo marchio a destra, filigrana marchio |
| Griglia prodotti | card fotografiche scure con numero oro | fascia numerata su fondo crema, bordi sottili |
| Fascia "marchio" | riquadro bordeaux nella griglia | fascia bordeaux a tutta larghezza con foto |

Tutto il resto è identico: layout base, pagine interne, footer, contatti, gallery, schede prodotto (che nel tema Notte usano comunque sfondo chiaro per il testo lungo, con testata e footer scuri).

Implementazione: `src/styles/theme-notte.css` e `theme-farina.css` definiscono solo custom properties e `@font-face`; il layout importa quello giusto. Tre componenti hanno una variante per tema (`Header`, `HeroHome`, `ProductGrid`): file `X.notte.astro` e `X.farina.astro`, scelti da un piccolo `src/lib/theme.ts`.

Mockup di riferimento: `.superpowers/brainstorm/*/content/direzioni-visive-v4.html` (Notte = B) e `fusione-ac.html` (Farina).

## 8. Media

- Foto originali dedotte dei doppioni in `src/assets/photos/`. `<Picture>` con `widths=[480, 800, 1200, 1600]`, `formats=["avif","webp"]`, `alt` tradotto per lingua. Hero: `loading="eager"` e `fetchpriority="high"`; resto lazy.
- Marchio: `src/assets/logo/pittogramma.svg` (tracciato recuperato dall'SVG originale), colorato via `fill="currentColor"`. Wordmark: `PaneDiTriora.png` bianco 630×136, usato solo nel tema Notte; in Farina il nome è testo.
- Video hero (Notte): da `hero_background_39s_H81_c2oSi0E.mp4` (sorgente 1280×720, non si ingrandisce) taglio di 12-15 s in loop pulito, `hero.webm` (AV1) e `hero.mp4` (H.264), target < 1,5 MB ciascuno, senza audio, `hero-poster.jpg`. In `public/video/`. Markup `<video autoplay muted loop playsinline poster>` inserito solo con `min-width: 768px`, non se `prefers-reduced-motion: reduce`, e con `<source>` caricate lazy tramite `preload="none"` + script che avvia dopo `load`. Sotto 768 px: `<Picture>` statica.
- Gallery: griglia CSS, click apre `<dialog>` con la stessa immagine a 1600 px, frecce prev/next, chiusura con Esc. Un solo componente, ~40 righe di JS.
- YouTube: facade con poster locale, iframe creato al click con `youtube-nocookie.com`.
- Font: woff2 self-hosted in `public/fonts/`, subset latin + latin-ext, `font-display: swap`, `<link rel="preload">` del solo display font. Lithos Pro (font del wordmark) non viene usato come webfont per licenza.
- PDF tabelle nutrizionali in `public/docs/`.

Budget: home mobile < 300 KB trasferiti senza video; home desktop Notte < 2 MB con video; scheda prodotto < 250 KB.

## 9. Deploy, DNS, dominio

- Repo Git privato su GitHub (paoloalby/paneditriora). Due progetti Cloudflare Pages con upload diretto da CLI (`wrangler pages deploy`), senza collegare GitHub a Cloudflare: `paneditriora-notte` (build con `THEME=notte`) e `paneditriora-farina` (`THEME=farina`). Output `dist/`. Le anteprime escono con `noindex` (env `NOINDEX=true`).
- `public/_headers`: `Cache-Control: public, max-age=31536000, immutable` su `/_astro/*`, `/fonts/*`, `/video/*`; security headers base (`X-Content-Type-Options`, `Referrer-Policy`, `Permissions-Policy`, CSP con `frame-src youtube-nocookie.com google.com`).
- `public/_redirects`: `/it 301 /it/`, `/umbraco 410`.
- `functions/index.ts`: solo per `/`. Ordine: cookie `lang` valido, poi primo valore di `Accept-Language` che corrisponde a una delle 6 lingue, altrimenti `en`. Risposta 302 con `Vary: Accept-Language, Cookie`.
- Dominio: il cliente chiede a Aruba Business l'auth-code per `paneditriora.it` (scaduto il 16/09/2026, stato `autoRenewPeriod`: verificare subito che il rinnovo sia passato). Trasferimento su IONOS. Poi nameserver Cloudflare. Prima di cambiare DNS: export di tutti i record attuali, in particolare `MX mail.paneditriora.it` e relativi A, che vanno ricreati identici finché la posta non viene migrata (IONOS include caselle col dominio; decisione del cliente).
- Il progetto Pages scelto dal cliente prende `paneditriora.it` e `www.paneditriora.it`; l'altro si elimina.

## 10. Verifica

- `pnpm build` senza warning; `pnpm astro check` pulito.
- Script `scripts/check-i18n.mjs`: per ogni HTML in `dist/` verifica che esistano i 6 `hreflang` + `x-default` e che puntino a file esistenti. Fallisce se manca qualcosa.
- Link checker su `dist/` (es. `linkinator`), zero 404 interni.
- Lighthouse su home e una scheda prodotto, entrambi i temi, mobile e desktop: ≥ 95 su Performance, Accessibility, Best Practices, SEO.
- Rich Results Test su home (Bakery, FAQ) e su una scheda (Product).
- Controllo visivo in Chrome delle 6 lingue per home, prodotto, contatti in entrambi i temi, a 375 px e 1440 px.
- Root: `curl -H "Accept-Language: de-DE"` risponde 302 verso `/de/`; senza header verso `/en/`; con cookie `lang=fr` verso `/fr/`.

## 11. Fuori scopo

- CMS, area riservata, form, newsletter, e-commerce.
- Migrazione della posta (decisione separata del cliente).
- Blog o news.
- Traduzioni professionali (revisione fatta dal cliente).

## 12. Da chiedere al cliente

1. Conferma rinnovo dominio e disponibilità a chiedere l'auth-code a Aruba Business.
2. Email da pubblicare.
3. Orari di apertura del panificio.
4. Eventuale TikTok o altri social.
5. Se vuole il video hero anche su mobile (ora: no).
6. Un dato preciso sulla durata del pane, se vogliono farne un claim.
7. Caselle email attive sul dominio (per non perderle nel cambio DNS).
