06: Frontmatter e Markdown per il web
← 05 - Obsidian Flavored Markdown e portabilità · Indice · successivo → 07 - Strumenti, stile e trappole
6.1 Che cos’è il frontmatter
Un blocco di metadati in cima al file, delimitato da ---. Non è Markdown: è YAML
(per approfondire, il corso dedicato).
---
title: Configurare il server
description: Come preparare l'ambiente di sviluppo
pubDate: 2026-08-21
tags: [setup, server]
draft: false
---
## PrerequisitiChi lo supporta:
| Sistema | YAML --- | TOML +++ | Note |
|---|---|---|---|
| Obsidian | ✓ (unico) | ✗ | è il motore delle “Properties” |
| Astro | ✓ | ✓ | validato con Zod nelle content collections |
| Jekyll | ✓ | ✗ | obbligatorio: senza, il file non viene processato |
| Hugo | ✓ | ✓ | anche JSON |
| Pandoc | ✓ | ✗ | i valori stringa vengono parsati come Markdown |
Deve essere la primissima cosa del file: nemmeno una riga vuota prima.
6.2 Properties di Obsidian
Da Obsidian 1.4 il frontmatter ha un editor grafico. Il formato sul disco non è cambiato (è sempre YAML), ma ci sono regole da conoscere:
- Sette tipi: text, list, number, checkbox, date (
YYYY-MM-DD), date & time, tags. Il tipo è associato al nome della proprietà a livello di vault, non al singolo file. - Niente proprietà annidate. Questo è il limite che conta: uno schema con oggetti dentro oggetti non è editabile dall’interfaccia.
- Niente Markdown nei valori.
- I wikilink dentro le proprietà vanno fra virgolette:
nota: "[[Altra nota]]". - Proprietà speciali:
tags,aliases,cssclasses. - L’editor riscrive il file: normalizza il quoting, converte le liste in stile a blocchi, e può spostare o perdere i commenti. Se un file è condiviso con un altro sistema, aspettati diff spuri quando tocchi una proprietà dall’interfaccia.
6.3 Le tre trappole del frontmatter (che sono trappole YAML)
1. I valori ambigui vanno virgolettati.
paese: NO # ← in molti parser diventa false (Norvegia → falso)
versione: 1.10 # ← diventa il numero 1.1: hai perso la patch
cap: 01234 # ← diventa 1234, oppure 668 in ottale
orario: 12:30 # ← in YAML 1.1 diventa 750✅ verificato con PyYAML 6.0.3 e con lo schema core di YAML 1.2: sono tutti reali, e cambiano da parser a parser. Regola: qualsiasi codice, versione, identificatore o sigla va fra apici singoli.
2. Le date. pubDate: 2026-08-21 senza virgolette diventa un oggetto data in molti
parser (fra cui quello che usa Astro) e una stringa in altri. In Astro con Zod, usa
z.coerce.date(): funziona in entrambi i casi.
3. Il cancelletto. colore: #FF0000 produce un valore vuoto: il # preceduto da
spazio apre un commento. ✅ verificato. Va scritto colore: '#FF0000'.
6.4 Astro: dalle note al sito
Il modo corretto di gestire contenuto Markdown in Astro sono le content collections: dichiari uno schema, Astro valida ogni file e ti dà tipi TypeScript.
// src/content.config.ts
import { defineCollection } from 'astro:content';
import { glob } from 'astro/loaders';
import { z } from 'astro/zod';
const guide = defineCollection({
loader: glob({ base: './src/content/guide', pattern: '**/[^_]*.{md,mdx}' }),
schema: z.object({
title: z.string(),
description: z.string().optional(),
pubDate: z.coerce.date(),
draft: z.boolean().default(false),
tags: z.array(z.string()).default([]),
}),
});
export const collections = { guide };Il valore vero: se sbagli un campo del frontmatter, la build si ferma e ti dice dove. Su venti note scritte a mano in mesi diversi, questo è ciò che tiene insieme la baracca.
Lo schema come contratto fra Obsidian e il sito
Se le stesse note vivono in Obsidian e in Astro, tieni lo schema piatto (Obsidian non gestisce proprietà annidate) e usa gli stessi nomi di campo in entrambi. Ne guadagni anche in Obsidian: le viste “Bases” lavorano proprio sulle properties.
Da sapere: layout: nel frontmatter funziona per i .md dentro src/pages/, non
per le content collections (lì il layout lo decidi nella rotta).
6.5 MDX: quando serve e cosa ti costa
MDX è Markdown + JSX: puoi importare componenti e usare espressioni.
---
title: Setup
---
import Callout from '../../components/Callout.astro';
## Prerequisiti
<Callout tipo="attenzione">Serve Node 22.</Callout>Ma MDX toglie delle cose rispetto al Markdown normale:
- niente blocchi di codice indentati (l’indentazione serve al JSX) → solo fence;
- niente autolink
<https://esempio.it>(indistinguibili dal JSX); - niente commenti HTML
<!-- -->→ si usa{/* */}; <e{letterali vanno escapati (\<,\{).
Quest’ultimo punto è quello che rompe le build davvero: scrivere in prosa { "chiave": 1 }
o Set<string> o ${variabile} fa fallire la compilazione. La regola pratica: se una
frase contiene { o <, mettila fra backtick, dentro il codice non viene interpretato.
Il costo secondario, ma non trascurabile: un .mdx non è più leggibile in Obsidian
come nota normale.
Regola d’ingaggio: .md di default, .mdx solo quando quella pagina specifica ha
bisogno di un componente interattivo.
6.6 Markdoc, l’alternativa
{% callout type="warning" %}
Attenzione a questo passaggio.
{% /callout %}Markdoc usa tag dichiarativi invece di JSX: niente import, niente esecuzione di JavaScript arbitrario nel contenuto, e i tag sono validabili con uno schema. Ha senso quando il contenuto lo scrive qualcun altro (o arriva da un CMS) e vuoi una sandbox vera. Se scrivi da solo, MDX è più diretto.
6.7 Scrivere una volta, pubblicare ovunque
La strategia sostenibile, in tre regole:
- Il contenuto è
.mdstandard. Niente sintassi proprietaria nel testo. - I metadati stanno nel frontmatter, con nomi coerenti e valori sempre virgolettati quando ambigui.
- Le trasformazioni stanno nel generatore, non nel contenuto. Wikilink, callout, componenti: li converte la pipeline, non li scrivi due volte a mano.
Il testo così resta leggibile fra dieci anni, con qualsiasi editor. Che è poi il motivo per cui hai scelto Markdown invece di un formato proprietario.
Esercizi
- Aggiungi un frontmatter coerente alle ultime cinque note che hai scritto, usando gli stessi nomi di campo. Poi controlla in Obsidian che le properties siano tipizzate bene.
- Scrivi uno schema Zod per quelle cinque note e fai fallire la build di proposito con un campo sbagliato: leggi il messaggio d’errore.
- Metti
versione: 1.10ecodice: 007in un frontmatter e leggili da un parser (python3 -c "import yaml;print(yaml.safe_load(open('nota.md').read().split('---')[1]))"). Guarda cosa ti torna. - Prendi una nota
.mde convertila in.mdxcon un componente dentro. Nota cosa devi cambiare per farla compilare.