🧠 Obsidian · & le vault autoportant

Chapitre 03
Le front-matter : le contrat de données

Objectifs du chapitre

1. Un bloc YAML en tête de fichier

Une note peut commencer par un bloc délimité par deux lignes de trois tirets. Obsidian l'appelle « propriétés », le reste du monde l'appelle front-matter :

---
type: concept
title: Rétraction de bras
created: 2026-08-02
updated: 2026-08-02
scope: work
tags: [safety, siemens]
---

## Définition

Le corps de la note commence ici.

Le bloc doit être tout en haut du fichier, sans ligne vide avant. Un front-matter précédé d'un titre ou d'une ligne blanche n'est pas reconnu : il s'affiche comme du texte.

Obsidian affiche ce bloc sous forme de tableau éditable en haut de la note. Le mode source (Ctrl+E bascule) montre le YAML brut. L'éditeur de propriétés est confortable et il quote automatiquement ce qui doit l'être — un point qui aura son importance en section 4.

2. Les clés qu'Obsidian connaît

La plupart des clés sont libres : tu inventes les noms qui te servent. Quatre ont un sens particulier pour Obsidian :

CléEffet
tagsÉquivalent des #étiquettes du corps, mais déclarées proprement. À préférer : elles ne polluent pas le texte.
aliasesNoms alternatifs sous lesquels la note est atteignable par lien et par recherche.
cssclassesClasses CSS appliquées à la note — utile avec un extrait CSS pour, par exemple, élargir une note de tableau.
publishUtilisé par le service Obsidian Publish. Sans intérêt si tu ne l'utilises pas.

Tout le reste — type, status, repo, projects — n'existe que pour toi et pour tes requêtes.

3. Le typage des propriétés

Obsidian associe un type à chaque nom de propriété rencontré dans le vault : texte, liste, nombre, date, date et heure, case à cocher. Ce type gouverne l'éditeur — un champ typé « date » ouvre un calendrier — et il est global au vault, pas par note.

Ces associations vivent dans .obsidian/types.json :

{
  "types": {
    "aliases": "aliases",
    "cssclasses": "multitext",
    "tags": "tags",
    "created": "date",
    "status": "text"
  }
}

Le typage est déduit de la première valeur rencontrée, puis figé. Si ta toute première note écrit milestones: 3, la propriété devient un nombre pour tout le vault, et milestones: [étude, FAT] ailleurs deviendra incohérent.

Le remède est le même que pour le reste du chapitre : décide du schéma d'abord, et applique-le par template plutôt qu'à la main.

4. Les trois pièges de syntaxe

Un lien non quoté n'est pas un lien

C'est le piège le plus coûteux, parce qu'il est silencieux. En YAML, un crochet ouvrant démarre une liste. Donc :

projects: [[supervision]]      # ← PAS un lien

YAML lit une liste contenant une liste contenant la chaîne supervision. Ni Obsidian ni Dataview n'y verront un lien. Il faut quoter :

projects: ["[[supervision]]"]  # ← un lien, dans une liste
projects:
  - "[[supervision]]"         # ← même chose, forme longue

L'éditeur de propriétés d'Obsidian quote tout seul. Le piège ne se déclenche que si tu édites le YAML à la main, en mode source — ce qui arrive dès qu'on écrit un template.

Les deux-points coupent la valeur

title: Rétraction : le cas du bras 3   # ← YAML invalide
title: "Rétraction : le cas du bras 3" # ← correct

Un deux-points suivi d'une espace sépare une clé de sa valeur. Dans une valeur non quotée, il rend le document invalide — et un front-matter invalide n'est pas partiellement lu, il est ignoré en entier.

Les dates ne sont pas des chaînes

created: 2026-08-02       # ← une date pour YAML
created: "2026-08-02"     # ← une chaîne qui ressemble à une date

Les deux s'affichent pareil et se trient pareil tant que le format est ISO. La différence apparaît en requête : Dataview sait faire de l'arithmétique sur une date, pas sur une chaîne. Reste cohérent dans tout le vault, et le format ISO AAAA-MM-JJ te protège dans les deux cas.

5. Le front-matter comme contrat

Jusqu'ici, du confort. L'idée qui change tout est ailleurs : si le front-matter est régulier, il devient une base de données, et l'arborescence peut être plate.

Régulier veut dire quatre choses :

  1. Des champs obligatoires. Toute note en porte le même noyau — dans le vault de la partie II : type, title, created, updated, scope.
  2. Des énumérations fermées. type vaut daily, project ou concept, et rien d'autre. Trois valeurs, pas quarante.
  3. Des noms stables. Un seul nom par idée : jamais project ici et projects là.
  4. Quelque chose qui vérifie. Une convention que rien ne contrôle dérive en quelques semaines.

Voici le schéma du vault de la partie II, qui sert d'exemple fil rouge. Noms de champs et valeurs d'énumération en anglais, prose des notes en français : les clés accentuées sont pénibles à écrire dans les requêtes Dataview, et un contrat à moitié traduit obligerait à se rappeler de quel côté est chaque terme.

---
type: daily | project | concept  # énumération fermée
title: Rétraction de bras
created: 2026-08-02              # ISO, jamais modifié après création
updated: 2026-08-02              # mis à jour à chaque édition
scope: work | personal
tags: [safety]
---

Puis, selon le type :

# type: project
status: active | dormant | closed
repo: 100-industrial-supervision  # nom de dossier local, jamais une URL
milestones: []

# type: concept
sources: []
see_also: []

# type: daily
projects: ["[[supervision]]"]     # noter les guillemets

Pourquoi created et updated séparés

created ne change jamais après la création ; updated bouge à chaque édition. Cette séparation permet deux tris différents — « les fiches les plus récentes » et « ce que j'ai touché cette semaine » — et garde le tri chronologique stable quand on retouche une vieille note.

Pourquoi une énumération fermée

Parce qu'ouvrir type le condamne. En quelques mois tu auras meeting-notes, réunion, Réunion et meeting, et aucune requête ne pourra plus les traiter ensemble.

Trois valeurs, c'est peu, et c'est délibéré : ajouter un type doit coûter un effort conscient — modifier la convention, le template, la vue, dans le même commit.

Un champ mérite d'exister s'il répond à une question que tu te poses vraiment. « Quels projets sont actifs ? » justifie status. « Quelle est l'humeur de cette note ? » ne justifie rien : personne ne posera jamais la question, et le champ ne sera pas rempli au bout de trois semaines.

6. Vérifier plutôt qu'espérer

Un contrat sans contrôle est un vœu. Le vault de la partie II embarque un validateur, vault.py doctor, qui parcourt les notes et vérifie : front-matter présent, champs obligatoires renseignés, type et scope dans leur énumération, status présent et valide sur les projets, et aucun lien de projet pointant vers une note inexistante.

$ uv run --project 90-meta/tooling 90-meta/tooling/vault.py doctor
20-notes/temps-de-cycle.md : champ obligatoire manquant : scope
30-projets/supervision.md : status invalide : en cours
10-journal/2026/2026-08-01.md : project inconnu : superivsion
3 probleme(s)

Trois secondes d'exécution, et la dérive est nommée avant d'avoir contaminé cent notes. Le chapitre 10 détaille ce validateur.

Récapitulatif

Exercices

Exercice 1 — Trouver l'erreur

Ce front-matter ne produit rien dans les requêtes. Trois défauts, lesquels ?


---
type: Projet
title: Supervision : refonte du poste opérateur
status: en cours
projects: [[ruwais]]
---
Voir la solution

1. Le deux-points dans title. Non quoté, il rend le YAML invalide, et un front-matter invalide est ignoré en entier — c'est la cause première du « rien ne remonte ». À écrire title: "Supervision : refonte du poste opérateur".

2. type: Projet avec une majuscule, et status: en cours hors énumération. Une requête filtrant sur type = "project" et status = "active" ne verra jamais cette note. Le validateur les signale tous les deux.

3. projects: [[ruwais]] non quoté. YAML y lit une liste de liste de chaînes, pas un lien. À écrire projects: ["[[ruwais]]"].

À noter aussi : created, updated et scope manquent, mais c'est une omission, pas une erreur de syntaxe.

Exercice 2 — Concevoir un champ

Tu veux suivre l'avancement de tes projets plus finement que active / dormant / closed. Un collègue propose avancement: 65 (pourcentage). Argumente pour ou contre.

Voir la solution

Contre, dans la plupart des cas. Trois raisons :

  • Il ne répond à aucune question précise. « Quels projets sont actifs ? » se pose ; « quels projets sont entre 60 et 70 % ? » ne se pose jamais.
  • Il exige une mise à jour continue pour rester vrai. Un champ dont la valeur se périme en silence est pire qu'un champ absent : il fait croire à une information.
  • Le chiffre est arbitraire. 65 % de quoi ? Sans définition partagée, deux projets à 65 ne sont pas comparables.

Pour, à une condition : que le pourcentage soit dérivé plutôt que saisi — par exemple le ratio de jalons cochés, calculé par une requête. Là il ne se périme plus, puisqu'il est recalculé à l'affichage.

C'est la bonne réflexe général : préférer ce qui se calcule à ce qui se maintient.

Exercice 3 — Migrer sans tout casser

Ton vault contient 200 notes avec date:, et tu veux passer à created:. Comment procèdes-tu, et dans quel ordre ?

Voir la solution

L'ordre importe, parce que les vues et les templates dépendent du nom.

  1. Sauvegarder : le vault est sous git, donc commiter d'abord. C'est ce qui rend la suite sans risque.
  2. Renommer dans les fichiers, avec Obsidian fermé pour qu'il ne réécrive rien pendant l'opération :
    $ grep -rl '^date:' 20-notes 30-projets \
        | xargs sed -i 's/^date:/created:/'
    L'ancrage ^ évite de toucher un date: qui apparaîtrait au milieu d'une phrase.
  3. Mettre à jour templates et vues dans le même commit, sinon une note créée entre-temps repart avec l'ancien nom.
  4. Relancer le validateur et vérifier zéro problème, puis git diff --stat pour confirmer que seuls les fichiers attendus ont bougé.
  5. Nettoyer le typage : .obsidian/types.json garde une entrée date devenue orpheline. Sans conséquence, mais autant la retirer.

Et si le renommage se passe mal, git checkout . annule tout : c'est précisément pour ce genre de manipulation que le vault est versionné.