Structure of project

A typical Almoststatic project has the following structure:

├── content
│   ├── include
│   ├── media
│   ├── pages
│   └── config.yaml
├── templates
└── is a Flask app used to built your site. It can be minimalist if you only need to develop a static site or you can build a complete web app with some static contents. you can write a little script to write the static pages.

templates is the default location for Jinja template files, but you can add custom folders to search before default folder or move templates elsewhere.

content is the directory containing all directives and data for Almoststatic. it should contains at least a media folder for static contents, a pages folder for page declarations, and a config.yaml configuration file.


Flask has it’s own standard method to deliver static contents but with Almoststatic it’s suggested to use it’s method because it’s easier to configure and automate static generation, but if needed the two methods can be combined, see sample in source code.

The content/media folder

The media folder stores media (images, videos, etc…), css and javascript files. You can create any subfolder structure based on your needs to organize your site, then in templates and pages you can get them with get_media command.

The content/pages folder

This folder must contain only *.yaml files with page declarations. It can be structured in any subfolders structure and the url of pages will be the same of the path plus the name of file.

Other content subfolders

Pages can access to included contents, see Embedding and including. You can organize them into folders under content folder.

The config.yaml file

A typical config.yaml file looks like this:

# global configuration settings
   # home path for content yaml files
   content: "content"
   # home path for jinja2 templates
   templates: ["custom","templates"]
   # folder for yaml page files within content
   pages: "pages"
   # folder for media files within content
   media: "media"
   # name of default template for pages
   templ_name: "page.html"
   # url prefix for static pages
   static_url: ""
   # during development disable cache to enable auto reloading of templates
   cache: True
   # macros available in all pages
      $flask: '[Flask]({: target="_blank"}'

# default metadata for pages
   title: "My page"
   description: "A site built with Almoststatic"
   author: "Almoststatic"
   tags: [Almoststaic, Flask, Python, html]
   generator: "Almoststatic"

# specific globals for this site
slogan: Build your own static and almost static sites with Almoststatic

  - name: Home
    url: index

  - name: Pages
      - name: About
        url: about
      - name: Our products
        url: products
      - name: 404
        static_out: True
        url: nopage

  - name: Static
    static_out: True
    url: write_static

The config section contain configuration parameters, all can be omitted if default values are ok.


You can add folders to template directive, i.e. with templates: ["custom","templates"] Template files first are searched in "custom" folder and if not found in "templates" folder.

The meta section contain default metadata values for pages, all can be omitted.

The rest of definitions are free. This is a good place to store menus of site.

The content of config.yaml file is also added to Jinja2 globals environment variable so it is available on each page and each widget as a dict. So if you have a custom menu called EnglishMenu you can access to it in templates as config['EnglishMenu'] or even with a value of a variable as in config[]

The file

Almoststatic has 2 classes. The first is Almoststatic that have the rendering engine and don’t need Flask, but only Jinja2. The second is FlaskAlmoststatic which bind Almoststatic into a Flask app.

In a Flask app you can include Almoststatic in this way. First initialize the system with:

app = Flask(__name__)
app.config['FAS_CONFIG'] = "./content/config.yaml"
fas = FlaskAlmoststatic()

Then write a route to serve static pages:

def fas_pages(page):
   page_text = fas.build_page(page)
   if not page_text:
      return page_not_found(404)
   return make_response(page_text)

As you can see, the core of Almoststatic is the method build_page which do all the job.

Within the app you can combine static contents and dynamic content and do everything that Flask can do.

The script

When your site is done, you can write a little script to publish static pages. A minimalistic example is:

import almoststatic

a = almoststatic.Almoststatic()

MEDIA_PREFIX = 'media'
DESTINATION = '../_static_site'
OUT_PAGES = ['write_static', 'write_done']


The most important call is to write_static method, which require parameters to configure url’s and paths.

This do not copy media files and do not publish pages anywhere, but it’s easy to extend the script to do all you need.