Content
There is different kinds of content in Cecil:
- Pages
- Markdown (or plain text) files.
- Assets
- Handled assets files (i.e.: resized images, compiled Sass, minified scripts, etc.).
- Static
- Files copied as is.
- Data
- Custom variables collections.
Files organization
Pages should be organized in a manner that reflects the rendered website.
File system tree
<mywebsite>
├─ pages
| ├─ blog <- Section
| | ├─ post-1.md <- Page in Section
| | └─ post-2.md
| ├─ projects
| | └─ project-1.md
| └─ about.md <- Page in the root
├─ assets
| ├─ styles.scss <- Asset file
| └─ logo.png
├─ static
| └─ video.mp4 <- Static file
└─ data
└─ authors.yml <- Data collection
Explanation:
- Each folder in the root of
pages/
is called a Section (e.g.: “Blog“, “Project“, etc.) - You can override Section’s default variables by creating an
index.md
file in its directory (e.g.:blog/index.md
) - Files in
assets/
are handled with theasset()
function in templates - Files in
static/
are copied as is in the root of the built website (e.g.:static/video.mp4
->video.mp4
) - Content of files in
data/
is exposed in templates with{{ site.data }}
Built website tree
<mywebsite>
└─ _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
├─ styles.css
├─ logo.png
└─ video.mp4
By default each Page is generated as slugified-filename/index.html
to get a “beautiful“ URL like https://mywebsite.tld/blog/post-1/
.
To get an “ugly” URL (like 404.html
instead of 404/
), set uglyurl: true
in front matter.
File VS URL
File:
pages/my-projects/project-1.md
└───── filepath ──────┘
URL:
┌───── baseurl ─────┬─────── path ────────┐
https://example.com/my-projects/project-1/index.html
└─ section ─┴─ slug ──┘
Page anatomy
A Page is a file made up of a front matter and a body.
Front matter
The front matter is a collection of variables (in key/value format) surrounded by ---
.
Example:
---
title: "The title"
date: 2019-02-21
tags: [tag 1, tag 2]
customvar: "Value of customvar"
---
Body
Body is the main content of a Page, it could be written in Markdown or in plain text.
Example:
# Header
[toc]
## Sub-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.
## Sub-Header 2

## Sub-Header 3
:::tip
**Tip:** This is an advice.
:::
Markdown
Cecil supports Markdown format but also Markdown Extra.
Cecil also provides extra features to enhance your content, see below.
Table of contents
You can add a table of contents with the following Markdown syntax:
[toc]
Excerpt
An excerpt can be defined in the body with one of those following tags: excerpt
or break
.
Example:
Introduction.
<!-- excerpt -->
Main content.
Notes
Create a Note block (info, tips, important, etc.).
Example:
:::tip
**Tip:** This is an advice.
:::
Is converted to:
<div class="note note-tip">
<p>
<strong>Tip:</strong> This is an advice.
</p>
</div>
Syntax highlight
Enables code block syntax highlighter by setting the body.highlight.enabled option to true
.
Example:
```php echo "Hello world"; ```
Is rendered to:
echo "Hello world";
Inserted text
Represents a range of text that has been added.
++text++
Is converted to:
<ins>text</ins>
Images
Lazy loading
By default Cecil apply the attribute loading="lazy"
on each images.
Example:

Is converted to:
<img src="/image.jpg" loading="lazy">
Resize
Each image in the body can be resized by setting a smaller width than the original one with the extra attribute {width=X}
(the resize
option in the body configuration must be enabled).
Example:
{width=800}
Is converted to:
<img src="/assets/thumbnails/800/image.jpg" width="800" height="600">
Responsive
If the responsive
option in the body configuration is enabled, then all images in the body will be automatically responsived.
Example:
{width=800}
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"
sizes="100vw"
>
WebP
If the webp
option in the body configuration is enabled, an alterative image in the WebP format is created.
Example:

Is converted to:
<picture>
<source srcset="/image.webp" type="image/webp">
<img src="/image.jpg">
</picture>
Caption
You can automatically add a caption (figcaption
) to an image with the optional title.
Example:

Is converted to:
<figure>
<img src="/image.jpg" title="Title">
<figcaption>Title</figcaption>
</figure>
Audio and video
Cecil can generate audio and video HTML elements, based on the Markdown image markup, with a special alternative text as a keyword (audio
or video
).
Audio
Example:
{controls}
Is converted to:
<audio src="/video/test.mp3" controls></audio>
Video
Example:
{controls poster=/images/video-test.png style="width:100%;"}
Is converted to:
<video src="/video/test.mp4" controls poster="/images/video-test.png" style="width:100%;"></video>
Variables
The front matter can contains custom variables applied to the current Page.
It must be the first thing in the file and must be a valid YAML.
Predefined variables
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 | true . | false |
draft | Published or not | false . | true |
menu
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.
Examples:
---
menu: main
---
---
menu: [main, navigation]
---
---
menu:
main:
weight: 10
navigation:
weight: 20
---
Taxonomy
Taxonomies are declared in the Configuration.
A Page can contain several vocabularies (e.g.: tags
) and terms (e.g.: Tag 1
).
Example:
---
tags: ["Tag 1", "Tag 2"]
---
Schedule
Schedules pages’ publication.
Example:
The page will be published if current date is >= 2023-02-07:
schedule:
publish: 2023-02-07
This page is published if current date is <= 2022-04-28:
schedule:
expiry: 2022-04-28
redirect
As indicated by its name, the redirect
variable is used to redirect a page to a dedicated URL.
Example:
---
redirect: "https://arnaudligny.fr/"
---
alias
Alias is a redirection to the current page
Example:
---
title: "About"
alias:
- contact
---
In the previous example contact/
redirects to about/
.
output
Defines the output (rendred) format(s). See formats
configuration for more details.
Example:
---
output: [html, atom]
---
external
A Page with an external
variable try to fetch the content of the pointed resource.
Example:
---
external: "https://raw.githubusercontent.com/Cecilapp/Cecil/master/README.md"
---
File prefix
The filename can contain a prefix to define date
or weight
of the Page (used by sortby
).
date
The date prefix is used to set the creation date of the Page, and must be a valid date format (YYYY-MM-DD
).
Example:
In 2019-04-23-My blog post.md
:
- the prefix is
2019-04-23
- the
date
of the Page is2019-04-23
- the
title
of the Page isMy blog post
weight
The weight prefix is used to set the sort order of the Page, and must be a valid integer value.
Example:
In 1-The first project.md
:
- the prefix is
1
- the
weight
of the Page is1
- the
title
of the Page isThe first project
Section
Some dedicated variables can be used in a custom Section (e.g.: blog/index.md
).
sortby
The order of Pages can be changed in a Section.
Available values are:
date
: more recent firsttitle
: alphabetic orderweight
: lightest first
Example:
---
sortby: title
---
pagination
Global pagination configuration can be overridden in a Section.
Example:
---
pagination:
max: 2
path: "p"
---
cascade
Any values in cascade
will be merged into the front matter of all sub pages.
Example:
---
cascade:
banner: image.jpg
---
circular
Set circular
to true
to enable circular pagination with page.<prev/next>.
Example:
---
circular: true
---
Home page
Like another section Home page support sortby
and pagination
configuration.
pagesfrom
Set a valid section’s name to pagesfrom
to use pages collection from this section.
exclude
Set exclude
to true
to hide a Page from lists (like Home page, Section, Sitemap, etc.).
Example:
---
exclude: true
---
Multilingual
If your pages are 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
as a suffix in the file name.
Example:
about.fr.md
Language in the front matter
Defines the page’s language by setting the language
variable with language code
as value in the front matter.
Example:
---
language: fr
---
Reference between translated pages
Each page reference pages in others languages with the langref
variable.
The langref
variable is provided by default, but you can change it in the front matter:
---
langref: my-page-ref
---
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 %}
Experimental
Display variables
Front matter variables can be use in the body with the template’s syntax {{ page.variable }}
.
Example:
--
var: 'value'
---
The value of `var` is {{ page.var }}.
Shortcodes
Shortcodes are helpers to create dynamic content.
Built-in shortcodes
2 shortcodes are available by default:
YouTube
{{ shortcode.youtube(id) }}
id
: YouTube video ID
Example:
{{ shortcode.youtube('NaB8JBfE7DY') }}
GitHub Gist
{{ shortcode.gist(user, id) }}
user
: GitHub user nameid
: Gist ID
Example:
{{ shortcode.gist('Narno', 'fbe791e05b93951ffc1f6abda8ee88f0') }}
Custom shortcode
A shortcode is a Twig macro you must add in a template named shortcodes.twig
.
Example:
shortcodes.twig
:
{% extends 'macros.twig' %}
{% block macros %}
{# the "foo" shortcode #}
{% macro foo(bar = 'bar') %}
<strong>{{ bar }}</strong>
{% endmacro %}
{% endblock %}