Structure of project

A typical Almoststatic project has the following structure:

├── content
│   ├── include
│   ├── media
│   ├── pages
│   └── config.yaml
├── templates
├── flaskapp.py
└── write_static.py

flaskapp.py 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.

write_static.py is a little script used to write the static pages.

templates is the default location for Jinja template files, but you can add custom folders to search before the 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.

Note

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. If needed, the two methods can be combined; see the sample in the 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 retrieve them with the 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 as 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 the content folder.

The config.yaml file

A typical config.yaml file looks like this:

---
# global configuration settings
config:
   # 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
   macros:
      $flask: '[Flask](https://flask.palletsprojects.com){: target="_blank"}'

# default metadata for pages
meta:
   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

MainMenu:
  - name: Home
    url: index

  - name: Pages
    drop:
      - 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 contains configuration parameters, all can be omitted if default values are ok.

Note

You can add folders to the template directive, i.e. with templates: ["custom","templates"] Template files are first searched in the "custom" folder and, if not found, in the "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 for the 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[page.menu]

The flaskapp.py file

Almoststatic has 2 classes. The first is Almoststatic that has the rendering engine and doesn’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()
fas.init_app(app)

Then write a route to serve static pages:

@app.route('/<path:page>')
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 does all the job.

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

The write_static.py 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()
a.load_config()

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

a.write_static(destination=DESTINATION,
               media_prefix=MEDIA_PREFIX,
               static_url=STATIC_URL,
               out_pages=OUT_PAGES)
a.write_json_meta(destination=DESTINATION)

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.

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