<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Programmation on Antoine Cavard - Blog</title>
    <link>https://blog.chaudron.de/tags/programmation/</link>
    <description>Recent content in Programmation on Antoine Cavard - Blog</description>
    <generator>Hugo</generator>
    <language>fr</language>
    <copyright>2016-2026 Antoine CAVARD</copyright>
    <lastBuildDate>Sun, 18 Oct 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://blog.chaudron.de/tags/programmation/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Création de carnets guidés</title>
      <link>https://blog.chaudron.de/posts/2026-10-18_creation-de-carnets/</link>
      <pubDate>Sun, 18 Oct 2026 00:00:00 +0000</pubDate>
      <guid>https://blog.chaudron.de/posts/2026-10-18_creation-de-carnets/</guid>
      <description>Concevoir une collection de carnets guidés, de l&amp;rsquo;idée à la publication.</description>
      <content:encoded><![CDATA[<p>Ce projet est né de l&rsquo;envie de créer mon propre journal guidé autour du Yams. Je voulais garder une trace de mes réflexions comme dans un journal personnel mais rattachée à un lieu et à une activité précise. Je voulais aussi faire ma propre grille de score.</p>
<p>Est venu ensuite le journal guidé d&rsquo;aventure né de l&rsquo;envie de créer un carnet de notes pour mes aventures. Je l&rsquo;ai construit à partir de mes préparations  et de mes retours d&rsquo;expérience de voyage à vélo.</p>
<h2 id="1-les-carnets">1. Les carnets</h2>
<h3 id="11-le-yatzy-journal">1.1 Le Yatzy Journal</h3>
<p>Le premier carnet propose trois versions du Yams. Chacune a sa grille de score ses règles et sa façon de compter les points. Le tout est décliné en trois langues.</p>
<p>Après les grilles de score vient un journal guidé de cinq pages thématiques qui se répètent à chaque nouvelle partie. On y note le contexte du moment (lieu, météo, ce qu&rsquo;on boit et mange), les faits marquants du jeu, ses sensations et ses réflexions. La dernière page est un espace libre de création.</p>
<h3 id="12-ladventure-journal">1.2 L&rsquo;Adventure Journal</h3>
<p>Le second carnet contient un journal guidé de six pages dédié à une aventure. Il suit le fil du voyage : le départ et le retour, les lieux et les paysages traversés, la vie sur la route (compagnons, campement, spécialités culinaires), puis les rencontres, les mésaventures, les conseils pour la prochaine fois et un espace libre de création. Ces six pages se répètent pour pouvoir noter plusieurs aventures.</p>
<p>En complément le carnet contient en dernière partie une checklist du matériel et de l&rsquo;équipement à ne pas oublier avant le départ.</p>
<h2 id="2-les-besoins">2. Les besoins</h2>
<p>Mes besoins de départ tenaient en trois points : le format, la séparation de la forme et du fond, et l&rsquo;automatisation.</p>
<p><strong>Le format :</strong> Je voulais un carnet de poche assez compact pour se glisser dans un sac ou une sacoche de vélo.</p>
<p><strong>Séparer la forme du fond :</strong> Je voulais pouvoir modifier un texte sans toucher à la mise en page.</p>
<p><strong>L&rsquo;automatisation :</strong> Je voulais produire plusieurs carnets, en plusieurs langues, avec des sections répétées, des variantes de couleurs et une mise en page cohérente. Il fallait aussi pouvoir régénérer le document complet après une modification, travailler sur chaque partie séparément et obtenir des PDF prêts à envoyer à l&rsquo;imprimeur.</p>
<h2 id="3-les-contraintes">3. Les contraintes</h2>
<p>J&rsquo;ai choisi le format A6 (108 × 175 mm). Toutes les plateformes d&rsquo;impression à la demande ne proposent pas ce format. Ce critère a guidé mon choix vers <a href="https://www.lulu.com">Lulu</a>.</p>
<p>Ce choix a fixé une partie des contraintes techniques : dimensions exactes des pages, marges de sécurité, zones de rognage, caractéristiques des fichiers à fournir. Elles ont influencé la conception des carnets dès le départ.</p>
<h2 id="4-les-choix-techniques">4. Les choix techniques</h2>
<h3 id="41-les-logiciels-de-mise-en-page">4.1 Les logiciels de mise en page</h3>
<p>Dans le monde du logiciel libre des applications comme Scribus ou Inkscape permettent de créer des documents destinés à l&rsquo;impression. Elles conviennent très bien pour un carnet unique.</p>
<p>Mais dans le cadre de mon projet j&rsquo;ai estimé qu&rsquo;elles n&rsquo;étaient pas adaptées car il cumule plusieurs langues, des sections répétées, des variantes de couleurs et une mise en page à garder identique. Refaire tout cela à la main devient vite fastidieux. J&rsquo;ai donc décidé de construire un programme sur mesure.</p>
<h3 id="42-séparer-la-forme-du-fond">4.2 Séparer la forme du fond</h3>
<p>Je choisis de gérer la position des traits, les espacements, les marges, les tailles de texte et les polices par un programme Python. C&rsquo;est le langage que je connais le mieux il est très répandu et on trouve beaucoup d&rsquo;aide sur internet.</p>
<p>Les textes sont stockés à part au format JSON. C&rsquo;est un format simple à lire et à modifier à la main. Je peux ainsi modifier un texte sans toucher à la mise en page. Il me suffit ensuite de lancer une ligne de commande pour générer le document complet.</p>
<p>Les carnets guidés contiennent des sections qui se répètent : une page de journal, une grille, une checklist. Je choisis donc de découper chaque partie du carnet en composants réutilisables que j&rsquo;assemble ensuite pour former le carnet complet. Le but est de créer chaque composant une seule fois et de le réutiliser y compris d&rsquo;un carnet à l&rsquo;autre.</p>
<h2 id="5-la-conception">5. La conception</h2>
<p>Chaque partie du carnet a son propre sous-répertoire. Il contient :</p>
<ul>
<li>un fichier JSON avec le contenu</li>
<li>un script Python qui met ce contenu en forme</li>
</ul>
<p>Un programme global <code>build.py</code> appelle tous les sous-programmes et gère l&rsquo;assemblage final.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>build/
</span></span><span style="display:flex;"><span>├── preface/
</span></span><span style="display:flex;"><span>│   ├── generate.py
</span></span><span style="display:flex;"><span>│   └── content.json
</span></span><span style="display:flex;"><span>├── how-to/
</span></span><span style="display:flex;"><span>│   ├── generate.py
</span></span><span style="display:flex;"><span>│   └── content.json
</span></span><span style="display:flex;"><span>├── guided-journal/
</span></span><span style="display:flex;"><span>│   ├── generate.py
</span></span><span style="display:flex;"><span>│   └── content.json
</span></span><span style="display:flex;"><span>├── checklist/
</span></span><span style="display:flex;"><span>│   ├── generate.py
</span></span><span style="display:flex;"><span>│   └── content.json
</span></span><span style="display:flex;"><span>├── cover/
</span></span><span style="display:flex;"><span>│   ├── generate.py
</span></span><span style="display:flex;"><span>│   └── colors.json
</span></span><span style="display:flex;"><span>└── build.py      ← assemblage final
</span></span></code></pre></div><h3 id="51-le-contenu--les-textes-en-json">5.1 Le contenu : les textes en JSON</h3>
<p>Voici un exemple très simplifié de <code>content.json</code> pour une page de journal :</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;fr&#34;</span>: {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;pages&#34;</span>: [
</span></span><span style="display:flex;"><span>      {
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;id&#34;</span>: <span style="color:#ae81ff">5</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&#34;fields&#34;</span>: [
</span></span><span style="display:flex;"><span>          { <span style="color:#f92672">&#34;label&#34;</span>: <span style="color:#e6db74">&#34;RENCONTRES&#34;</span>, <span style="color:#f92672">&#34;lines&#34;</span>: <span style="color:#ae81ff">5</span> },
</span></span><span style="display:flex;"><span>          { <span style="color:#f92672">&#34;label&#34;</span>: <span style="color:#e6db74">&#34;MOMENT OU DÉCOUVERTE INATTENDUE&#34;</span>, <span style="color:#f92672">&#34;lines&#34;</span>: <span style="color:#ae81ff">5</span> },
</span></span><span style="display:flex;"><span>          { <span style="color:#f92672">&#34;label&#34;</span>: <span style="color:#e6db74">&#34;MÉSAVENTURE&#34;</span>, <span style="color:#f92672">&#34;lines&#34;</span>: <span style="color:#ae81ff">5</span> },
</span></span><span style="display:flex;"><span>          { <span style="color:#f92672">&#34;label&#34;</span>: <span style="color:#e6db74">&#34;CONSEILS POUR LA PROCHAINE FOIS&#34;</span>, <span style="color:#f92672">&#34;lines&#34;</span>: <span style="color:#ae81ff">4</span> }
</span></span><span style="display:flex;"><span>        ]
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>    ]
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Le fichier contient les textes et le nombre de lignes d&rsquo;écriture sous chaque texte. La mise en page reste du ressort du programme Python.</p>
<h3 id="52-la-mise-en-page--le-script-python">5.2 La mise en page : le script Python</h3>
<p>Voici une version simplifiée d&rsquo;un <code>generate.py</code>.</p>
<p>Le script lit le fichier <code>content.json</code> puis construit une page SVG au format A6. Il place ensuite les titres les uns sous les autres, chacun suivi de son nombre de lignes d&rsquo;écriture et résultat est converti en PDF.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#f92672">import</span> argparse
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> json
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> os
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> subprocess
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> xml.etree.ElementTree <span style="color:#66d9ef">as</span> ET
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># ==================================================</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># CONFIG A6</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># ==================================================</span>
</span></span><span style="display:flex;"><span>A6 <span style="color:#f92672">=</span> {<span style="color:#e6db74">&#34;width&#34;</span>: <span style="color:#ae81ff">108</span>, <span style="color:#e6db74">&#34;height&#34;</span>: <span style="color:#ae81ff">175</span>, <span style="color:#e6db74">&#34;margin&#34;</span>: <span style="color:#ae81ff">12.7</span>}
</span></span><span style="display:flex;"><span>TEXT <span style="color:#f92672">=</span> {<span style="color:#e6db74">&#34;font&#34;</span>: <span style="color:#e6db74">&#34;Inter&#34;</span>, <span style="color:#e6db74">&#34;size&#34;</span>: <span style="color:#ae81ff">3</span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># ==================================================</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># GÉNÉRATEUR SVG</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># ==================================================</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">generate_page</span>(config):
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;&#34;&#34;Génère une page SVG à partir du JSON&#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    svg <span style="color:#f92672">=</span> ET<span style="color:#f92672">.</span>Element(<span style="color:#e6db74">&#34;svg&#34;</span>, {
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;xmlns&#34;</span>: <span style="color:#e6db74">&#34;http://www.w3.org/2000/svg&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;width&#34;</span>: <span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;</span><span style="color:#e6db74">{</span>A6[<span style="color:#e6db74">&#39;width&#39;</span>]<span style="color:#e6db74">}</span><span style="color:#e6db74">mm&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;height&#34;</span>: <span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;</span><span style="color:#e6db74">{</span>A6[<span style="color:#e6db74">&#39;height&#39;</span>]<span style="color:#e6db74">}</span><span style="color:#e6db74">mm&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;viewBox&#34;</span>: <span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;0 0 </span><span style="color:#e6db74">{</span>A6[<span style="color:#e6db74">&#39;width&#39;</span>]<span style="color:#e6db74">}</span><span style="color:#e6db74"> </span><span style="color:#e6db74">{</span>A6[<span style="color:#e6db74">&#39;height&#39;</span>]<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>    })
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Style</span>
</span></span><span style="display:flex;"><span>    style <span style="color:#f92672">=</span> ET<span style="color:#f92672">.</span>SubElement(svg, <span style="color:#e6db74">&#34;style&#34;</span>)
</span></span><span style="display:flex;"><span>    style<span style="color:#f92672">.</span>text <span style="color:#f92672">=</span> <span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;&#34;&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    .label </span><span style="color:#ae81ff">{{</span><span style="color:#e6db74"> font-size: 4px; font-weight: 600; font-family: &#39;</span><span style="color:#e6db74">{</span>TEXT[<span style="color:#e6db74">&#39;font&#39;</span>]<span style="color:#e6db74">}</span><span style="color:#e6db74">&#39;; </span><span style="color:#ae81ff">}}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    .line </span><span style="color:#ae81ff">{{</span><span style="color:#e6db74"> stroke: black; stroke-width: 0.2px; </span><span style="color:#ae81ff">}}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    margin <span style="color:#f92672">=</span> A6[<span style="color:#e6db74">&#34;margin&#34;</span>]
</span></span><span style="display:flex;"><span>    y <span style="color:#f92672">=</span> margin
</span></span><span style="display:flex;"><span>    line_height <span style="color:#f92672">=</span> <span style="color:#ae81ff">6</span>  <span style="color:#75715e"># mm</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Récupère la première page</span>
</span></span><span style="display:flex;"><span>    page <span style="color:#f92672">=</span> config[<span style="color:#e6db74">&#34;fr&#34;</span>][<span style="color:#e6db74">&#34;pages&#34;</span>][<span style="color:#ae81ff">0</span>]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Pour chaque champ</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> field <span style="color:#f92672">in</span> page[<span style="color:#e6db74">&#34;fields&#34;</span>]:
</span></span><span style="display:flex;"><span>        <span style="color:#75715e"># Label</span>
</span></span><span style="display:flex;"><span>        ET<span style="color:#f92672">.</span>SubElement(svg, <span style="color:#e6db74">&#34;text&#34;</span>, {<span style="color:#e6db74">&#34;x&#34;</span>: str(margin), <span style="color:#e6db74">&#34;y&#34;</span>: str(y), <span style="color:#e6db74">&#34;class&#34;</span>: <span style="color:#e6db74">&#34;label&#34;</span>})<span style="color:#f92672">.</span>text <span style="color:#f92672">=</span> field[<span style="color:#e6db74">&#34;label&#34;</span>]
</span></span><span style="display:flex;"><span>        y <span style="color:#f92672">+=</span> <span style="color:#ae81ff">5</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e"># Lignes</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">for</span> _ <span style="color:#f92672">in</span> range(field[<span style="color:#e6db74">&#34;lines&#34;</span>]):
</span></span><span style="display:flex;"><span>            ET<span style="color:#f92672">.</span>SubElement(svg, <span style="color:#e6db74">&#34;line&#34;</span>, {<span style="color:#e6db74">&#34;x1&#34;</span>: str(margin), <span style="color:#e6db74">&#34;y1&#34;</span>: str(y), <span style="color:#e6db74">&#34;x2&#34;</span>: str(A6[<span style="color:#e6db74">&#34;width&#34;</span>] <span style="color:#f92672">-</span> margin), <span style="color:#e6db74">&#34;y2&#34;</span>: str(y), <span style="color:#e6db74">&#34;class&#34;</span>: <span style="color:#e6db74">&#34;line&#34;</span>})
</span></span><span style="display:flex;"><span>            y <span style="color:#f92672">+=</span> line_height
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        y <span style="color:#f92672">+=</span> <span style="color:#ae81ff">3</span>  <span style="color:#75715e"># Espace entre les champs</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> svg
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># ==================================================</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># EXPORT PDF</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># ==================================================</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">svg_to_pdf</span>(svg_file, pdf_file):
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;&#34;&#34;Convertit SVG en PDF avec inkscape&#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    subprocess<span style="color:#f92672">.</span>run([<span style="color:#e6db74">&#34;inkscape&#34;</span>, <span style="color:#e6db74">&#34;--export-type=pdf&#34;</span>, <span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;--export-filename=</span><span style="color:#e6db74">{</span>pdf_file<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>, svg_file], check<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>, capture_output<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># ==================================================</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># CLI</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># ==================================================</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> __name__ <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;__main__&#34;</span>:
</span></span><span style="display:flex;"><span>    parser <span style="color:#f92672">=</span> argparse<span style="color:#f92672">.</span>ArgumentParser()
</span></span><span style="display:flex;"><span>    parser<span style="color:#f92672">.</span>add_argument(<span style="color:#e6db74">&#34;--output&#34;</span>, <span style="color:#e6db74">&#34;-o&#34;</span>, default<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;page.pdf&#34;</span>)
</span></span><span style="display:flex;"><span>    args <span style="color:#f92672">=</span> parser<span style="color:#f92672">.</span>parse_args()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Charge le JSON</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">with</span> open(<span style="color:#e6db74">&#34;content.json&#34;</span>, encoding<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;utf-8&#34;</span>) <span style="color:#66d9ef">as</span> f:
</span></span><span style="display:flex;"><span>        config <span style="color:#f92672">=</span> json<span style="color:#f92672">.</span>load(f)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Génère le SVG, le convertit en PDF, puis supprime le SVG</span>
</span></span><span style="display:flex;"><span>    svg_file <span style="color:#f92672">=</span> args<span style="color:#f92672">.</span>output<span style="color:#f92672">.</span>replace(<span style="color:#e6db74">&#34;.pdf&#34;</span>, <span style="color:#e6db74">&#34;.svg&#34;</span>)
</span></span><span style="display:flex;"><span>    ET<span style="color:#f92672">.</span>ElementTree(generate_page(config))<span style="color:#f92672">.</span>write(svg_file, encoding<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;utf-8&#34;</span>, xml_declaration<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>)
</span></span><span style="display:flex;"><span>    svg_to_pdf(svg_file, args<span style="color:#f92672">.</span>output)
</span></span><span style="display:flex;"><span>    os<span style="color:#f92672">.</span>remove(svg_file)
</span></span></code></pre></div><p>Dans la version réelle les scripts gèrent davantage d&rsquo;éléments : les retours à la ligne, les blocs colorés, les différents types de pages et le choix de la langue.</p>
<h2 id="6-la-réalisation">6. La réalisation</h2>
<h3 id="61-travailler-partie-par-partie">6.1 Travailler partie par partie</h3>
<p>Chaque composant sait générer sa propre partie du carnet. Je peux générer uniquement la préface, une page de journal ou la checklist puis produire un PDF pour vérifier le résultat. J&rsquo;avance pas à pas sans régénérer tout le carnet à chaque modification.</p>
<h3 id="62-lassemblage-final">6.2 L&rsquo;assemblage final</h3>
<p>Quand chaque partie me convient <code>build.py</code> appelle les sous-programmes et produit le document final. Il gère :</p>
<ul>
<li>l&rsquo;ordre des sections</li>
<li>l&rsquo;insertion de pages blanches</li>
<li>la répétition de certaines parties</li>
<li>la sélection de la langue</li>
<li>l&rsquo;assemblage des fichiers PDF</li>
</ul>
<h3 id="63-une-base-commune">6.3 Une base commune</h3>
<p>Les titres, pieds de page, marges, espacements et styles suivent la même logique dans tous les carnets. Le contenu change mais la composition reste similaire. C&rsquo;est ce qui donne à l&rsquo;ensemble l&rsquo;allure d&rsquo;une collection cohérente.</p>
<h2 id="7-où-acheter-mes-carnets">7. Où acheter mes carnets</h2>
<p>Les deux carnets sont disponibles sur la boutique Lulu :</p>
<ul>
<li><strong><a href="https://www.lulu.com/fr/shop/antoine-cavard/adventure-journal/hardcover/product-e7n5rqg.html">Adventure Journal</a></strong> : carnet guidé pour les voyages à vélo ou autrement, 193 pages, couverture rigide, format de poche.</li>
<li><strong><a href="https://www.lulu.com/fr/shop/antoine-cavard/yatzy-journal/hardcover/product-rmr4m9j.html">Yatzy Journal</a></strong> : trois versions du jeu avec leur grille de score, accompagnées d&rsquo;un journal guidé, en trois langues, 193 pages, couverture rigide, format de poche.</li>
</ul>
<h2 id="conclusion">Conclusion</h2>
<p>Le système fonctionne bien. Une fois la logique en place pour le premier carnet le deuxième a été beaucoup plus rapide à produire.</p>
<p>Comme les deux carnets reposent sur le même programme ils partagent le même format et une composition proche : position des titres, pieds de page, marges, organisation générale.</p>
<p>J&rsquo;ai maintenant l&rsquo;outil et la méthode pour continuer à faire grandir ma collection. Quel sera le prochain carnet ? À suivre :)</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
