Aller au contenu

#Les templates

Un template est un fichier JSON de templates/ qui compose une page : quelles sections, avec quels réglages, dans quel ordre. Il ne contient pas une ligne de HTML — le balisage est dans les sections, le template ne fait que les assembler.

C’est la séparation qui permet à un client de réorganiser sa page d’accueil sans ouvrir un fichier Liquid, et à un thème de servir sept gabarits avec les mêmes trente-cinq sections.

#La forme

templates/index.jsonjson
{
  "sections": {
    "hero": {
      "type": "hero",
      "settings": { "titre": "Un travail soigné, tenu dans les délais" },
      "blocks": {
        "b1": { "type": "argument", "settings": { "texte": "Devis gratuit" } },
        "b2": { "type": "argument", "settings": { "texte": "Intervention sous 48 h" } }
      },
      "block_order": ["b1", "b2"]
    },
    "prestations": {
      "type": "prestations",
      "settings": { "colonnes": "3", "fond": "voile" }
    }
  },
  "order": ["hero", "prestations"]
}

Deux clés à la racine, et c’est tout.

sectionsobjetrequis

Les instances de section, indexées par un identifiant libre. La clé n’est pas le type : c’est ce qui permet de poser deux fois la même section sur une page, avec des réglages différents.

ordertableau

L’ordre d’affichage, par identifiant. Facultatif : sans lui, on prend l’ordre des clés de sections. C’est ce que fait Shopify pour les templates écrits à la main, et cela évite qu’un template parfaitement valable soit refusé pour une clé manquante.

#Ce qu’une instance peut porter

typechaînerequis

Le nom du fichier de section, sans sections/ ni .liquid. "type": "prestations" fait chercher sections/prestations.liquid.

settingsobjet

Les valeurs des réglages, par id. Elles recouvrent les default du schéma de la section.

blocksobjet

Les blocs, indexés par identifiant. Voir Les blocs.

block_ordertableau

L’ordre des blocs. Fait foi quand il existe.

disabledbooléendéfaut : false

true retire la section du rendu sans la supprimer du fichier. Le contenu est conservé, la section n’apparaît plus.

Astuce

Une clé de sections absente d’order n’est pas rendue, et une entrée d’order qui ne correspond à aucune section est ignorée en silence. Les deux sont utiles — la première pour mettre une section de côté, la seconde pour supprimer une section sans nettoyer l’ordre — et les deux font disparaître du contenu sans un mot. C’est le premier endroit à regarder quand une section « n’apparaît pas ».

#L’ordre de résolution — trois niveaux

Une page du CMS demande un gabarit. Le moteur cherche, dans cet ordre :

  1. templates/<nom>.json

    Le gabarit dédié. Une page « Contact » avec templates/contact.json obtient exactement la composition prévue pour elle.

  2. templates/page.json

    Le gabarit générique des pages libres. C’est le maillon qui compte, et il est expliqué ci-dessous.

  3. templates/index.json

    Le dernier recours. Il est requis dans tout thème, donc ce niveau répond toujours — sauf si son JSON est cassé.

Si aucun des trois ne répond, la page rend une chaîne vide et l’erreur Aucun template pour « <nom> ».

Ces trois niveaux valent pour les pages du CMS. Le blog a ses deux gabarits à lui, sans repli : voir Le blog.

#Ce que page.json répare

Danger

Sans templates/page.json, une page « Tarifs » sans gabarit dédié retombait sur index.json — c’est-à-dire affichait la page d’accueil entière, bandeau, prestations et avis compris, sous un autre titre. Chaque page nouvelle était donc un doublon de l’accueil : ce que Google sanctionne, et ce qu’aucun client ne comprend.

D’où la forme d’un page.json : une tête neutre et un corps vide, prêts à recevoir du contenu.

themes/origo/templates/page.jsonjson
{
  "sections": {
    "tete": {
      "type": "hero-sobre",
      "settings": { "surtitre": "", "titre": "", "texte": "" }
    },
    "corps": {
      "type": "texte",
      "settings": {},
      "blocks": {
        "b1": {
          "type": "paragraphe",
          "settings": {
            "texte": "Cette page attend son contenu. Ajoutez-y les sections que vous voulez depuis l'éditeur, ou demandez à Cosa de la rédiger pour vous."
          }
        }
      },
      "block_order": ["b1"]
    }
  },
  "order": ["tete", "corps"]
}

Les titres sont volontairement vides : la section hero-sobre masque ce qui est blank, la page affiche donc une tête sobre sans texte parasite, et non « Un travail soigné, tenu dans les délais » sur la page « Mentions légales ».

Astuce

Écris page.json en premier, avant même index.json. C’est lui qui décide de ce à quoi ressemble une page dont personne ne s’est occupé — et il y en aura toujours.

#Les gabarits des thèmes d’origine

ThèmeTemplates
aplombindex, page, contact, a-propos, prestations, tarifs, realisations
cadenceindex, page, contact, a-propos, prestations, tarifs, planning
epureindex
forgeindex, page, contact, a-propos
origoindex, page, contact, a-propos, prestations, tarifs, realisations
piazzaindex, page, contact, a-propos
sceneindex, page, contact, a-propos, prestations, tarifs, realisations
velaindex, page, contact, a-propos

Aucun ne déclare encore blog ni article : leurs blogs sont rendus par la plateforme. Voir Le blog.

Sept d’entre eux déclarent au minimum index, page, contact et a-propos : ce sont les pages qu’un site vitrine a toujours. origo, aplomb, cadence et scene vont plus loin parce qu’ils visent tous les métiers ; epure n’a que son index, sur lequel toutes ses pages retombent — c’est exactement le doublon d’accueil décrit plus haut, une dette de ce thème et non un modèle à copier.

themes/origo/templates/contact.json — extraitjson
{
  "sections": {
    "tete": {
      "type": "hero-sobre",
      "settings": {
        "surtitre": "Écrivez-nous",
        "titre": "Nous contacter",
        "texte": "On vous répond sous 48 h, toujours par une personne."
      }
    },
    "contact": { "type": "contact", "settings": { "surtitre": "", "titre": "", "texte": "" } },
    "acces": {
      "type": "acces",
      "settings": { "fond": "voile" },
      "blocks": {
        "b1": { "type": "info", "settings": { "intitule": "Adresse", "detail": "12 rue de l'Exemple\n69000 Lyon" } },
        "b2": { "type": "info", "settings": { "intitule": "Téléphone", "detail": "04 00 00 00 00" } }
      },
      "block_order": ["b1", "b2"]
    }
  },
  "order": ["tete", "contact", "acces"]
}

Deux choses à noter. La section contact reçoit des titres vides parce que la tête les a déjà écrits : deux « Nous contacter » à la suite, c’est ce qu’on obtient quand on laisse les défauts partout. Et "detail" contient \n — dans un fichier JSON, l’échappement standard fonctionne ; c’est dans une chaîne Liquid qu’il ne fonctionnerait pas.

#La même section, deux fois sur une page

C’est tout l’intérêt d’indexer par identifiant plutôt que par type :

json
{
  "sections": {
    "services-particuliers": {
      "type": "prestations",
      "settings": { "titre": "Pour les particuliers", "colonnes": "2" }
    },
    "services-pros": {
      "type": "prestations",
      "settings": { "titre": "Pour les professionnels", "colonnes": "3", "fond": "voile" }
    }
  },
  "order": ["services-particuliers", "services-pros"]
}

Chaque instance reçoit son propre section.id, ce qui permet à la section de fabriquer des ancres uniques.

#Le blog : blog.json et article.json

Le blog d’un site — /blog, /blog/<blog>, /blog/<blog>/<article> — n’est pas une page du CMS : les articles s’écrivent dans le CMS, et c’est la plateforme qui les sert. Par défaut, elle les sert dans sa propre page : sobre, aux couleurs du site, mais sans l’en-tête, le menu, le pied ni les polices de ton thème. Sur un thème fait sur mesure, le blog a alors l’air d’un autre site, et le visiteur n’a plus de menu pour revenir.

Un thème qui veut habiller son blog déclare l’un des deux gabarits, ou les deux, comme chez Shopify. La page est alors rendue comme toutes les autres : la coquille, ses sections d’en-tête et de pied, puis les sections du gabarit.

templates/article.json

Un article : /blog/<blog>/<article>. Le contexte porte l’objet article — titre, date, image, contenu — et blog, celui de l’article, avec ses articles pour un « À lire aussi ».

templates/blog.json

Les listes. /blog/<blog> montre les articles d’un blog ; /blog montre directement les articles quand le site n’a qu’un blog (ou aucun), et le sommaire des blogs quand il en a plusieurs. Les trois passent par ce gabarit, avec l’objet blog. Le sommaire se reconnaît à page.adresse == '/blog' avec blog.blogs.size > 1.

Les deux sont indépendants : un thème qui ne déclare que article.json habille ses articles, et ses listes restent celles de la plateforme.

Attention

Aucun repli. C’est le fichier qui décide, et lui seul : sans templates/article.json, l’article est rendu par la plateforme — jamais par page.json ni par index.json, qui ne savent pas afficher un texte d’article. Un fichier présent mais illisible (JSON cassé, clé sections absente) a le même effet : la plateforme reprend la main, plutôt que de servir une page vide comme le ferait une page ordinaire.

templates/article.jsonjson
{
  "sections": {
    "article": { "type": "article" },
    "suite": { "type": "a-lire-aussi", "settings": { "nombre": 3 } }
  },
  "order": ["article", "suite"]
}
sections/article.liquidliquid
<article class="article">
  <a class="retour" href="{{ article.blog.adresse }}">← {{ article.blog.titre }}</a>
  <h1>{{ article.titre }}</h1>
  {%- if article.date != blank -%}
    <time datetime="{{ article.date }}">{{ article.date | date_fr }}</time>
  {%- endif -%}
  {%- if article.image != blank -%}
    <img src="{{ article.image }}" alt="" width="1600" height="900">
  {%- endif -%}
  <div class="article-corps">{{ article.contenu }}</div>
</article>

Le <h1> est à toi : le corps de l’article commence à <h2>. Et article.contenu est du HTML déjà rendu — pose-le tel quel, sans escape, et mets-le en forme dans ta feuille de style : la plateforme n’y ajoute aucun style.

Ce que la plateforme garde, quel que soit le gabarit : la porte d’un site protégé, la 404 d’un blog ou d’un article inconnu, les brouillons (seuls les articles publiés sont servis), et les métadonnées — titre, description, canonique, fil d’Ariane et BlogPosting. Ta coquille n’a pas à les reposer. Voir La coquille.

#Ce qui n’est pas dans un template

L’en-tête, le pied, la barre d’annonce. Ils apparaissent sur toutes les pages, donc c’est la coquille qui les pose avec {% section %}, et leurs valeurs vivent dans config/settings_data.json sous current.sections. Voir La coquille.

Les réglages globaux. Couleurs, largeur, typographie : ils valent pour le thème entier. Voir Réglages globaux.

#Ce qui se passe quand le JSON est cassé

lireTemplate rend null, et la page rend une chaîne vide avec l’erreur Aucun template pour « <nom> ». La coquille n’est même pas rendue.

Attention

C’est le seul fichier du thème dont une erreur produit une page vide, et non un simple commentaire HTML. Un .json est vérifié à l’écriture par l’API — JSON invalide : <message de l'analyseur> — donc l’accident vient rarement de l’éditeur du CMS. Il vient d’un import, ou d’un fichier écrit hors ligne et poussé par le CLI.

Un template dont le JSON est valide mais auquel il manque la clé sections est traité de la même façon : null, page vide. La clé order, elle, est facultative.

#Le rendu, dans l’ordre

  1. Les instances sont sélectionnées

    order est parcouru, chaque identifiant est cherché dans sections. Les absents sont écartés, les disabled aussi.

  2. Les blocs sont ordonnés

    Pour chaque instance, block_order — ou l’ordre des clés — donne le tableau section.blocks.

  3. Les sections sont rendues en parallèle

    Chacune avec son propre section, et le contexte complet du site. Une section ne voit ni les autres, ni ce qu’elles ont produit.

  4. Les HTML sont concaténés, puis la coquille est rendue

    Les résultats sont joints par un saut de ligne, et cette chaîne devient content_for_layout.

#Pages voisines