- SCSS 48.6%
- HTML 39.5%
- JavaScript 9.2%
- Shell 2.7%
|
|
||
|---|---|---|
| archetypes | ||
| assets | ||
| content | ||
| data | ||
| layouts | ||
| scripts | ||
| static | ||
| .gitignore | ||
| .woodpecker.yml | ||
| hugo.toml | ||
| README.md | ||
Linux Day Prato 2026 website
Sito ufficiale del Linux Day Prato 2026, generato con Hugo. Stile neobrutalista: colorato, ad alto contrasto, con ombre nette e bordi marcati.
Requisiti
- Hugo extended 0.165 (versione pinnata in CI,
.woodpecker.yml) (la versione extended serve per compilare lo SCSS). Verifica conhugo version: deve contenere+extended. - Git, con la cronologia completa del repository, per calcolare le date di ultima modifica delle pagine.
Comandi
./scripts/build.sh server # anteprima live su http://localhost:1313
./scripts/build.sh # build di produzione in public/ (HTML già minificato via config)
Struttura
.
├── hugo.toml # configurazione + parametri evento (DATA, contatti, CFP…)
├── content/_index.md # front matter della home (titolo/descrizione)
├── content/cfp.md # front matter della pagina /cfp/ (SEO)
├── data/ # ← TUTTI I CONTENUTI MODIFICABILI (YAML)
│ ├── navigation.yaml # voci di menu
│ ├── stats.yaml # numeri dell'hero
│ ├── marquee.yaml # parole della striscia scorrevole
│ ├── about.yaml # testo "Cos'è" + card
│ ├── schedule.yaml # programma + sale
│ ├── speakers.yaml # speaker
│ ├── cfp.yaml # testi della pagina Call for Papers
│ ├── partners.yaml # partner e comunità
│ ├── location.yaml # sede, mappa, indicazioni
│ ├── footer.yaml # colonne e testi del footer
│ └── social.yaml # link social
├── assets/
│ ├── scss/ # stili (compilati da Hugo Pipes)
│ │ ├── main.scss # entrypoint con gli @import
│ │ ├── _variables.scss # colori, ombre, breakpoint
│ │ ├── _fonts.scss # @font-face dei font self-hostati
│ │ ├── _base.scss _animations.scss _utilities.scss
│ │ └── components/ # uno SCSS per sezione/pagina
│ ├── icons/lucide/ # icone SVG vendorizzate (inline via partial icon.html)
│ ├── touch-icon.svg # sorgente di apple-touch-icon.png / favicon-96x96.png
│ └── js/main.js # menu mobile, countdown, filtri, pausa marquee, scroll reveal
├── layouts/
│ ├── _default/baseof.html # scheletro HTML
│ ├── _default/cfp.html # pagina Call for Papers
│ ├── index.html # home: assembla le sezioni
│ ├── 404.html
│ └── partials/ # head, header, footer, countdown, schema, scripts, icone
│ └── sections/ # hero, about, schedule, speakers, …
├── scripts/build.sh # build + lastmod automatici dalla cronologia Git
└── static/
├── favicon.svg apple-touch-icon.png favicon-96x96.png
└── fonts/ # woff2 self-hostati (Space Grotesk, Space Mono)
CI/CD
Pipeline Woodpecker in .woodpecker.yml: ogni push/PR compila il sito; sul
push in main fa anche il deploy con rsync sul VPS. Secret da configurare in
Woodpecker (repo → Settings → Secrets, evento push):
| Secret | Valore |
|---|---|
deploy_ssh_key |
chiave privata SSH dedicata, senza passphrase (ssh-keygen -t ed25519 -f deploy_key -N ''; la .pub va in authorized_keys sul VPS) |
deploy_known_hosts |
output di ssh-keyscan -H <host> |
deploy_host |
hostname o IP del VPS |
deploy_user |
utente SSH (non root, con scrittura sul path) |
deploy_path |
directory servita dal webserver, es. /var/www/day.linux.prato.it |
Fasi del sito
Il sito cambia faccia da solo, in base a tre flag booleani indipendenti in
hugo.toml. Sono indipendenti apposta: la sede può confermarsi a proposte
ancora aperte, e fra la chiusura della CFP e la scelta dei talk esiste una fase
intermedia in cui non c'è né una CFP da proporre né un programma da mostrare.
| Flag | Cosa accende |
|---|---|
params.cfp.open |
pagina /cfp/ attiva, CTA "Proponi un talk" in navbar e hero, invito "il palco è libero" al posto degli speaker, link /cfp/ negli slot liberi del programma |
params.programPublished |
sezione "Programma" in home, voce Programma in menu e footer, numeri di talk e speaker nell'hero, griglia speaker, performer nei dati strutturati |
params.locationConfirmed |
sezione "Dove", voce Dove in menu e footer, sede completa (via, coordinate) nei dati strutturati |
Le tre combinazioni che il sito attraversa in un anno:
- CFP aperta (
cfp.open = true,programPublished = false) — si raccolgono le proposte, programma e speaker non esistono ancora. - CFP chiusa, programma da decidere (entrambi
false) — le proposte sono in valutazione: niente più CTA, la sezione Speaker annuncia che il programma arriva, il Programma resta fuori pagina. - Programma pubblicato (
cfp.open = false,programPublished = true) — versione finale: programma e speaker online.
Gli elementi che seguono uno di questi flag sono marcati nei rispettivi YAML con
programHide: true (voci di menu e footer, numeri dell'hero) o
locationHide: true, e la regola di visibilità sta tutta in
layouts/partials/nav-hidden.html.
Il resto della Call for Papers:
email,deadlineDisplay→ destinatario della mail precompilata e data mostrata;formUrl(opzionale) → se valorizzato, i bottoni aprono il form al posto della mail.- Testi della pagina →
data/cfp.yaml(hero, formati, passi, blocco d'invio col modelloproposta.md). Il lead della CFP chiusa ha due versioni:closed(programma non ancora deciso) eclosedProgram(programma online).
Come aggiornare i contenuti
Quasi tutto si modifica nei file data/*.yaml senza toccare l'HTML:
- Data dell'evento e countdown →
hugo.toml(eventStart,eventEnd,eventDateDisplay). - Call for Papers → apertura/chiusura in
hugo.toml, testi indata/cfp.yaml(vedi sezione sopra) - Programma →
data/schedule.yaml; le descrizioni accettano Markdown. Usadesc: |-e una riga vuota tra i paragrafi;**testo**aggiunge enfasi. La sezione va online solo conparams.programPublished = true: finché èfalseil file si lavora come bozza, senza che nulla finisca in pagina. - Speaker →
data/speakers.yaml; le foto ottimizzate sono instatic/img/speakers/. Nelle schede comparerole, la qualifica professionale confermata per l'evento (eventuale fonte inroleSource); se manca, la riga è omessa.topicconserva il titolo del talk perllms.txt. - Partner →
data/partners.yaml - Mappa / indicazioni →
data/location.yaml
Il lastmod è completamente automatico: non va aggiunto né aggiornato nel
front matter. scripts/build.sh trova l'ultimo commit che ha modificato una
dipendenza effettiva della pagina (contenuto, dati, configurazione, template,
CSS, JavaScript o asset) e inietta la stessa data in <lastmod> del sitemap,
WebPage.dateModified e og:updated_time. Home e CFP hanno insiemi di
dipendenze separati, per evitare aggiornamenti fittizi. Le modifiche locali non
committate non cambiano la data: in produzione la fonte di verità è il commit
distribuito dalla CI, che usa sempre la cronologia Git completa.
Prima di trasformare il sito nell'edizione successiva, conserva il 2026 a un
URL permanente e aggiorna params.eventUrl, params.eventId, date, immagini e
testi. eventId identifica una singola edizione e non deve essere riciclato:
evita che motori di ricerca e knowledge graph fondano eventi di anni diversi.
Note tecniche
- CSS/JS: compilati, minificati (in produzione) e fingerprinted con Subresource Integrity tramite Hugo Pipes.
- Font: self-hostati in
static/fonts/(woff2, subset latin), nessuna richiesta a Google Fonts.@font-faceinassets/scss/_fonts.scss. - Icone: set Lucide vendorizzato in
assets/icons/lucide/e inserito inline dal partialicon.html, nessun CDN a runtime. Per aggiungerne una:curl -o assets/icons/lucide/<nome>.svg "https://api.iconify.design/lucide/<nome>.svg?height=1em" - SEO: meta description, Open Graph, Twitter Card, dati strutturati
schema.org/Event(JSON-LD, sede letta dadata/location.yaml, organizzatori effettivi dadata/organizers.yaml),sitemap.xmlerobots.txtgenerati da Hugo. - Accessibilità: skip-link,
aria-*su menu e filtri, focus visibile, pulsante pausa per la striscia scorrevole (preferenza ricordata in localStorage), supporto aprefers-reduced-motion. - Social card:
static/img/social-card.pngè la card CFP;static/img/social-card-event.pngè quella del programma. Le composizioni 16:9, 4:3 e 1:1 configurate inparams.eventImagesalimentanoschema.org/Event.image.