{
  "version": "https://jsonfeed.org/version/1.1",
  "title": "Cecil - Content",
  "home_page_url": "https://cecil.app/documentation/content/",
  "feed_url": "https://cecil.app/documentation/content/feed.json",
  "description": "Create and organize your content: pages, front matter, Markdown, multilingual and dynamic content.",
  "icon": "https://cecil.app/favicon.7ff4b89eec6dad139a7d2d6561543285.png",
  "favicon": "https://cecil.app/thumbnails/64x/favicon.7ff4b89eec6dad139a7d2d6561543285.png",
  "language": "en",
  "items": [
    {
      "id": "https://cecil.app/documentation/content/pages/",
      "url": "https://cecil.app/documentation/content/pages/",
      "title": "Pages and sections",
      "summary": "Anatomy of a page, file prefix, sections, sub-sections and home page.",
      "date_published": "2021-05-07T00:00:00+00:00",
      "date_modified": "2026-10-06T00:00:00+00:00","content_text": "Pages and sections\nA page is a file made up of a front matter and a body.\nFront matter\nThe front matter is a collection of variables (in key\/value format) surrounded by ---.\nExample:\n---\ntitle: \"The title\"\ndate: 2019-02-21\ntags: [tag 1, tag 2]\ncustomvar: \"Value of customvar\"\n---\nYou can also use &lt;!-- --&gt; or +++ as separator.\nBody\nBody is the main content of a page, it could be written in Markdown or in plain text.\nExample:\n# Header\n\n[toc]\n\n## Sub-Header 1\n\nLorem ipsum dolor [sit amet](https:\/\/example.com), consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n&lt;!-- excerpt --&gt;\nUt enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n\n## Sub-Header 2\n\n![Description](\/image.jpg \"Title\")\n\n## Sub-Header 3\n\n:::tip\nThis is advice.\n:::\nFile prefix\nThe filename can contain a prefix to define date or weight variables of the page (used by sortby).\nDefault prefix separators: _ and -.\nYou can customize them with the pages.prefix.separator option.\ndate\nThe date prefix is used to set the date of the page, and must be a valid date format (i.e.: « YYYY-MM-DD »).\nExample:\nIn « 2019-04-23_My blog post.md »:\n\nthe prefix is « 2019-04-23 »\nthe date of the page is « 2019-04-23 »\nthe title of the page is « My blog post »\n\nweight\nThe weight prefix is used to set the sort order of the page, and must be a valid integer value.\nExample:\nIn « 1_The first project.md »:\n\nthe prefix is « 1 »\nthe weight of the page is « 1 »\nthe title of the page is « The first project »\n\nSection\nSome dedicated variables can be used in a custom Section (i.e.: &lt;section&gt;\/index.md).\nsortby\nThe order of pages in a Section can be changed.\nAvailable values are:\n\ndate: more recent first\ntitle: alphabetic order\nweight: lightest first\n\nExample:\n---\nsortby: title\n---\nMore options:\n---\nsortby:\n  variable: date    # \"date\", \"updated\", \"title\" or \"weight\"\n  desc_title: false # used with \"date\" or \"updated\" variable value to sort by desc title order if items have the same date\n  reverse: false    # reversed if true\n---\npagination\nThe global pagination configuration is used by default, but you can change it for a specific Section.\nExample:\n---\npagination:\n  max: 5\n  path: \"page\"\n---\nPagination can be disabled for a Section:\n---\npagination: false\n---\ncascade\nAny variables in cascade are added to the front matter of all sub pages.\nExample:\n---\ncascade:\n  banner: image.jpg\n---\nExisting variables are not overridden.\ncircular\nSet circular to true to enable circular navigation with page.&lt;prev\/next&gt;.\nWith sub-sections, only the circular value of the top level Section is used.\nExample:\n---\ncircular: true\n---\nSub-section\nA nested folder that explicitly contains an index.md file is turned into a sub-section of its parent Section.\n&lt;mywebsite&gt;\n└─ pages\n   └─ blog                 &lt;- Section\n      ├─ index.md\n      ├─ post-1.md         &lt;- Page in Section \"blog\"\n      └─ 2024              &lt;- Sub-section (contains an \"index.md\")\n         ├─ index.md\n         └─ post-2.md      &lt;- Page in Section \"blog\" *and* sub-section \"blog\/2024\"\nA sub-section:\n\nis a Section (same type, variables and layout resolution) available at its own URL (e.g.: \/blog\/2024\/)\nis rendered with the layouts of its parent Sections if it doesn't have its own (e.g.: blog\/list.html.twig)\ncan be nested at any depth (e.g.: blog\/2024\/06\/)\nlists its own pages, and its pages also belong to each of their parent Sections\nis not listed in its parent Section\nis placed in the page.&lt;prev\/next&gt; navigation of its parent Section (according to its sortby), followed by its own pages\n\nA nested folder without an index.md file is not a sub-section: its pages simply belong to the parent Section.\nHome page\nLike another section, Home page support sortby and pagination configuration.\npagesfrom\nSet a valid Section name in pagesfrom to use pages collection from this Section in Home page.\nExample:\n---\npagesfrom: blog\n---",
      "content_html": "<h1>Pages and sections</h1>\n<p>A page is a file made up of a <a href=\"#front-matter\"><strong>front matter</strong></a> and a <a href=\"#body\"><strong>body</strong></a>.</p>\n<h2 id=\"front-matter\">Front matter</h2>\n<p>The <em>front matter</em> is a collection of <a href=\"2-front-matter.md\">variables</a> (in <em>key/value</em> format) surrounded by <code translate=\"no\">---</code>.</p>\n<p><em>Example:</em></p>\n<pre><code class=\"language-yaml hljs yaml\" translate=\"no\"><span class=\"hljs-meta\">---</span>\n<span class=\"hljs-attr\">title:</span> <span class=\"hljs-string\">\"The title\"</span>\n<span class=\"hljs-attr\">date:</span> <span class=\"hljs-number\">2019</span><span class=\"hljs-number\">-02</span><span class=\"hljs-number\">-21</span>\n<span class=\"hljs-attr\">tags:</span> <span class=\"hljs-string\">[tag</span> <span class=\"hljs-number\">1</span><span class=\"hljs-string\">,</span> <span class=\"hljs-string\">tag</span> <span class=\"hljs-number\">2</span><span class=\"hljs-string\">]</span>\n<span class=\"hljs-attr\">customvar:</span> <span class=\"hljs-string\">\"Value of customvar\"</span>\n<span class=\"hljs-meta\">---</span></code></pre>\n<aside class=\"note note-info\"><p>You can also use <code translate=\"no\">&lt;!-- --&gt;</code> or <code translate=\"no\">+++</code> as separator.</p></aside>\n<h2 id=\"body\">Body</h2>\n<p><em>Body</em> is the main content of a page, it could be written in <a href=\"3-markdown.md\">Markdown</a> or in plain text.</p>\n<p><em>Example:</em></p>\n<pre><code class=\"language-markdown hljs markdown\" translate=\"no\"><span class=\"hljs-section\"># Header</span>\n\n[toc]\n\n<span class=\"hljs-section\">## Sub-Header 1</span>\n\nLorem ipsum dolor [<span class=\"hljs-string\">sit amet</span>](<span class=\"hljs-link\">https://example.com</span>), consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n<span class=\"xml\"><span class=\"hljs-comment\">&lt;!-- excerpt --&gt;</span></span>\nUt enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n\n<span class=\"hljs-section\">## Sub-Header 2</span>\n\n![<span class=\"hljs-string\">Description</span>](<span class=\"hljs-link\">/image.jpg \"Title\"</span>)\n\n<span class=\"hljs-section\">## Sub-Header 3</span>\n\n:::tip\nThis is advice.\n:::</code></pre>\n<h2 id=\"file-prefix\">File prefix</h2>\n<p>The filename can contain a prefix to define <code translate=\"no\">date</code> or <code translate=\"no\">weight</code> variables of the page (used by <a href=\"../templates/reference/2-sorts.md#sort-by-date\"><code translate=\"no\">sortby</code></a>).</p>\n<aside class=\"note note-info\"><p>Default prefix separators: <code translate=\"no\">_</code> and <code translate=\"no\">-</code>.</p>\n<p>You can customize them with the <a href=\"../configuration/4-pages.md#pages-prefix-separator\"><code translate=\"no\">pages.prefix.separator</code></a> option.</p></aside>\n<h3 id=\"date\">date</h3>\n<p>The <em>date prefix</em> is used to set the <code translate=\"no\">date</code> of the page, and must be a valid date format (i.e.: « YYYY-MM-DD »).</p>\n<p><em>Example:</em></p>\n<p>In « 2019-04-23_My blog post.md »:</p>\n<ul>\n<li>the prefix is « 2019-04-23 »</li>\n<li>the <code translate=\"no\">date</code> of the page is « 2019-04-23 »</li>\n<li>the <code translate=\"no\">title</code> of the page is « My blog post »</li>\n</ul>\n<h3 id=\"weight\">weight</h3>\n<p>The <em>weight prefix</em> is used to set the sort order of the page, and must be a valid integer value.</p>\n<p><em>Example:</em></p>\n<p>In « 1_The first project.md »:</p>\n<ul>\n<li>the prefix is « 1 »</li>\n<li>the <code translate=\"no\">weight</code> of the page is « 1 »</li>\n<li>the <code translate=\"no\">title</code> of the page is « The first project »</li>\n</ul>\n<h2 id=\"section\">Section</h2>\n<p>Some dedicated variables can be used in a custom <em>Section</em> (i.e.: <code translate=\"no\">&lt;section&gt;/index.md</code>).</p>\n<h3 id=\"sortby\">sortby</h3>\n<p>The order of pages in a <em>Section</em> can be changed.</p>\n<p>Available values are:</p>\n<ul>\n<li><code translate=\"no\">date</code>: more recent first</li>\n<li><code translate=\"no\">title</code>: alphabetic order</li>\n<li><code translate=\"no\">weight</code>: lightest first</li>\n</ul>\n<p><em>Example:</em></p>\n<pre><code class=\"language-yaml hljs yaml\" translate=\"no\"><span class=\"hljs-meta\">---</span>\n<span class=\"hljs-attr\">sortby:</span> <span class=\"hljs-string\">title</span>\n<span class=\"hljs-meta\">---</span></code></pre>\n<p><strong>More options:</strong></p>\n<pre><code class=\"language-yaml hljs yaml\" translate=\"no\"><span class=\"hljs-meta\">---</span>\n<span class=\"hljs-attr\">sortby:</span>\n  <span class=\"hljs-attr\">variable:</span> <span class=\"hljs-string\">date</span>    <span class=\"hljs-comment\"># \"date\", \"updated\", \"title\" or \"weight\"</span>\n  <span class=\"hljs-attr\">desc_title:</span> <span class=\"hljs-literal\">false</span> <span class=\"hljs-comment\"># used with \"date\" or \"updated\" variable value to sort by desc title order if items have the same date</span>\n  <span class=\"hljs-attr\">reverse:</span> <span class=\"hljs-literal\">false</span>    <span class=\"hljs-comment\"># reversed if true</span>\n<span class=\"hljs-meta\">---</span></code></pre>\n<h3 id=\"pagination\">pagination</h3>\n<p>The global <a href=\"../configuration/4-pages.md#pages-pagination\">pagination configuration</a> is used by default, but you can change it for a specific <em>Section</em>.</p>\n<p><em>Example:</em></p>\n<pre><code class=\"language-yaml hljs yaml\" translate=\"no\"><span class=\"hljs-meta\">---</span>\n<span class=\"hljs-attr\">pagination:</span>\n  <span class=\"hljs-attr\">max:</span> <span class=\"hljs-number\">5</span>\n  <span class=\"hljs-attr\">path:</span> <span class=\"hljs-string\">\"page\"</span>\n<span class=\"hljs-meta\">---</span></code></pre>\n<p>Pagination can be disabled for a <em>Section</em>:</p>\n<pre><code class=\"language-yaml hljs yaml\" translate=\"no\"><span class=\"hljs-meta\">---</span>\n<span class=\"hljs-attr\">pagination:</span> <span class=\"hljs-literal\">false</span>\n<span class=\"hljs-meta\">---</span></code></pre>\n<h3 id=\"cascade\">cascade</h3>\n<p>Any variables in <code translate=\"no\">cascade</code> are added to the front matter of all <em>sub pages</em>.</p>\n<p><em>Example:</em></p>\n<pre><code class=\"language-yaml hljs yaml\" translate=\"no\"><span class=\"hljs-meta\">---</span>\n<span class=\"hljs-attr\">cascade:</span>\n  <span class=\"hljs-attr\">banner:</span> <span class=\"hljs-string\">image.jpg</span>\n<span class=\"hljs-meta\">---</span></code></pre>\n<aside class=\"note note-info\"><p>Existing variables are not overridden.</p></aside>\n<h3 id=\"circular\">circular</h3>\n<p>Set <code translate=\"no\">circular</code> to <code translate=\"no\">true</code> to enable circular navigation with <a href=\"../templates/2-variables.md#page-prev-next\"><em>page.&lt;prev/next&gt;</em></a>.</p>\n<aside class=\"note note-info\"><p>With <a href=\"#sub-section\">sub-sections</a>, only the <code translate=\"no\">circular</code> value of the top level <em>Section</em> is used.</p></aside>\n<p><em>Example:</em></p>\n<pre><code class=\"language-yaml hljs yaml\" translate=\"no\"><span class=\"hljs-meta\">---</span>\n<span class=\"hljs-attr\">circular:</span> <span class=\"hljs-literal\">true</span>\n<span class=\"hljs-meta\">---</span></code></pre>\n<h3 id=\"sub-section\">Sub-section</h3>\n<p>A nested folder that explicitly contains an <code translate=\"no\">index.md</code> file is turned into a <em>sub-section</em> of its parent <em>Section</em>.</p>\n<pre><code class=\"language-plaintext hljs plaintext\" translate=\"no\">&lt;mywebsite&gt;\n└─ pages\n   └─ blog                 &lt;- Section\n      ├─ index.md\n      ├─ post-1.md         &lt;- Page in Section \"blog\"\n      └─ 2024              &lt;- Sub-section (contains an \"index.md\")\n         ├─ index.md\n         └─ post-2.md      &lt;- Page in Section \"blog\" *and* sub-section \"blog/2024\"</code></pre>\n<p>A <em>sub-section</em>:</p>\n<ul>\n<li>is a <em>Section</em> (same type, variables and <a href=\"../templates/1-lookup-rules.md#type-section\">layout</a> resolution) available at its own URL (e.g.: <code translate=\"no\">/blog/2024/</code>)</li>\n<li>is rendered with the layouts of its parent <em>Sections</em> if it doesn't have its own (e.g.: <code translate=\"no\">blog/list.html.twig</code>)</li>\n<li>can be nested at any depth (e.g.: <code translate=\"no\">blog/2024/06/</code>)</li>\n<li>lists its own pages, and its pages also belong to each of their parent <em>Sections</em></li>\n<li>is <strong>not</strong> listed in its parent <em>Section</em></li>\n<li>is placed in the <a href=\"../templates/2-variables.md#page-prev-next\"><em>page.&lt;prev/next&gt;</em></a> navigation of its parent <em>Section</em> (according to its <code translate=\"no\">sortby</code>), followed by its own pages</li>\n</ul>\n<aside class=\"note note-info\"><p>A nested folder <strong>without</strong> an <code translate=\"no\">index.md</code> file is not a <em>sub-section</em>: its pages simply belong to the parent <em>Section</em>.</p></aside>\n<h2 id=\"home-page\">Home page</h2>\n<p>Like another section, <em>Home page</em> support <code translate=\"no\">sortby</code> and <code translate=\"no\">pagination</code> configuration.</p>\n<h3 id=\"pagesfrom\">pagesfrom</h3>\n<p>Set a valid <em>Section</em> name in <code translate=\"no\">pagesfrom</code> to use pages collection from this <em>Section</em> in <em>Home page</em>.</p>\n<p><em>Example:</em></p>\n<pre><code class=\"language-yaml hljs yaml\" translate=\"no\"><span class=\"hljs-meta\">---</span>\n<span class=\"hljs-attr\">pagesfrom:</span> <span class=\"hljs-string\">blog</span>\n<span class=\"hljs-meta\">---</span></code></pre>",
      "language": "en"
    },
    {
      "id": "https://cecil.app/documentation/content/front-matter/",
      "url": "https://cecil.app/documentation/content/front-matter/",
      "title": "Front matter",
      "summary": "Custom and predefined page variables: menu, taxonomy, schedule, redirect, alias, output, etc.",
      "date_published": "2021-05-07T00:00:00+00:00",
      "date_modified": "2026-10-03T00:00:00+00:00","content_text": "Front matter\nThe front matter can contains custom variables applied to the current page.\nIt must be the first thing in the file and must be a valid YAML.\nPredefined variables\n\n\n\nVariable\nDescription\nDefault value\nExample\n\n\n\n\ntitle\nTitle\nFile name without extension.\nPost 1\n\n\nlayout\nTemplate\nSee Lookup rules.\n404\n\n\ndate\nCreation date\nFile creation date (PHP DateTime object).\n2019\/04\/15\n\n\nsection\nSection\nPage's Section.\nblog\n\n\npath\nPath\nPage's path.\nblog\/post-1\n\n\nslug\nSlug\nPage's slug.\npost-1\n\n\npublished\nPublished or not\ntrue.\nfalse\n\n\ndraft\nPublished or not\nfalse.\ntrue\n\n\n\nAll the predefined variables can be overridden except section.\nupdated\nThe updated variable is used to define the last modification date of a page.\nExample:\n---\nupdated: 2026-02-02\n---\nBefore version 8.80.1, the updated variable was a predefined variable. It is now an optional variable (and must be defined in the front matter to be used).\nmenu\nA page can be added to a menu.\nThe entry name is the page title and the URL is the page path.\nThe same page can be added to multiple menus, and each entry's position can be set with the weight key (lowest first). The name key can be used to override the default entry name per menu.\nExamples:\n---\nmenu: main\n---\n---\nmenu: [main, navigation] # same page in multiple menus\n---\n---\nmenu:\n  main:\n    weight: 10\n  navigation:\n    weight: 20\n---\n---\ntitle: 'Our Expertise'\nmenu:\n  main:\n    weight: 15\n  footer:\n    weight: 15\n    name: \"Expertise\" # override the entry name in this menu\n---\nTaxonomy\nTaxonomy allows you to connect, relate and classify your website’s content.\nIn Cecil, these terms are gathered within vocabularies.\nVocabularies are declared in the Configuration.\n\nVocabulary\nA categorization of content (e.g.: tags, categories, etc.).\nTerm\nA term is an item of a vocabulary (e.g.: Development, PHP, etc.).\n\nExample:\n---\ntags: [\"Development\", \"PHP\"]\n---\nCecil then generates, for each vocabulary:\n\na page listing its terms, e.g.: \/tags\/\na page per term listing its pages, e.g.: \/tags\/development\/ and \/tags\/php\/\n\nSee templates lookup rules and taxonomy variables to customize those pages.\nSchedule\nSchedules pages’ publication.\nExample:\nThe page will be published if current date is &gt;= 2023-02-07:\nschedule:\n  publish: 2023-02-07\nThis page is published if current date is &lt;= 2022-04-28:\nschedule:\n  expiry: 2022-04-28\nredirect\nAs indicated by its name, the redirect variable is used to redirect a page to a dedicated URL.\nExample:\n---\nredirect: \"https:\/\/arnaudligny.fr\"\n---\nRedirect works with the redirect.html.twig template.\nalias\nAlias is a redirection to the current page\nExample:\n---\ntitle: \"About\"\nalias:\n  - contact\n---\nIn the previous example contact\/ redirects to about\/.\noutput\nDefines the output format of the page.\nAvailable formats are: html, atom, rss, json, xml, etc.\nYou can define one or more formats in an array.\nI’s not required to define an output format, but if you do, it must be one of the available formats defined in the Configuration.\nExample:\n---\noutput: [html, atom]\n---\nexternal\nA page with an external variable try to fetch the content of the pointed resource.\nExample:\n---\nexternal: \"https:\/\/raw.githubusercontent.com\/Cecilapp\/Cecil\/main\/README.md\"\n---\nexcluded\nSet excluded to true to hide a page from list pages (i.e.: Home page, Section, Sitemap, etc.).\nExample:\n---\nexcluded: true\n---\nexcluded is different from published: an excluded page is published but hidden from list pages.\nSince version 8.49.0, the previous exclude variable have been changed to excluded.",
      "content_html": "<h1>Front matter</h1>\n<p>The <em>front matter</em> can contains custom variables applied to the current page.</p>\n<p>It must be the first thing in the file and must be a valid <a href=\"https://en.wikipedia.org/wiki/YAML\" target=\"_blank\" rel=\"noopener noreferrer\">YAML</a>.</p>\n<h2 id=\"predefined-variables\">Predefined variables</h2>\n<table>\n<thead>\n<tr>\n<th>Variable</th>\n<th>Description</th>\n<th>Default value</th>\n<th>Example</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code translate=\"no\">title</code></td>\n<td>Title</td>\n<td>File name without extension.</td>\n<td><code translate=\"no\">Post 1</code></td>\n</tr>\n<tr>\n<td><code translate=\"no\">layout</code></td>\n<td>Template</td>\n<td>See <a href=\"../templates/1-lookup-rules.md#lookup-rules\"><em>Lookup rules</em></a>.</td>\n<td><code translate=\"no\">404</code></td>\n</tr>\n<tr>\n<td><code translate=\"no\">date</code></td>\n<td>Creation date</td>\n<td>File creation date (PHP <em>DateTime</em> object).</td>\n<td><code translate=\"no\">2019/04/15</code></td>\n</tr>\n<tr>\n<td><code translate=\"no\">section</code></td>\n<td>Section</td>\n<td>Page's <em>Section</em>.</td>\n<td><code translate=\"no\">blog</code></td>\n</tr>\n<tr>\n<td><code translate=\"no\">path</code></td>\n<td>Path</td>\n<td>Page's <em>path</em>.</td>\n<td><code translate=\"no\">blog/post-1</code></td>\n</tr>\n<tr>\n<td><code translate=\"no\">slug</code></td>\n<td>Slug</td>\n<td>Page's <em>slug</em>.</td>\n<td><code translate=\"no\">post-1</code></td>\n</tr>\n<tr>\n<td><code translate=\"no\">published</code></td>\n<td>Published or not</td>\n<td><code translate=\"no\">true</code>.</td>\n<td><code translate=\"no\">false</code></td>\n</tr>\n<tr>\n<td><code translate=\"no\">draft</code></td>\n<td>Published or not</td>\n<td><code translate=\"no\">false</code>.</td>\n<td><code translate=\"no\">true</code></td>\n</tr>\n</tbody>\n</table>\n<aside class=\"note note-info\"><p>All the predefined variables can be overridden except <code translate=\"no\">section</code>.</p></aside>\n<h2 id=\"updated\">updated</h2>\n<p>The <code translate=\"no\">updated</code> variable is used to define the last modification date of a page.</p>\n<p><em>Example:</em></p>\n<pre><code class=\"language-yaml hljs yaml\" translate=\"no\"><span class=\"hljs-meta\">---</span>\n<span class=\"hljs-attr\">updated:</span> <span class=\"hljs-number\">2026</span><span class=\"hljs-number\">-02</span><span class=\"hljs-number\">-02</span>\n<span class=\"hljs-meta\">---</span></code></pre>\n<aside class=\"note note-warning\"><p>Before version 8.80.1, the <code translate=\"no\">updated</code> variable was a predefined variable. It is now an optional variable (and must be defined in the front matter to be used).</p></aside>\n<h2 id=\"menu\">menu</h2>\n<p>A page can be added to a <a href=\"../configuration/1-site.md#menus\">menu</a>.</p>\n<p>The entry name is the page <code translate=\"no\">title</code> and the URL is the page <code translate=\"no\">path</code>.</p>\n<p>The same page can be added to multiple menus, and each entry's position can be set with the <code translate=\"no\">weight</code> key (lowest first). The <code translate=\"no\">name</code> key can be used to override the default entry name per menu.</p>\n<p><em>Examples:</em></p>\n<pre><code class=\"language-yaml hljs yaml\" translate=\"no\"><span class=\"hljs-meta\">---</span>\n<span class=\"hljs-attr\">menu:</span> <span class=\"hljs-string\">main</span>\n<span class=\"hljs-meta\">---</span></code></pre>\n<pre><code class=\"language-yaml hljs yaml\" translate=\"no\"><span class=\"hljs-meta\">---</span>\n<span class=\"hljs-attr\">menu:</span> <span class=\"hljs-string\">[main,</span> <span class=\"hljs-string\">navigation]</span> <span class=\"hljs-comment\"># same page in multiple menus</span>\n<span class=\"hljs-meta\">---</span></code></pre>\n<pre><code class=\"language-yaml hljs yaml\" translate=\"no\"><span class=\"hljs-meta\">---</span>\n<span class=\"hljs-attr\">menu:</span>\n  <span class=\"hljs-attr\">main:</span>\n    <span class=\"hljs-attr\">weight:</span> <span class=\"hljs-number\">10</span>\n  <span class=\"hljs-attr\">navigation:</span>\n    <span class=\"hljs-attr\">weight:</span> <span class=\"hljs-number\">20</span>\n<span class=\"hljs-meta\">---</span></code></pre>\n<pre><code class=\"language-yaml hljs yaml\" translate=\"no\"><span class=\"hljs-meta\">---</span>\n<span class=\"hljs-attr\">title:</span> <span class=\"hljs-string\">'Our Expertise'</span>\n<span class=\"hljs-attr\">menu:</span>\n  <span class=\"hljs-attr\">main:</span>\n    <span class=\"hljs-attr\">weight:</span> <span class=\"hljs-number\">15</span>\n  <span class=\"hljs-attr\">footer:</span>\n    <span class=\"hljs-attr\">weight:</span> <span class=\"hljs-number\">15</span>\n    <span class=\"hljs-attr\">name:</span> <span class=\"hljs-string\">\"Expertise\"</span> <span class=\"hljs-comment\"># override the entry name in this menu</span>\n<span class=\"hljs-meta\">---</span></code></pre>\n<h2 id=\"taxonomy\">Taxonomy</h2>\n<p>Taxonomy allows you to connect, relate and classify your website’s content.<br>\nIn Cecil, these terms are gathered within vocabularies.</p>\n<p>Vocabularies are declared in the <a href=\"../configuration/1-site.md#taxonomies\"><em>Configuration</em></a>.</p>\n<dl>\n<dt>Vocabulary</dt>\n<dd>A categorization of content (e.g.: <code translate=\"no\">tags</code>, <code translate=\"no\">categories</code>, etc.).</dd>\n<dt>Term</dt>\n<dd>A term is an item of a vocabulary (e.g.: <code translate=\"no\">Development</code>, <code translate=\"no\">PHP</code>, etc.).</dd>\n</dl>\n<p><em>Example:</em></p>\n<pre><code class=\"language-yaml hljs yaml\" translate=\"no\"><span class=\"hljs-meta\">---</span>\n<span class=\"hljs-attr\">tags:</span> <span class=\"hljs-string\">[\"Development\",</span> <span class=\"hljs-string\">\"PHP\"</span><span class=\"hljs-string\">]</span>\n<span class=\"hljs-meta\">---</span></code></pre>\n<p>Cecil then generates, for each vocabulary:</p>\n<ul>\n<li>a page listing its terms, e.g.: <code translate=\"no\">/tags/</code></li>\n<li>a page per term listing its pages, e.g.: <code translate=\"no\">/tags/development/</code> and <code translate=\"no\">/tags/php/</code></li>\n</ul>\n<p>See <a href=\"../templates/1-lookup-rules.md#type-vocabulary\">templates lookup rules</a> and <a href=\"../templates/2-variables.md#taxonomy\">taxonomy variables</a> to customize those pages.</p>\n<h2 id=\"schedule\">Schedule</h2>\n<p>Schedules pages’ publication.</p>\n<p><em>Example:</em></p>\n<p>The page will be published if current date is &gt;= 2023-02-07:</p>\n<pre><code class=\"language-yaml hljs yaml\" translate=\"no\"><span class=\"hljs-attr\">schedule:</span>\n  <span class=\"hljs-attr\">publish:</span> <span class=\"hljs-number\">2023</span><span class=\"hljs-number\">-02</span><span class=\"hljs-number\">-07</span></code></pre>\n<p>This page is published if current date is &lt;= 2022-04-28:</p>\n<pre><code class=\"language-yaml hljs yaml\" translate=\"no\"><span class=\"hljs-attr\">schedule:</span>\n  <span class=\"hljs-attr\">expiry:</span> <span class=\"hljs-number\">2022</span><span class=\"hljs-number\">-04</span><span class=\"hljs-number\">-28</span></code></pre>\n<h2 id=\"redirect\">redirect</h2>\n<p>As indicated by its name, the <code translate=\"no\">redirect</code> variable is used to redirect a page to a dedicated URL.</p>\n<p><em>Example:</em></p>\n<pre><code class=\"language-yaml hljs yaml\" translate=\"no\"><span class=\"hljs-meta\">---</span>\n<span class=\"hljs-attr\">redirect:</span> <span class=\"hljs-string\">\"https://arnaudligny.fr\"</span>\n<span class=\"hljs-meta\">---</span></code></pre>\n<aside class=\"note note-info\"><p>Redirect works with the <a href=\"https://github.com/Cecilapp/Cecil/blob/main/resources/layouts/_default/redirect.html.twig\" target=\"_blank\" rel=\"noopener noreferrer\"><code translate=\"no\">redirect.html.twig</code></a> template.</p></aside>\n<h2 id=\"alias\">alias</h2>\n<p>Alias is a redirection to the current page</p>\n<p><em>Example:</em></p>\n<pre><code class=\"language-yaml hljs yaml\" translate=\"no\"><span class=\"hljs-meta\">---</span>\n<span class=\"hljs-attr\">title:</span> <span class=\"hljs-string\">\"About\"</span>\n<span class=\"hljs-attr\">alias:</span>\n  <span class=\"hljs-bullet\">-</span> <span class=\"hljs-string\">contact</span>\n<span class=\"hljs-meta\">---</span></code></pre>\n<p>In the previous example <code translate=\"no\">contact/</code> redirects to <code translate=\"no\">about/</code>.</p>\n<h2 id=\"output\">output</h2>\n<p>Defines the output format of the page.</p>\n<p>Available formats are: <code translate=\"no\">html</code>, <code translate=\"no\">atom</code>, <code translate=\"no\">rss</code>, <code translate=\"no\">json</code>, <code translate=\"no\">xml</code>, etc.<br>\nYou can define one or more formats in an array.</p>\n<p>I’s not required to define an output format, but if you do, it must be one of the available formats defined in the <a href=\"../configuration/8-output.md#output-formats\"><em>Configuration</em></a>.</p>\n<p><em>Example:</em></p>\n<pre><code class=\"language-yaml hljs yaml\" translate=\"no\"><span class=\"hljs-meta\">---</span>\n<span class=\"hljs-attr\">output:</span> <span class=\"hljs-string\">[html,</span> <span class=\"hljs-string\">atom]</span>\n<span class=\"hljs-meta\">---</span></code></pre>\n<h2 id=\"external\">external</h2>\n<p>A page with an <code translate=\"no\">external</code> variable try to fetch the content of the pointed resource.</p>\n<p><em>Example:</em></p>\n<pre><code class=\"language-yaml hljs yaml\" translate=\"no\"><span class=\"hljs-meta\">---</span>\n<span class=\"hljs-attr\">external:</span> <span class=\"hljs-string\">\"https://raw.githubusercontent.com/Cecilapp/Cecil/main/README.md\"</span>\n<span class=\"hljs-meta\">---</span></code></pre>\n<h2 id=\"excluded\">excluded</h2>\n<p>Set <code translate=\"no\">excluded</code> to <code translate=\"no\">true</code> to hide a page from list pages (i.e.: <em>Home page</em>, <em>Section</em>, <em>Sitemap</em>, etc.).</p>\n<p><em>Example:</em></p>\n<pre><code class=\"language-yaml hljs yaml\" translate=\"no\"><span class=\"hljs-meta\">---</span>\n<span class=\"hljs-attr\">excluded:</span> <span class=\"hljs-literal\">true</span>\n<span class=\"hljs-meta\">---</span></code></pre>\n<aside class=\"note note-info\"><p><code translate=\"no\">excluded</code> is different from <a href=\"#predefined-variables\"><code translate=\"no\">published</code></a>: an excluded page is published but hidden from list pages.</p></aside>\n<aside class=\"note note-warning\"><p>Since version 8.49.0, the previous <code translate=\"no\">exclude</code> variable have been changed to <code translate=\"no\">excluded</code>.</p></aside>",
      "language": "en"
    },
    {
      "id": "https://cecil.app/documentation/content/markdown/",
      "url": "https://cecil.app/documentation/content/markdown/",
      "title": "Markdown",
      "summary": "Markdown syntax and extensions: attributes, links, images, table of contents, notes, syntax highlight, etc.",
      "date_published": "2021-05-07T00:00:00+00:00",
      "date_modified": "2026-10-03T00:00:00+00:00","content_text": "Markdown\nCecil supports Markdown format, but also Markdown Extra.\nCecil also provides extra features to enhance your content, see below.\nAttributes\nWith Markdown Extra you can set an id, class and custom attributes on certain elements using an attribute block.\nFor instance, put the desired attribute(s) after a header, a fenced code block, a link or an image at the end of the line inside curly brackets, like this:\n## Header {#id .class attribute=value}\nFor an inline element, like a link, you must use a line break after the closing brace:\nLorem ipsum [dolor](url){attribute=value} \nsit amet.\nLinks\nYou can create a link with the syntax [Text](url), where url can be a path, a relative path to a Markdown file, an external URL, etc.\nExample:\n[Link to a path](\/about\/)\n[Link to a Markdown file](\/about\/)\n[Link to Cecil website](https:\/\/cecil.app)\nA relative link to a Markdown file is resolved from the folder of the current file (as on GitHub), then replaced by the URL of the targeted page.\nLink to a page\nYou can easily create a link to a page with the syntax [Page title](page:page-id).\nExample:\n[Link to a blog post](page:blog\/post-1)\nExternal\nBy default external links have the following value for rel attribute: noopener noreferrer.\nExample:\n&lt;a href=\"&lt;url&gt;\" rel=\"noopener noreferrer\"&gt;Link to another website&lt;\/a&gt;\nYou can change this behavior with pages.body.links.external options.\nEmbedded links\nCecil can try to turn a link into embedded content by using the {embed} attribute or by setting the global configuration option pages.body.links.embed.enabled to true.\nOnly YouTube, Vimeo, Dailymotion, and GitHub Gists links are supported.\nExample:\n[CECIL : LE générateur de SITES STATIQUES en PHP](https:\/\/www.youtube.com\/watch?v=ur8koU0iYvc){embed}\n\n\n\nLocal video\/audio files\nCecil can also create a video and audio HTML elements, through the file extension.\nExample:\n[Video file](video.mp4){embed controls poster=\/images\/video-test.png}\n[Audio file](song.mp3){embed controls}\nIs converted to:\n&lt;video src=\"\/video.mp4\" controls poster=\"\/images\/video-test.png\" style=\"max-width:100%;height:auto;\"&gt;&lt;\/video&gt;\n&lt;audio src=\"\/song.mp3\" controls&gt;&lt;\/audio&gt;\nImages\nTo add an image, use an exclamation mark (!) followed by alternative description in brackets ([]), and the path or URL to the image in parentheses (()).\nYou can optionally add a title in quotation marks.\n![Alternative description](\/image.jpg \"Image title\")\nThe path should be relative to the root of your website (e.g.: \/image.jpg), however Cecil is able to normalize a path relative to assets and static directories (e.g.: ..\/..\/assets\/image.jpg).\nLazy loading\nCecil adds the attribute loading=\"lazy\" to each image.\nExample:\n![](\/image.jpg)\nIs converted to:\n&lt;img src=\"\/image.jpg\" loading=\"lazy\"&gt;\nYou can disable this behavior with the attribute {loading=eager} or with the lazy option.\nDecoding\nCecil adds the attribute decoding=\"async\" to each image.\nExample:\n![](\/image.jpg)\nIs converted to:\n&lt;img src=\"\/image.jpg\" decoding=\"async\"&gt;\nYou can disable this behavior with the attribute {decoding=auto} or with the decoding option.\nResize\nEach image in the body can be resized automatically by setting a smaller width than the original one, with the extra attribute {width=X}.\nExample:\n![](\/image.jpg){width=800}\nIs converted to:\n&lt;img src=\"\/thumbnails\/800\/image.jpg\" width=\"800\" height=\"600\"&gt;\nRatio is preserved (height attribute is calculated automatically), the original file is not altered and the resized version is stored in \/thumbnails\/&lt;width&gt;\/.\nThis feature requires an image processing library: Imagick is used first if available (and able to read JPEG and PNG), then libvips (through the PHP FFI extension), and finally GD as fallback; otherwise it only adds a width HTML attribute to the img tag.\nlibvips support is optional and is not bundled with cecil.phar. To use it, Cecil must be installed with Composer, and you need:\n\nlibvips installed on your system\nthe PHP FFI extension enabled\nthe intervention\/image-driver-vips package installed alongside Cecil\n\nIf Cecil is a dependency of your project (see Library):\ncomposer require intervention\/image-driver-vips\nIf Cecil is installed globally:\ncomposer global require cecil\/cecil intervention\/image-driver-vips\nFormats\nIf the formats option is defined, alternatives images are created and added.\nExample:\n![](\/image.jpg)\nCould be converted to:\n&lt;picture&gt;\n  &lt;source srcset=\"\/image.avif\" type=\"image\/avif\"&gt;\n  &lt;source srcset=\"\/image.webp\" type=\"image\/webp\"&gt;\n  &lt;img src=\"\/image.jpg\"&gt;\n&lt;\/picture&gt;\nPlease note that not all image formats are always included in the PHP image extensions.\nResponsive\nIf the responsive option is enabled, then all images in the body will be made responsive automatically.\nExample:\n![](\/image.jpg){width=800}\nwill be converted to:\n&lt;img src=\"\/thumbnails\/800\/image.jpg\" width=\"800\" height=\"600\"\n  srcset=\"\/thumbnails\/320\/image.jpg 320w,\n          \/thumbnails\/640\/image.jpg 640w,\n          \/thumbnails\/800\/image.jpg 800w\"\n  sizes=\"100vw\"\n&gt;\nBecause a body image is converted into an Asset, the different widths must be defined in assets configuration.\nThe sizes attribute takes the value of the assets.images.responsive.sizes.default configuration option, but it can be changed by creating a new entry named after a class added to the image.\nExample:\nassets:\n  images:\n    responsive:\n      sizes:\n        default: 100vw\n        my_class: \"(max-width: 800px) 768px, 1024px\"\n![](\/image.jpg){.my_class}\nYou can combine formats and responsive options.\nCSS class\nYou can set a default value to the class attribute of each image with the class option.\nCaption\nThe optional title can be used to create a caption (figcaption) automatically by enabling the caption option.\nExample:\n![](\/images\/img.jpg \"Title\")\nIs converted to:\n&lt;figure&gt;\n  &lt;img src=\"\/image.jpg\" title=\"Title\"&gt;\n  &lt;figcaption&gt;Title&lt;\/figcaption&gt;\n&lt;\/figure&gt;\nCaption supports Markdown content.\nLocalized image\nFor translated pages, Cecil first looks for a language-suffixed file when resolving Markdown image paths.\nExample:\n![](\/images\/cecil-logo.png)\nWith a French page (fr), Cecil tries \/images\/cecil-logo.fr.png first, then falls back to \/images\/cecil-logo.png.\nPlaceholder\nAs images are typically heavier and slower resources, and they don’t block rendering, we should attempt to give users something to look at while they wait for the image to arrive.\nThe placeholder attribute accepts two options:\n\ncolor: display a colored background (based on image dominant color)\nlqip: Low-Quality Image Placeholder\n\nExamples:\n![](\/images\/img.jpg){placeholder=color}\n![](\/images\/img.jpg){placeholder=lqip}\nYou can set a value to the placeholder attribute for each image with the placeholder option.\nThe lqip option is not compatible with animated GIF.\nTable of contents\nYou can add a table of contents with the following Markdown syntax:\n[toc]\nBy default, the ToC extracts H2 and H3 headings. You can change this behavior with body options.\nExcerpt\nAn excerpt can be defined in the body with one of those following tags: excerpt or break.\nExample:\nIntroduction.\n&lt;!-- excerpt --&gt;\nMain content.\nThen use the excerpt_html filter in your template.\nNotes\nCreate a Note block (info, tips, important, etc.).\nExample:\n:::tip\n**Tip:** This is advice.\n:::\nIs converted to:\n&lt;aside class=\"note note-tip\"&gt;\n  &lt;p&gt;\n    &lt;strong&gt;Tip:&lt;\/strong&gt; This is advice.\n  &lt;\/p&gt;\n&lt;\/aside&gt;\nTip: This is advice.\nOthers examples:\nempty\ninfo\ntip\nimportant\nwarning\ncaution\nSyntax highlight\nCode block syntax highlighting is enabled by default with the pages.body.highlight option.\nIf needed, you can disable it with:\npages:\n  body:\n    highlight: false\nExample:\n\n```php\necho \"Hello world\";\n```\n\nIs rendered to:\necho \"Hello world\";\nYou can customize the syntax highlighting style by creating your own theme. See the Highlight.js Theme Guide.\nInserted text\nRepresents a range of text that has been added.\n++text++\nIs converted to:\n&lt;ins&gt;text&lt;\/ins&gt;",
      "content_html": "<h1>Markdown</h1>\n<p>Cecil supports <a href=\"http://daringfireball.net/projects/markdown/syntax\" target=\"_blank\" rel=\"noopener noreferrer\">Markdown</a> format, but also <a href=\"https://michelf.ca/projects/php-markdown/extra/\" target=\"_blank\" rel=\"noopener noreferrer\">Markdown Extra</a>.</p>\n<p>Cecil also provides <strong>extra features</strong> to enhance your content, see below.</p>\n<h2 id=\"attributes\">Attributes</h2>\n<p>With <a href=\"https://michelf.ca/projects/php-markdown/extra/\" target=\"_blank\" rel=\"noopener noreferrer\">Markdown Extra</a> you can set an id, class and custom attributes on certain elements using an attribute block.<br>\nFor instance, put the desired attribute(s) after a header, a fenced code block, a link or an image at the end of the line inside curly brackets, like this:</p>\n<pre><code class=\"language-markdown hljs markdown\" translate=\"no\"><span class=\"hljs-section\">## Header {#id .class attribute=value}</span></code></pre>\n<aside class=\"note note-warning\"><p>For an inline element, like a link, you must use a line break after the closing brace:</p>\n<pre><code class=\"language-markdown hljs markdown\" translate=\"no\">Lorem ipsum [<span class=\"hljs-string\">dolor</span>](<span class=\"hljs-link\">url</span>){attribute=value} \nsit amet.</code></pre></aside>\n<h2 id=\"links\">Links</h2>\n<p>You can create a link with the syntax <code translate=\"no\">[Text](url)</code>, where <code translate=\"no\">url</code> can be a path, a relative path to a Markdown file, an external URL, etc.</p>\n<p><em>Example:</em></p>\n<pre><code class=\"language-markdown hljs markdown\" translate=\"no\">[<span class=\"hljs-string\">Link to a path</span>](<span class=\"hljs-link\">/about/</span>)\n[<span class=\"hljs-string\">Link to a Markdown file</span>](<span class=\"hljs-link\">/about/</span>)\n[<span class=\"hljs-string\">Link to Cecil website</span>](<span class=\"hljs-link\">https://cecil.app</span>)</code></pre>\n<aside class=\"note note-info\"><p>A relative link to a Markdown file is resolved from the folder of the current file (as on GitHub), then replaced by the URL of the targeted page.</p></aside>\n<h3 id=\"link-to-a-page\">Link to a page</h3>\n<p>You can easily create a link to a page with the syntax <code translate=\"no\">[Page title](page:page-id)</code>.</p>\n<p><em>Example:</em></p>\n<pre><code class=\"language-markdown hljs markdown\" translate=\"no\">[<span class=\"hljs-string\">Link to a blog post</span>](<span class=\"hljs-link\">page:blog/post-1</span>)</code></pre>\n<h3 id=\"external\">External</h3>\n<p>By default external links have the following value for <code translate=\"no\">rel</code> attribute: <code translate=\"no\">noopener noreferrer</code>.</p>\n<p><em>Example:</em></p>\n<pre><code class=\"language-html hljs xml\" translate=\"no\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a</span> <span class=\"hljs-attr\">href</span>=<span class=\"hljs-string\">\"&lt;url&gt;\"</span> <span class=\"hljs-attr\">rel</span>=<span class=\"hljs-string\">\"noopener noreferrer\"</span>&gt;</span>Link to another website<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">a</span>&gt;</span></code></pre>\n<p>You can change this behavior with <a href=\"../configuration/4-pages.md#pages-body-links\"><code translate=\"no\">pages.body.links.external</code> options</a>.</p>\n<h3 id=\"embedded-links\">Embedded links</h3>\n<p>Cecil can try to turn a link into embedded content by using the <code translate=\"no\">{embed}</code> attribute or by setting the global configuration option <code translate=\"no\">pages.body.links.embed.enabled</code> to <code translate=\"no\">true</code>.</p>\n<aside class=\"note note-important\"><p>Only <strong>YouTube</strong>, <strong>Vimeo</strong>, <strong>Dailymotion</strong>, and <strong>GitHub Gists</strong> links are supported.</p></aside>\n<p><em>Example:</em></p>\n<pre><code class=\"language-markdown hljs markdown\" translate=\"no\">[<span class=\"hljs-string\">CECIL : LE générateur de SITES STATIQUES en PHP</span>](<span class=\"hljs-link\">https://www.youtube.com/watch?v=ur8koU0iYvc</span>){embed}</code></pre>\n<p><div style=\"position:relative;padding-bottom:56.25%;height:0;overflow:hidden;\">\n<iframe src=\"https://www.youtube-nocookie.com/embed/ur8koU0iYvc\" loading=\"lazy\" width=\"640\" height=\"360\" frameborder=\"0\" allow=\"accelerometer;autoplay;encrypted-media;gyroscope;picture-in-picture;fullscreen;web-share;\" allowfullscreen=\"\" style=\"position:absolute;top:0;left:0;width:100%;height:100%;border:0;background-color:#d8d8d8;\"></iframe>\n</div></p>\n<h4>Local video/audio files</h4>\n<p>Cecil can also create a video and audio HTML elements, through the file extension.</p>\n<p><em>Example:</em></p>\n<pre><code class=\"language-markdown hljs markdown\" translate=\"no\">[<span class=\"hljs-string\">Video file</span>](<span class=\"hljs-link\">video.mp4</span>){embed controls poster=/images/video-test.png}\n[<span class=\"hljs-string\">Audio file</span>](<span class=\"hljs-link\">song.mp3</span>){embed controls}</code></pre>\n<p>Is converted to:</p>\n<pre><code class=\"language-html hljs xml\" translate=\"no\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">video</span> <span class=\"hljs-attr\">src</span>=<span class=\"hljs-string\">\"/video.mp4\"</span> <span class=\"hljs-attr\">controls</span> <span class=\"hljs-attr\">poster</span>=<span class=\"hljs-string\">\"/images/video-test.png\"</span> <span class=\"hljs-attr\">style</span>=<span class=\"hljs-string\">\"max-width:100%;height:auto;\"</span>&gt;</span><span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">video</span>&gt;</span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">audio</span> <span class=\"hljs-attr\">src</span>=<span class=\"hljs-string\">\"/song.mp3\"</span> <span class=\"hljs-attr\">controls</span>&gt;</span><span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">audio</span>&gt;</span></code></pre>\n<h2 id=\"images\">Images</h2>\n<p>To add an image, use an exclamation mark (<code translate=\"no\">!</code>) followed by alternative description in brackets (<code translate=\"no\">[]</code>), and the path or URL to the image in parentheses (<code translate=\"no\">()</code>).<br>\nYou can optionally add a title in quotation marks.</p>\n<pre><code class=\"language-markdown hljs markdown\" translate=\"no\">![<span class=\"hljs-string\">Alternative description</span>](<span class=\"hljs-link\">/image.jpg \"Image title\"</span>)</code></pre>\n<aside class=\"note note-info\"><p>The path should be relative to the root of your website (e.g.: <code translate=\"no\">/image.jpg</code>), however Cecil is able to normalize a path relative to <em>assets</em> and <em>static</em> directories (e.g.: <code translate=\"no\">../../assets/image.jpg</code>).</p></aside>\n<h3 id=\"lazy-loading\">Lazy loading</h3>\n<p>Cecil adds the attribute <code translate=\"no\">loading=\"lazy\"</code> to each image.</p>\n<p><em>Example:</em></p>\n<pre><code class=\"language-markdown hljs markdown\" translate=\"no\">![](/image.jpg)</code></pre>\n<p>Is converted to:</p>\n<pre><code class=\"language-html hljs xml\" translate=\"no\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img</span> <span class=\"hljs-attr\">src</span>=<span class=\"hljs-string\">\"/image.jpg\"</span> <span class=\"hljs-attr\">loading</span>=<span class=\"hljs-string\">\"lazy\"</span>&gt;</span></code></pre>\n<aside class=\"note note-info\"><p>You can disable this behavior with the attribute <code translate=\"no\">{loading=eager}</code> or with the <a href=\"../configuration/4-pages.md#pages-body-images\"><code translate=\"no\">lazy</code> option</a>.</p></aside>\n<h3 id=\"decoding\">Decoding</h3>\n<p>Cecil adds the attribute <code translate=\"no\">decoding=\"async\"</code> to each image.</p>\n<p><em>Example:</em></p>\n<pre><code class=\"language-markdown hljs markdown\" translate=\"no\">![](/image.jpg)</code></pre>\n<p>Is converted to:</p>\n<pre><code class=\"language-html hljs xml\" translate=\"no\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img</span> <span class=\"hljs-attr\">src</span>=<span class=\"hljs-string\">\"/image.jpg\"</span> <span class=\"hljs-attr\">decoding</span>=<span class=\"hljs-string\">\"async\"</span>&gt;</span></code></pre>\n<aside class=\"note note-info\"><p>You can disable this behavior with the attribute <code translate=\"no\">{decoding=auto}</code> or with the <a href=\"../configuration/4-pages.md#pages-body-images\"><code translate=\"no\">decoding</code> option</a>.</p></aside>\n<h3 id=\"resize\">Resize</h3>\n<p>Each image in the <em>body</em> can be resized automatically by setting a smaller width than the original one, with the extra attribute <code translate=\"no\">{width=X}</code>.</p>\n<p><em>Example:</em></p>\n<pre><code class=\"language-markdown hljs markdown\" translate=\"no\">![](/image.jpg){width=800}</code></pre>\n<p>Is converted to:</p>\n<pre><code class=\"language-html hljs xml\" translate=\"no\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img</span> <span class=\"hljs-attr\">src</span>=<span class=\"hljs-string\">\"/thumbnails/800/image.jpg\"</span> <span class=\"hljs-attr\">width</span>=<span class=\"hljs-string\">\"800\"</span> <span class=\"hljs-attr\">height</span>=<span class=\"hljs-string\">\"600\"</span>&gt;</span></code></pre>\n<aside class=\"note note-info\"><p>Ratio is preserved (<code translate=\"no\">height</code> attribute is calculated automatically), the original file is not altered and the resized version is stored in <code translate=\"no\">/thumbnails/&lt;width&gt;/</code>.</p></aside>\n<aside class=\"note note-important\"><p>This feature requires an image processing library: <a href=\"https://www.php.net/manual/book.imagick.php\" target=\"_blank\" rel=\"noopener noreferrer\">Imagick</a> is used first if available (and able to read JPEG and PNG), then <a href=\"https://www.libvips.org/\" target=\"_blank\" rel=\"noopener noreferrer\">libvips</a> (through the PHP <a href=\"https://www.php.net/manual/book.ffi.php\" target=\"_blank\" rel=\"noopener noreferrer\">FFI</a> extension), and finally <a href=\"https://www.php.net/manual/book.image.php\" target=\"_blank\" rel=\"noopener noreferrer\">GD</a> as fallback; otherwise it only adds a <code translate=\"no\">width</code> HTML attribute to the <code translate=\"no\">img</code> tag.</p></aside>\n<aside class=\"note note-info\"><p>libvips support is optional and is not bundled with <code translate=\"no\">cecil.phar</code>. To use it, Cecil must be installed with <a href=\"https://getcomposer.org\" target=\"_blank\" rel=\"noopener noreferrer\">Composer</a>, and you need:</p>\n<ol>\n<li><a href=\"https://www.libvips.org/install.html\" target=\"_blank\" rel=\"noopener noreferrer\">libvips</a> installed on your system</li>\n<li>the PHP <a href=\"https://www.php.net/manual/book.ffi.php\" target=\"_blank\" rel=\"noopener noreferrer\">FFI</a> extension enabled</li>\n<li>the <code translate=\"no\">intervention/image-driver-vips</code> package installed alongside Cecil</li>\n</ol>\n<p>If Cecil is a dependency of your project (see <a href=\"../developers/2-library.md#libvips-support\">Library</a>):</p>\n<pre><code class=\"language-bash hljs bash\" translate=\"no\">composer require intervention/image-driver-vips</code></pre>\n<p>If Cecil is installed globally:</p>\n<pre><code class=\"language-bash hljs bash\" translate=\"no\">composer global require cecil/cecil intervention/image-driver-vips</code></pre></aside>\n<h3 id=\"formats\">Formats</h3>\n<p>If the <a href=\"../configuration/4-pages.md#pages-body-images\"><code translate=\"no\">formats</code> option</a> is defined, alternatives images are created and added.</p>\n<p><em>Example:</em></p>\n<pre><code class=\"language-markdown hljs markdown\" translate=\"no\">![](/image.jpg)</code></pre>\n<p>Could be converted to:</p>\n<pre><code class=\"language-html hljs xml\" translate=\"no\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">picture</span>&gt;</span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">source</span> <span class=\"hljs-attr\">srcset</span>=<span class=\"hljs-string\">\"/image.avif\"</span> <span class=\"hljs-attr\">type</span>=<span class=\"hljs-string\">\"image/avif\"</span>&gt;</span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">source</span> <span class=\"hljs-attr\">srcset</span>=<span class=\"hljs-string\">\"/image.webp\"</span> <span class=\"hljs-attr\">type</span>=<span class=\"hljs-string\">\"image/webp\"</span>&gt;</span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img</span> <span class=\"hljs-attr\">src</span>=<span class=\"hljs-string\">\"/image.jpg\"</span>&gt;</span>\n<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">picture</span>&gt;</span></code></pre>\n<aside class=\"note note-important\"><p>Please note that <strong>not all image formats</strong> are always included in the PHP image extensions.</p></aside>\n<h3 id=\"responsive\">Responsive</h3>\n<p>If the <a href=\"../configuration/4-pages.md#pages-body-images\"><code translate=\"no\">responsive</code> option</a> is enabled, then all images in the <em>body</em> will be made responsive automatically.</p>\n<p><em>Example:</em></p>\n<pre><code class=\"language-markdown hljs markdown\" translate=\"no\">![](/image.jpg){width=800}</code></pre>\n<p>will be converted to:</p>\n<pre><code class=\"language-html hljs xml\" translate=\"no\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img</span> <span class=\"hljs-attr\">src</span>=<span class=\"hljs-string\">\"/thumbnails/800/image.jpg\"</span> <span class=\"hljs-attr\">width</span>=<span class=\"hljs-string\">\"800\"</span> <span class=\"hljs-attr\">height</span>=<span class=\"hljs-string\">\"600\"</span>\n  <span class=\"hljs-attr\">srcset</span>=<span class=\"hljs-string\">\"/thumbnails/320/image.jpg 320w,\n          /thumbnails/640/image.jpg 640w,\n          /thumbnails/800/image.jpg 800w\"</span>\n  <span class=\"hljs-attr\">sizes</span>=<span class=\"hljs-string\">\"100vw\"</span>\n&gt;</span></code></pre>\n<aside class=\"note note-info\"><p>Because a body image is converted into an <a href=\"../assets/index.md#asset\">Asset</a>, the different widths must be defined in <a href=\"../configuration/6-assets.md\">assets configuration</a>.</p></aside>\n<p>The <code translate=\"no\">sizes</code> attribute takes the value of the <code translate=\"no\">assets.images.responsive.sizes.default</code> configuration option, but it can be changed by creating a new entry named after a <em>class</em> added to the image.</p>\n<p><em>Example:</em></p>\n<pre><code class=\"language-yaml hljs yaml\" translate=\"no\"><span class=\"hljs-attr\">assets:</span>\n  <span class=\"hljs-attr\">images:</span>\n    <span class=\"hljs-attr\">responsive:</span>\n      <span class=\"hljs-attr\">sizes:</span>\n        <span class=\"hljs-attr\">default:</span> <span class=\"hljs-string\">100vw</span>\n        <span class=\"hljs-attr\">my_class:</span> <span class=\"hljs-string\">\"(max-width: 800px) 768px, 1024px\"</span></code></pre>\n<pre><code class=\"language-markdown hljs markdown\" translate=\"no\">![](/image.jpg){.my_class}</code></pre>\n<aside class=\"note note-info\"><p>You can combine <code translate=\"no\">formats</code> and <code translate=\"no\">responsive</code> options.</p></aside>\n<h3 id=\"css-class\">CSS class</h3>\n<p>You can set a default value to the <code translate=\"no\">class</code> attribute of each image with the <a href=\"../configuration/4-pages.md#pages-body-images\"><code translate=\"no\">class</code> option</a>.</p>\n<h3 id=\"caption\">Caption</h3>\n<p>The optional title can be used to create a caption (<code translate=\"no\">figcaption</code>) automatically by enabling the <a href=\"../configuration/4-pages.md#pages-body-images\"><code translate=\"no\">caption</code> option</a>.</p>\n<p><em>Example:</em></p>\n<pre><code class=\"language-markdown hljs markdown\" translate=\"no\">![](/images/img.jpg \"Title\")</code></pre>\n<p>Is converted to:</p>\n<pre><code class=\"language-html hljs xml\" translate=\"no\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">figure</span>&gt;</span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img</span> <span class=\"hljs-attr\">src</span>=<span class=\"hljs-string\">\"/image.jpg\"</span> <span class=\"hljs-attr\">title</span>=<span class=\"hljs-string\">\"Title\"</span>&gt;</span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">figcaption</span>&gt;</span>Title<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">figcaption</span>&gt;</span>\n<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">figure</span>&gt;</span></code></pre>\n<aside class=\"note note-info\"><p>Caption supports Markdown content.</p></aside>\n<h3 id=\"localized-image\">Localized image</h3>\n<p>For translated pages, Cecil first looks for a language-suffixed file when resolving Markdown image paths.</p>\n<p><em>Example:</em></p>\n<pre><code class=\"language-markdown hljs markdown\" translate=\"no\">![](/images/cecil-logo.png)</code></pre>\n<p>With a French page (<code translate=\"no\">fr</code>), Cecil tries <code translate=\"no\">/images/cecil-logo.fr.png</code> first, then falls back to <code translate=\"no\">/images/cecil-logo.png</code>.</p>\n<h3 id=\"placeholder\">Placeholder</h3>\n<p>As images are typically heavier and slower resources, and they don’t block rendering, we should attempt to give users something to look at while they wait for the image to arrive.</p>\n<p>The <code translate=\"no\">placeholder</code> attribute accepts two options:</p>\n<ol>\n<li><code translate=\"no\">color</code>: display a colored background (based on image dominant color)</li>\n<li><code translate=\"no\">lqip</code>: <a href=\"https://www.guypo.com/introducing-lqip-low-quality-image-placeholders\" target=\"_blank\" rel=\"noopener noreferrer\">Low-Quality Image Placeholder</a></li>\n</ol>\n<p><em>Examples:</em></p>\n<pre><code class=\"language-markdown hljs markdown\" translate=\"no\">![](/images/img.jpg){placeholder=color}\n![](/images/img.jpg){placeholder=lqip}</code></pre>\n<aside class=\"note note-tip\"><p>You can set a value to the <code translate=\"no\">placeholder</code> attribute for each image with the <a href=\"../configuration/4-pages.md#pages-body-images\"><code translate=\"no\">placeholder</code> option</a>.</p></aside>\n<aside class=\"note note-warning\"><p>The <code translate=\"no\">lqip</code> option is not compatible with animated GIF.</p></aside>\n<h2 id=\"table-of-contents\">Table of contents</h2>\n<p>You can add a table of contents with the following Markdown syntax:</p>\n<pre><code class=\"language-markdown hljs markdown\" translate=\"no\">[toc]</code></pre>\n<aside class=\"note note-info\"><p>By default, the ToC extracts H2 and H3 headings. You can change this behavior with <a href=\"../configuration/4-pages.md#pages-body\">body options</a>.</p></aside>\n<h2 id=\"excerpt\">Excerpt</h2>\n<p>An excerpt can be defined in the <em>body</em> with one of those following tags: <code translate=\"no\">excerpt</code> or <code translate=\"no\">break</code>.</p>\n<p><em>Example:</em></p>\n<pre><code class=\"language-html hljs xml\" translate=\"no\">Introduction.\n<span class=\"hljs-comment\">&lt;!-- excerpt --&gt;</span>\nMain content.</code></pre>\n<p>Then use the <a href=\"../templates/reference/3-filters.md#excerpt-html\"><code translate=\"no\">excerpt_html</code> filter</a> in your template.</p>\n<h2 id=\"notes\">Notes</h2>\n<p>Create a <em>Note</em> block (info, tips, important, etc.).</p>\n<p><em>Example:</em></p>\n<pre><code class=\"language-markdown hljs markdown\" translate=\"no\">:::tip\n<span class=\"hljs-strong\">**Tip:**</span> This is advice.\n:::</code></pre>\n<p>Is converted to:</p>\n<pre><code class=\"language-html hljs xml\" translate=\"no\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">aside</span> <span class=\"hljs-attr\">class</span>=<span class=\"hljs-string\">\"note note-tip\"</span>&gt;</span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p</span>&gt;</span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">strong</span>&gt;</span>Tip:<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">strong</span>&gt;</span> This is advice.\n  <span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">p</span>&gt;</span>\n<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">aside</span>&gt;</span></code></pre>\n<aside class=\"note note-tip\"><p><strong>Tip:</strong> This is advice.</p></aside>\n<p><em>Others examples:</em></p>\n<aside class=\"note\"><p>empty</p></aside>\n<aside class=\"note note-info\"><p>info</p></aside>\n<aside class=\"note note-tip\"><p>tip</p></aside>\n<aside class=\"note note-important\"><p>important</p></aside>\n<aside class=\"note note-warning\"><p>warning</p></aside>\n<aside class=\"note note-caution\"><p>caution</p></aside>\n<h2 id=\"syntax-highlight\">Syntax highlight</h2>\n<p>Code block syntax highlighting is enabled by default with the <a href=\"../configuration/4-pages.md#pages-body-highlight\">pages.body.highlight</a> option.</p>\n<p>If needed, you can disable it with:</p>\n<pre><code class=\"language-yaml hljs yaml\" translate=\"no\"><span class=\"hljs-attr\">pages:</span>\n  <span class=\"hljs-attr\">body:</span>\n    <span class=\"hljs-attr\">highlight:</span> <span class=\"hljs-literal\">false</span></code></pre>\n<p><em>Example:</em></p>\n<pre>\n```php\necho \"Hello world\";\n```\n</pre>\n<p>Is rendered to:</p>\n<pre><code class=\"language-php hljs php\" translate=\"no\"><span class=\"hljs-keyword\">echo</span> <span class=\"hljs-string\">\"Hello world\"</span>;</code></pre>\n<aside class=\"note note-info\"><p>You can customize the syntax highlighting style by creating your own theme. See the <a href=\"https://highlightjs.readthedocs.io/en/latest/theme-guide.html\" target=\"_blank\" rel=\"noopener noreferrer\">Highlight.js Theme Guide</a>.</p></aside>\n<h2 id=\"inserted-text\">Inserted text</h2>\n<p>Represents a range of text that has been added.</p>\n<pre><code class=\"language-markdown hljs markdown\" translate=\"no\">++text++</code></pre>\n<p>Is converted to:</p>\n<pre><code class=\"language-html hljs xml\" translate=\"no\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ins</span>&gt;</span>text<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">ins</span>&gt;</span></code></pre>",
      "language": "en"
    },
    {
      "id": "https://cecil.app/documentation/content/multilingual/",
      "url": "https://cecil.app/documentation/content/multilingual/",
      "title": "Multilingual",
      "summary": "Translate pages through file name or front matter and link translated pages.",
      "date_published": "2021-05-07T00:00:00+00:00",
      "date_modified": "2026-10-03T00:00:00+00:00","content_text": "Multilingual\nIf your pages are available in multiple languages there is 2 different ways to define it:\nThrough file name\nThis is the common way to translate a page from the main language to another language.\nYou just need to duplicate the reference page and suffix it with the target language code (e.g.: fr).\nExample:\n├─ about.md    # the reference page\n└─ about.fr.md # the french version (`fr`)\nYou can change the URL of the translated page with the slug variable in the front matter. For example:\n---\nslug: a-propos\n---\n# about.md    -&gt; \/about\/\n# about.fr.md -&gt; \/fr\/a-propos\/\nThrough front matter\nIf you want to create a page in a language other than the main language, without it being a translation of an existing page, you can use the language variable in its front matter.\nExample:\n---\nlanguage: fr\n---\nLink translated pages\nEach translated page reference the pages in others languages.\nThose pages collection is available in templates with the following variable:\n{{ page.translations }}\nThe langref variable is provided by default, but you can change it in the front matter:\n---\nlangref: my-page-ref\n---",
      "content_html": "<h1>Multilingual</h1>\n<p>If your pages are available in multiple <a href=\"../configuration/2-languages.md#languages\">languages</a> there is 2 different ways to define it:</p>\n<h2 id=\"through-file-name\">Through file name</h2>\n<p>This is the common way to translate a page from the main <a href=\"../configuration/2-languages.md#language\">language</a> to another language.</p>\n<p>You just need to duplicate the reference page and suffix it with the target language <code translate=\"no\">code</code> (e.g.: <code translate=\"no\">fr</code>).</p>\n<p><em>Example:</em></p>\n<pre><code class=\"language-plaintext hljs plaintext\" translate=\"no\">├─ about.md    # the reference page\n└─ about.fr.md # the french version (`fr`)</code></pre>\n<aside class=\"note note-tip\"><p>You can change the URL of the translated page with the <code translate=\"no\">slug</code> variable in the front matter. For example:</p>\n<pre><code class=\"language-yml hljs yaml\" translate=\"no\"><span class=\"hljs-meta\">---</span>\n<span class=\"hljs-attr\">slug:</span> <span class=\"hljs-string\">a-propos</span>\n<span class=\"hljs-meta\">---</span>\n<span class=\"hljs-comment\"># about.md    -&gt; /about/</span>\n<span class=\"hljs-comment\"># about.fr.md -&gt; /fr/a-propos/</span></code></pre></aside>\n<h2 id=\"through-front-matter\">Through front matter</h2>\n<p>If you want to create a page in a language other than the main language, without it being a translation of an existing page, you can use the <code translate=\"no\">language</code> variable in its front matter.</p>\n<p><em>Example:</em></p>\n<pre><code class=\"language-yml hljs yaml\" translate=\"no\"><span class=\"hljs-meta\">---</span>\n<span class=\"hljs-attr\">language:</span> <span class=\"hljs-string\">fr</span>\n<span class=\"hljs-meta\">---</span></code></pre>\n<h2 id=\"link-translated-pages\">Link translated pages</h2>\n<p>Each translated page reference the pages in others languages.</p>\n<p>Those pages collection is available in <a href=\"../templates/2-variables.md#page\">templates</a> with the following variable:</p>\n<pre><code class=\"language-twig hljs twig\" translate=\"no\"><span class=\"hljs-template-variable\">{{ page.translations }}</span></code></pre>\n<aside class=\"note note-info\"><p>The <code translate=\"no\">langref</code> variable is provided by default, but you can change it in the front matter:</p>\n<pre><code class=\"language-yml hljs yaml\" translate=\"no\"><span class=\"hljs-meta\">---</span>\n<span class=\"hljs-attr\">langref:</span> <span class=\"hljs-string\">my-page-ref</span>\n<span class=\"hljs-meta\">---</span></code></pre></aside>",
      "language": "en"
    },
    {
      "id": "https://cecil.app/documentation/content/dynamic-content/",
      "url": "https://cecil.app/documentation/content/dynamic-content/",
      "title": "Dynamic content",
      "summary": "Use variables and Twig expressions inside page content.",
      "date_published": "2021-05-07T00:00:00+00:00",
      "date_modified": "2026-10-03T00:00:00+00:00","content_text": "Dynamic content\nYou can create dynamic content in a page by using the template_from_string Twig function.\n{{ include(template_from_string(page.content, \"dynamic content for page \" ~ page.id)) }}\nWith this, you can use any page variable in the body of the page.\n--\nvar: 'value'\n---\nThe value of `var` is {{ page.var }}.",
      "content_html": "<h1>Dynamic content</h1>\n<p>You can create dynamic content in a page by using the <a href=\"https://twig.symfony.com/doc/3.x/functions/template_from_string.html\" target=\"_blank\" rel=\"noopener noreferrer\"><code translate=\"no\">template_from_string</code></a> Twig function.</p>\n<pre><code class=\"language-twig hljs twig\" translate=\"no\"><span class=\"hljs-template-variable\">{{ <span class=\"hljs-name\">include</span><span class=\"hljs-params\">(template_from_string(page.content, \"dynamic content for page \" ~ page.id)</span>) }}</span></code></pre>\n<p>With this, you can use any page variable in the <em>body</em> of the page.</p>\n<pre><code class=\"language-twig hljs twig\" translate=\"no\"><span class=\"xml\">--\nvar: 'value'\n---\nThe value of `var` is </span><span class=\"hljs-template-variable\">{{ page.var }}</span><span class=\"xml\">.</span></code></pre>",
      "language": "en"
    }
  ]
}
