Writing pages

The content of pages are written into file in yaml format.

Technically speaking Python translate yaml files in dictionaries and lists, so within Almoststatic, pages are dictionaries of data.

To facilitate the writing of the page, the html contents can be written in markdown format which is easy to write and read and less error prone then standard html.

Pages are stored by default into ./content/pages folder, and we can arrange pages into subfolders.

Minimal page

Let see a minimal page:

---
title: My page
author: Me

content:
  - type: text_html
    id: row1
    text: |
      ## My text

      This is a **Markdown** text

- type: text_html
   id: row2
   text: |
      <h2>My second text</h2>

      And this is a plain <b>html</b> text

Every page can have some metadata values, but are not required. If omitted, default values are kept. Metadata recognized are:

key

value

default

filename

full pathname of file

Automatically calculated

pagename

name of page (same of url)

Automatically calculated

title

title of page

Should be present

description

description of page

Configurable in config.yaml

author

author of page

Configurable in config.yaml

tags

list of arbitrary tags for page

Default an empty list

templ_name

template name used to render the page

Configurable in config.yaml

extends

base page to extend

Configurable in config.yaml

cacheable

if page is cacheable it is rendered only once

set to False it page must be recalculated at every call.

date

date of page

If not declared the last date of modification

Every page must have a content key which contain a list of widgets which are rendered by templates. In the previous sample we have 2 widgets of type text_html, the first render some Markdown text and the second some html.

Each page can have a widgets_envelope which is the default envelope for each widget (see documentation for widgets below).

With this structure, the page content is send to the templ_name that extends the extends base page (see details in Jinja documentation). In this way the resulting page is a html page which contain some fixed contents like headers, navbars and footers whit a list of widgets in the middle.

With templ_name and extends metadata filed is possible to change the base look of classes of pages, i.e. you can have a look for standard pages and blog pages.

Some extra contents

Often you need more sophisticated pages, to do that you can add contents that is not automatically recognized, but that can be renderer into templates:

---
title: My page
author: Me

hero:
  id: hero
  image: hero/hero1.jpg
  text: My content

aside:
  - type: text_html
    id: intro
    class: info-box
    text: |
      ## Aside
      This content is inserted out of main content flow.

content:
  - type: text_html
    id: row1
    text: |
      ## My text

      This is a **Markdown** text

In this case, only content is automatically recognized, but hero and aside can be intercepted by templates.

Widgets

So content list is composed by widgets and the same can be for extra contents, but what is a widget?

A widget is a portion of html. His data is declared into page and the look is given by a template, so the widget:

- type: text_html
  text: |
    ## My text
    This is a **Markdown** text

is rendered by text_html.html template which look like:

<div>
   {{widget.text|safe}}
</div>

This is really the simplest widget, to see more sophisticated widgets take a look at samples. With the power of Jinja2 template system, you can use conditions and loops with full level of complexity.

Note

in {{widget.text|safe}}, "widget.text" is the field to write on page, and "|safe" is a filter (in terms of Flask) which lets the text to be rendered as is, without it, the html tags are rendered as text. So it is always needed.

Widgets fields

Almoststatic has few rules. To add a widget within a page you have to declare is type so Almoststatic can find the right template. Within a widget the only field recognized is text which is rendered as html.

You can optionally surround the widget into an envelope which is a list of 2 snippets of html code the first addedd before the widget and the second addedd after the widget. If not present a widgets_envelope at page level is searched.

Then you can add as many fields as your template requires. The following is a widget a little more complex:

- type: carousel
  id: carousel1
  class: carousel-fade
  btn_class: "btn btn-primary btn-lg"
  slides:
    - image: [carousel1/slide1.jpg, "image_class", "image_alt"]
      align: text-start
      text: |
        # My first image
        some text
      buttons: [["Learn more", "#"]]

    - image: [carousel1/slide2.jpg, "image_class1", "image_alt1"]
      text: |
        # My second image
        Another wonderful text, inline.
      buttons:
        [
          ["Gallery", "#", "btn btn-info"],
          ["Once more", "#", "btn btn-primary"],
        ]

    - image: [carousel1/slide3.jpg, "image_class2", "image_alt2"]
      align: text-end
      text: |
        # lorem text
      buttons: [["Learn more", "#", "btn btn-info"]]

In this case we have a carousel with several slides with images, text and buttons

If you like you can disable a widget, for example to choose between different solutions. Each widget can have the disable field which excludes it from rendering.

- type: text_html
  disable: True
  text: |
    ## This will never be rendered

Widgets best practices

With widgets you have a full freedom in fields. But we advise to use a consistent style of naming fields and use at least some of this

key

value

id

Every widget should have a unique id into the page, this helps to apply custom style

class

This can apply a css class to the widget

style

If id is set it’s easy to add some css style to the widget

tags

You can add a list of tags which can be used as flags to configure widgets

In the same way, use a clean style in your templates.

{# text_html

The simplest widget, display the text entered as html or markdown

parameters:
id: give a unique ID to every widget in the page
style: additional css style rules for this ID
class: set additional classes for the widget
text: text or content

-#}
{%include "include/widget_style.html" -%}
<div id="{{widget.id}}" class="{{widget.class}}">
   {{widget.text|safe}}
</div>