Aller au contenu

#Créer son premier thème

À la fin de ce guide, un site Webcosa rendra avec un thème Liquid que tu auras sur ton disque, dans ton éditeur, sous ton Git — et un changement de couleur mettra une dizaine de secondes à se retrouver en ligne. On part d’un site vide et on ne saute aucune étape.

Le parcours en une phrase : installer un thème d’origine, le publier, le récupérer sur sa machine, le modifier, le repousser. Cinq gestes, dont trois ne se font qu’une fois.

Attention

Fais ce guide sur un site qui n’est pas encore devant des clients — un site d’essai, ou une préproduction. On y publie un thème dès la deuxième étape, et publier change ce que voient les visiteurs. Un site en ligne se traite autrement : voir La boucle locale et Publier.

#Avant de commencer

Node.js≥ 20.13requis

Vérifie avec node --version — Node 22 LTS ou 24 est le choix recommandé, et Installation dit d’où vient le plancher. Le CLI n’a aucune dépendance : le fichier scripts/theme.mjs se suffit à lui-même et peut être copié hors du dépôt.

Un site actif dans ton compterequis

Un site suspendu ou dont l’essai est terminé refuse toute écriture de thème avec Ce site n'est plus actif (402).

Un éditeur qui connaît Liquid

Facultatif mais confortable. Le format est celui de Shopify : n’importe quelle extension « Shopify Liquid » colore correctement sections/*.liquid.

#Le parcours

  1. Installer un thème d’origine

    Dans le CMS, ouvre Site web. En bas de l’écran, la section Installer un thème liste les thèmes d’origine que ce site n’a pas encore : Origo, Forge, Vela, Piazza. Chacun affiche à qui il s’adresse et trois traits qui le distinguent.

    Prends Forge pour ce guide — c’est le plus court des quatre, donc le plus facile à lire en entier.

    Ce que tu dois voir : un message « « Forge » est installé, en brouillon. », et une nouvelle ligne dans Brouillons, au-dessus de la section d’installation. La carte « Forge » disparaît de la liste des thèmes disponibles — on ne propose pas deux fois le même.

    Note

    Le catalogue de store.webcosa.com n’est pas celui-ci. Le Store installe des réglages et une page d’accueil pour l’ancien moteur de rendu ; les thèmes Liquid, eux, s’installent depuis l’écran Site web du CMS et de nulle part ailleurs. Les deux moteurs coexistent — voir Anatomie d’un thème.

  2. Le publier

    Sur la ligne « Forge » des brouillons, clique Publier. Une confirmation nomme ce qui va changer, puis le site bascule.

    Pourquoi si tôt ? Parce qu'un thème brouillon ne se prévisualise pas. Il n’existe aucune adresse qui rende le site avec un thème non publié : le rendu public cherche le thème de rôle publie, et lui seul. Tant que Forge reste brouillon, tu écriras du Liquid sans jamais voir le résultat.

    Ce que tu dois voir : « « Forge » est en ligne. », la ligne quitte les brouillons et remonte en haut de l’écran avec la pastille En ligne, et l’aperçu en haut de page montre le nouveau thème. Ouvre l’adresse publique du site dans un onglet : la page d’accueil de Forge s’affiche, avec ses textes d’exemple.

    Astuce

    La publication crée au passage une page d’accueil au site s’il n’en avait pas. C’est délibéré : publier un thème, c’est mettre le site en ligne, et un site en ligne sans page d’accueil n’a nulle part où poser un titre.

  3. Créer une clé d’API

    Le CLI ne connaît pas les cookies du navigateur. Il s’authentifie avec une clé, qui se crée dans le CMS : Réglages → Clés d’API.

    Choisis la portée themes : lecture ne permet que lister et recuperer, et tu vas pousser.

    Danger

    Le secret — wc_ suivi de 43 caractères — ne s’affiche qu’une fois. La base n’en garde que l’empreinte : personne, pas même nous, ne peut te le rendre. Copie-le maintenant. Perdue, une clé se révoque et se remplace, elle ne se retrouve pas.

  4. Connecter le CLI

    node scripts/theme.mjs connexion

    La commande demande l’adresse du CMS, puis la clé — sans l’afficher à l’écran. Elle la vérifie avant de l’écrire dans ~/.webcosa/config.json, en 0600. Une clé qui ne marche pas n’est pas enregistrée : la découvrir maintenant vaut mieux que trois commandes plus tard.

    Ce que tu dois voir :

    ✓ Clé enregistrée dans /Users/toi/.webcosa/config.json (0600)
      https://cms.webcosa.com — site Mon Client (mon-client), 1 thème visible.
      Thème publié : Forge

    La ligne « site … » est celle qu’il faut lire deux fois. Sans --site=, le serveur retient le premier site accessible à la clé, et cet ordre change dès qu’un site s’ajoute au compte. Si le nom affiché n’est pas celui que tu visais, relance avec --site=<slug>.

  5. Voir ce qu’il y a sur le site

    node scripts/theme.mjs lister id nom version rôle modifié 11111111 Forge 1.0.0 publié il y a 3 min

    L’identifiant court — les huit premiers caractères — suffit partout où l’on attend un --theme=. Le nom aussi.

  6. Récupérer le thème sur le disque

    node scripts/theme.mjs recuperer --theme=Forge --dossier=~/webcosa/forge

    Ce que tu dois voir :

    ✓ 23 fichiers de « Forge » écrits dans /Users/toi/webcosa/forge
      .webcosa.json y a été posé : les prochaines commandes n'ont plus besoin d'options.

    Le dossier contient exactement les six dossiers du format :

    ~/webcosa/forge
    assets/theme.css
    config/settings_data.json
    config/settings_schema.json
    config/theme.json
    layout/theme.liquid
    sections/annonce.liquid
    sections/appel.liquid
    sections/avis.liquid
    
    snippets/bouton.liquid
    snippets/section-tete.liquid
    templates/a-propos.json
    templates/contact.json
    templates/index.json
    templates/page.json
    .webcosa.json

    .webcosa.json dit quel site et quel thème. Il est versionnable et ne contient jamais la clé — celle-ci vit dans ~/.webcosa/config.json. Un fichier de projet qui contiendrait le secret finirait poussé sur GitHub le jour même.

    Attention

    N’utilise pas --dossier=themes/… depuis la racine du dépôt du CMS : ce themes/ est celui des thèmes d’origine, compilés au catalogue et proposés à tous les sites. Le CLI t’avertit si tu le fais. Voir Ajouter un thème au catalogue.

  7. Se placer dans le dossier

    cd ~/webcosa/forge

    À partir d’ici, plus aucune option n’est nécessaire : le CLI cherche .webcosa.json dans le dossier courant puis dans ses parents, comme git avec .git. Lancé de n’importe quel sous-dossier du thème, il retrouve le site et le thème visés.

  8. Lire la coquille

    Ouvre layout/theme.liquid. C’est le HTML qui entoure toutes les pages du site — le seul fichier que le rendu exige d’abord, et sans lequel le thème est purement et simplement ignoré.

    layout/theme.liquidliquid
    <!doctype html>
    <html lang="fr">
      <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>{{ page.titre }} — {{ site.nom }}</title>
        {{ 'theme.css' | asset_url | stylesheet_tag }}
    
        <style>
          :root {
            --encre: {{ settings.encre }};
            --papier: {{ settings.papier }};
            --accent: {{ settings.accent }};
            --accent-sombre: {{ settings.accent | teinte: -25 }};
            --trait: {{ settings.encre | teinte: 80 }};
            --largeur: {{ settings.largeur }}px;
          }
        </style>
      </head>
      <body>
        <a class="saut" href="#contenu">Aller au contenu</a>
    
        {% section 'annonce' %}
        {% section 'entete' %}
    
        <main id="contenu">{{ content_for_layout }}</main>
    
        {% section 'pied' %}
      </body>
    </html>

    Trois choses à retenir de ce fichier, elles reviendront partout :

    • content_for_layout est le trou par lequel la page entre. Les sections du template s’y déversent, dans l’ordre.
    • {% section 'entete' %} rend une section directement depuis la coquille. Ses valeurs ne vivent pas dans un template mais dans config/settings_data.json, sous current.sections. C’est ce qui rend l’en-tête et le pied modifiables comme le reste.
    • Les réglages deviennent des variables CSS, posées une seule fois sur la racine. Toute la feuille de style suit ensuite un changement de couleur sans qu’on la touche.
    Danger

    asset_url prend le nom seul du fichier, jamais son chemin : {{ 'theme.css' | asset_url }}, et surtout pas {{ 'assets/theme.css' | asset_url }}. L’adresse produite est /theme-assets/<id>/theme.css — un seul segment — et c’est la route qui remet le préfixe assets/. Écrire le chemin complet fabrique une adresse à deux segments qui ne correspond à aucune route : la feuille de style répond 404, et la page rend quand même, en HTML nu. Aucune erreur, un site qui ressemble juste à un thème mal écrit. C’est le bug le plus coûteux que ce format ait produit.

  9. Changer une couleur

    Ouvre config/settings_data.json. Ce sont les valeurs des réglages globaux pour ce site — leurs déclarations, elles, sont dans settings_schema.json.

    config/settings_data.jsonjson
    {
      "current": {
        "encre": "#16211c",
        "papier": "#f7f5f0",
        "accent": "#2f6f4e",
        "largeur": 1200,
        "trait": 2,
        "sections": {
          "annonce": {
            "settings": { "texte": "Devis gratuit sous 48 h — déplacement compris" }
          }
        }
      }
    }

    Remplace "accent": "#2f6f4e" par "accent": "#b4442c". Enregistre.

    Tu n’as touché à aucune ligne de CSS : la coquille pose --accent à partir de ce réglage, et --accent-sombre s’en déduit par teinte: -25. Ce filtre existe précisément pour ça — sans lui, chaque nuance d’une couleur réglable devrait être un réglage de plus, et personne ne remplit un panneau de vingt sélecteurs de couleur.

  10. Pousser

    node scripts/theme.mjs pousserForge · /Users/toi/webcosa/forge ↑ modifié config/settings_data.json ✓ 1 modifié, 22 inchangés

    Le CLI compare les empreintes SHA-256 locales à celles du serveur et n’envoie que ce qui a changé. Vingt-deux fichiers identiques ne traversent pas le réseau.

  11. Regarder

    Recharge l’adresse publique du site. L’accent a changé : les boutons, les filets, les surtitres.

    Il n’y a rien à purger et rien à attendre — la page publique est rendue à chaque requête, donc la modification est visible au rechargement suivant.

#Ajouter une section

Changer une couleur, c’est du réglage. Ajouter une section, c’est écrire du thème. Deux fichiers : la section, puis sa déclaration dans le template.

  1. Écrire la section

    Crée sections/horaires.liquid. Le fichier a deux parties : le balisage, puis un bloc {% schema %} qui décrit ses réglages.

    sections/horaires.liquidliquid
    <section class="section horaires">
      <div class="enveloppe">
        {%- render 'section-tete',
            surtitre: section.settings.surtitre,
            titre: section.settings.titre -%}
    
        <dl class="horaires-liste">
          {%- for bloc in section.blocks -%}
            <div>
              <dt>{{ bloc.settings.jour }}</dt>
              <dd>{{ bloc.settings.heures }}</dd>
            </div>
          {%- endfor -%}
        </dl>
    
        {%- if section.settings.note != blank -%}
          <p class="horaires-note">{{ section.settings.note | lignes }}</p>
        {%- endif -%}
      </div>
    </section>
    
    {% schema %}
    {
      "name": "Horaires",
      "settings": [
        { "type": "text", "id": "surtitre", "label": "Surtitre", "default": "Nous trouver" },
        { "type": "text", "id": "titre", "label": "Titre", "default": "Horaires d'ouverture" },
        { "type": "textarea", "id": "note", "label": "Note", "default": "" }
      ],
      "blocks": [
        {
          "type": "jour",
          "name": "Jour",
          "settings": [
            { "type": "text", "id": "jour", "label": "Jour", "default": "Lundi" },
            { "type": "text", "id": "heures", "label": "Heures", "default": "9 h – 18 h" }
          ]
        }
      ],
      "max_blocks": 7
    }
    {% endschema %}

    Quatre choses s’y jouent, et elles sont générales :

    • section.settings.<id> lit un réglage déclaré plus bas. L’id du schéma et la clé lue doivent coïncider — une faute de frappe rend du vide, sans erreur. Voir Les types de réglage.
    • section.blocks est la liste des éléments répétables. Le client en ajoute et en retire depuis l’éditeur, dans la limite de max_blocks. Voir Les blocs.
    • render 'section-tete' appelle snippets/section-tete.liquid. Un snippet ne voit que ce qu’on lui passe — il n’hérite pas du contexte de l’appelant. Voir Snippets.
    • lignes transforme les retours à la ligne en <br> et échappe le HTML. C’est le filtre à utiliser sur tout texte saisi dans une zone multiligne : sans lui, la note s’afficherait d’un seul tenant.
  2. La déclarer dans le template

    Une section écrite mais non déclarée ne rend rien. C’est templates/index.json qui compose la page d’accueil, et il tient deux clés : sections, qui donne les valeurs de chacune, et order, qui donne l’ordre d’affichage.

    Ajoute l’entrée dans sections, puis le nom dans order :

    templates/index.jsonjson
    {
      "sections": {
        "horaires": {
          "type": "horaires",
          "settings": {
            "titre": "Horaires d'ouverture",
            "note": "Fermé les jours fériés.\nSur rendez-vous le samedi."
          },
          "blocks": {
            "j1": { "type": "jour", "settings": { "jour": "Lundi au jeudi", "heures": "8 h – 18 h" } },
            "j2": { "type": "jour", "settings": { "jour": "Vendredi", "heures": "8 h – 16 h" } },
            "j3": { "type": "jour", "settings": { "jour": "Samedi", "heures": "sur rendez-vous" } }
          },
          "block_order": ["j1", "j2", "j3"]
        }
      },
      "order": ["bandeau", "chiffres", "prestations", "horaires", "contact", "appel"]
    }
    Attention

    Ce bloc est un extrait : garde les autres sections du fichier. La clé de premier niveau ("horaires") est un identifiant libre dans la page ; "type" est le nom du fichier, sans .liquid. Les deux se ressemblent ici parce que c’est l’usage, mais rien ne l’impose — deux sections du même type peuvent coexister sous deux clés différentes.

    L’ordre des blocs vient de block_order, pas de l’ordre des clés de blocks : un objet JSON n’a pas d’ordre garanti, et s’en remettre à lui produit une page qui se réordonne toute seule après un aller-retour en base.

  3. Pousser et regarder

    node scripts/theme.mjs pousserForge · /Users/toi/webcosa/forge + nouveau sections/horaires.liquid ↑ modifié templates/index.json ✓ 1 nouveau, 1 modifié, 22 inchangés

    Recharge l’accueil : la section apparaît entre les prestations et le formulaire de contact.

#Quand ça ne marche pas

Trois échecs couvrent la quasi-totalité des premiers essais.

#Le CLI refuse le fichier

Sortie du CLIbash
 sections/horaires.liquid tag "for" not closed, line:14, col:1 [syntaxe]

La syntaxe est validée sur le serveur, à l’écriture, et un fichier refusé n’est pas enregistré. L’envoi s’interrompt : un thème à moitié poussé est pire qu’un thème non poussé. Corrige, repousse.

#La section n’apparaît pas, sans message

Regarde le code source de la page rendue — pas l’inspecteur, qui ne montre pas toujours les commentaires — et cherche <!-- section.

Rendu de la pagehtml
<!-- section absente : horaire -->

Une section qui échoue est remplacée par un commentaire HTML plutôt que par une page blanche. Ici, le "type" du template et le nom du fichier ne coïncident pas — horaire contre horaires.

#Un réglage « ne marche pas »

C’est presque toujours un id qui ne correspond pas. Le moteur tourne avec strictVariables désactivé : une variable absente rend une chaîne vide, pas une erreur. Pratique en production, traître en développement.

Vérifie que l’id du schéma, la clé du template et ce que lit le Liquid s’écrivent exactement pareil, accents compris.

#La suite

Tu as maintenant la boucle complète, mais avec un pousser à la main à chaque sauvegarde. La commande de suivi le fait pour toi — et il faut savoir quand elle est dangereuse.