Cecil logo


There is 3 kinds of content in Cecil:

  1. Pages (Markdown files in content/)
  2. Static files (images, PDF, etc. in static/)
  3. Data files (custom variables collections in data/)

Files organization

Your content should be organized in a manner that reflects the rendered website.

File system tree

├─ content
|  ├─ blog               <- Section
|  |  ├─ post-1.md       <- Page in Section
|  |  └─ post-2.md
|  ├─ projects
|  |  └─ project-1.md
|  └─ about.md           <- Page in the root
├─ static
|  └─ logo.png           <- Static file
├─ assets
|  └─ styles.scss        <- Asset file
└─ data
   └─ authors.yml        <- Data collection
  • Each folder in the root of content/ is called a Section (ie: “Blog“, “Project“, etc.)
  • You can override Section’s default variables by creating ana file index.md in its directory (ie: blog/index.md)
  • Files in static/ are copied as is in the root of the built website (ie: static/images/logo.png -> images/logo.png)
  • Files in assets/ are handled with the asset() function
  • Content of files in data/ is exposed in templates with {{ site.data }}

Built website tree

└─ _site
   ├─ index.html               <- Generated home page
   ├─ blog/
   |  ├─ index.html            <- Generated list of posts
   |  ├─ post-1/index.html     <- A blog post
   |  └─ post-2/index.html
   ├─ projects/
   |  ├─ index.html            <- Generated list of projects
   |  └─ project-1/index.html
   ├─ about/index.html
   ├─ logo.png
   └─ styles.css

By default each Page is generated as filename-slugified/index.html to get a “beautiful“ URL like https://mywebsite.tld/blog/post-1/. To get an “ugly” URL (404.html instead of 404/), set uglyurl: true in front matter.

File VS URL structure

                        └───── filepath ──────┘
    ┌───── baseurl ─────┬─────── path ────────┐
                        └─ section ─┴─ slug ──┘

Page anatomy

A Page is a file made up of a front matter and a body.

Front matter

The front matter is used to store variables in a Page, in key/value format.

It must be the first thing in the file and must be a valid YAML.
Separators must be ---, <!-- --> or +++.


title: "The title"
date: 2019-02-21
tags: [tag 1, tag 2]
customvar: "Value of customvar"


Body is the main content of a Page, it could be written in Markdown, in Markdown Extra or in plain text.

Cecil provides extra features to enhance your content (image caption, image lazy loading, image resizing, responsive image, text excerpt, table of contents).
See below for more details.


# Header


## Header 1

Lorem ipsum dolor [sit amet](https://example.com), consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
<!-- excerpt -->
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

## Header 2

![Description](/image.jpg 'Title')


Lazy loading

By default Cecil apply the attribute loading="lazy" on each images.
So you can disable it in configuration.


Is converted to :

<img src="/image.jpg" loading="lazy">

You can autommatically add a caption (figcaption) to an image by adding a title.

![](/images/img.jpg 'Title')

Is converted to :

  <img src="/image.jpg" title="Title">

Each image in the body can be resized by setting a smaller width than the original image with the extra attribute {width=X} and if the resize option of the converter is enabled.

Ratio is preserved, the original file is not altered, and the resized version is stored in /assets/thumbnails/<width>/image.jpg.
This feature requires GD extension (otherwise it only add a width HTML attribute to the img tag).


Is converted to :

<img src="/assets/thumbnails/800/image.jpg" width="800" height="600">

If the responsive option of the converter is enabled, then all images in the body will be automatically responsived.


If resize and responsive options are enabled, then this Markdown line will be converted to:

<img src="/assets/thumbnails/800/image.jpg" width="800" height="600"
  srcset="/assets/thumbnails/320/image.jpg 320w,
          /assets/thumbnails/640/image.jpg 640w,
          /assets/thumbnails/800/image.jpg 800w"


An excerpt can be defined in the body with one of those following tags: excerpt or break.


<!-- excerpt -->
Main content.

Table of contents

You can add a table of contents with the following Markdown syntax:



The front matter can contains custom variables applied to the current Page.


All the predefined variables can be overridden except section.

Variable Description Default value Example
title Title File name without extension. Post 1
layout Template See Lookup rules. 404
date Creation date File creation date (PHP DateTime object). 2019/04/15
updated Modification date File modification date (PHP DateTime object). 2021/11/19
section Section Page's Section. blog
path Path Page's path. blog/post-1
slug Slug Page's slug. post-1
published Published or not false. true
draft Published or not true. false

A Page can be added to a menu.

A same Page could be added to severals menus, and the position of each entry can be defined with the weight key (the lightest first).

See Menus configuration for details.


menu: navigation
menu: [main, navigation]
    weight: 10
    weight: 20


Taxonomies are declared in the Configuration.

Each Page can contain severals terms (ie: Tag 1) of each taxonomies’ vocabulary (ie: tags).


tags: ["Tag 1", "Tag 2"]


As indicated by its name, the redirect variable is used to redirect a page to a dedicated URL.

It use the template redirect.html.twig.


redirect: "https://arnaudligny.fr/"


alias is used to create redirections to the current page.


title: "About"
  - contact

In the previous example contact/ redirects to about/.


A Page with an external variable try to fetch the content of the pointed resource.


external: "https://raw.githubusercontent.com/Cecilapp/Cecil/master/README.md"

File prefix

The filename can contain a prefix to define date or weight (used by sortby) of the Page.

The prefix is not included in the title of the Page.
Available prefix separator are -, _ and ..


The date prefix is used to set the creation date of the Page, and must be a valid date format (YYYY-MM-DD).


In 2019-04-23-My blog post.md:

  • the prefix is 2019-04-23
  • the date of the Page is 2019-04-23
  • the title of the Page is My blog post


The weight prefix is used to set the sort order of the Page, and must be a valid integer value.


In 1-The first project.md:

  • the prefix is 1
  • the weight of the Page is 1
  • the title of the Page is The first project


Some dedicated variables can be used in a custom Section (ie: blog/index.md).


The order of Pages can be changed for a Section.

Available values are:

  • date: more recent first
  • title: alphabetic order
  • weight: lightest first


sortby: title


Global pagination configuration can be overridden for a Section.


  max: 2
  path: "p"


Any values in cascade will be merged into the front matter of all sub pages.
Existing variables are not overridden.


  banner: image.jpg


Set circular to true to enable circular pagination with page.<prev/next>.


circular: true

Home page

Home page support sortby and pagination configuration.


Set pagesfrom to a valid section to use pages collection from a section.


Set exclude to true to hide the Page from lists (like Home page, Section, Sitemap, etc.).


exclude: true

exclude is different from published: an excluded page is published but it’s hidden from the Section.


If your content is available in multiple languages there is 2 ways to define it:

Language in the file name

Defines the page’s language by adding the language code in the file name.



Language in the front matter

Defines the page’s language by setting the language variable with language code as value in the front matter.


language: fr

Dynamic content

You can use variables and shortcodes in the body content.

To do this you must include a specific template instead of {{ page.content }}:

{% include page.content_template %}


Display variables

Front matter variables can be use in the body with the template’s syntax {{ page.variable }}.


var: 'value'
The value of `var` is {{ page.var }}.


Shortcodes are helpers to create dynamic content.

Built-in shortcodes

2 shortcodes are available by default:

{{ shortcode.youtube(id) }}
  • id: YouTube video ID


{{ shortcode.youtube('NaB8JBfE7DY') }}
GitHub Gist
{{ shortcode.gist(user, id) }}
  • user: GitHub user name
  • id: Gist ID


{{ shortcode.gist('Narno', 'fbe791e05b93951ffc1f6abda8ee88f0') }}

Custom shortcode

A shortcode is a Twig macro you must add in a template named shortcodes.twig.



{% extends 'macros.twig' %}

{% block macros %}

{# the "foo" shortcode #}
{% macro foo(bar = 'bar') %}
<strong>{{ bar }}</strong>
{% endmacro %}

{% endblock %}

Suggest a modification

← Quick Start Templates →