Content
There is different kinds of content in Cecil:
- Pages (Markdown or plain text files in
content/
) - Assets files (images, CSS, scripts, etc. in
assets/
) - Static files (videos, PDF, etc. in
static/
) - 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
<mywebsite>
├─ content
| ├─ 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
Notes:
- Each folder in the root of
content/
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 - 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 filename-slugified/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 structure
File:
content/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 ---
.
It must be the first thing in the file and must be a valid YAML.
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, in Markdown Extra or in plain text.
Cecil also provides extra features to enhance your content: table of contents, text excerpt, image manipulation (caption, lazy loading, resizing, responsive) and notes).
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.
:::
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.
Images
Lazy loading
By default Cecil apply the attribute loading="lazy"
on each images.
Example:

Is converted to:
<img src="/image.jpg" loading="lazy">
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>
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>
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>
Variables
The front matter can contains custom variables applied to the current Page.
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/
.
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 the Page from lists (like Home page, Section, Sitemap, etc.).
Example:
---
exclude: true
---
Multilingual
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
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
---
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 %}