Creating Your Own Themes

Theme Package Structure

Themes are essentially a folder with a manifest and a collection of templates and supporting static files (images, CSS, Javascript, etc.). Custom themes should be put in a themes folder within the site’s root. You can put themes elsewhere by specifying the THEME_DIRS setting.

A sample theme folder might look like this:

.
├── theme_id
|   ├── static
|   |   ├── scripts
|   |   |   ├── script.js
|   |   |   └── ...
|   |   ├── stylesheets
|   |   |   ├── theme.less
|   |   |   ├── reset.css
|   |   |   └── ...
|   |   ├── templates
|   |   |   ├── theme
|   |   |   |   ├── layouts
|   |   |   |   |   └── ...
|   |   |   |   ├── _footer.html
|   |   |   |   ├── base.html
|   |   |   |   ├── post_list.html
|   |   |   |   └── ...
|   ├── bundles.yaml
|   └── metadata.yaml

Theme Manifest

Each theme must contain a file called metadata.yaml that contains metadata about the theme. The theme manifest is a simple text file in YAML format. The Dark Rainbow theme manifest looks like this, for example:

name: 'Dark Rainbow'
id: 'dark_rainbow'
description: 'A dark theme with just a hint of color.'
author: 'Tyler Butler <tyler@tylerbutler.com>'
website: 'http://tylerbutler.com'
license: 'Creative Commons BY-SA 3.0'
use_precompiled_styles: no

template_dirs:
  - '../_shared/templates/'

copy_content:
  - ['../_shared/images/rss/37.png', 'images/rss.png']

settings:
  typekit_id: ~
  comments: ~
  comments_account: ~
  simple_search: yes
  bigfoot:
    enabled: yes
  sharing:
    enabled: no
    facebook:
      enabled: no
      app_id: ~
    twitter:
      enabled: no
      username: ~

Theme Manifest Parameters

name
The verbose human-readable name of the theme.
id
The ID of the theme. This must match the folder name of the theme and should not contain spaces. This is used internally by Engineer to identify the theme.
self_contained (optional)

Indicates whether the theme is self-contained or not. Defaults to True if not specified.

Note

This parameter is not currently used and may be deprecated in the future.

description (optional)
A more verbose description of the theme.
author (optional)
The name and/or email address of the theme’s author.
website (optional)
The website where the theme or information about it can be found.
license (optional)
The license under which the theme is made available.
use_precompiled_styles (optional)

Indicates whether to use precompiled stylesheets. Defaults to True.

See also

Static Content

New in version 0.5.0.

use_foundation (optional)

Indicates whether the theme makes use of the Foundation CSS library included in Engineer. Defaults to False.

Deprecated since version 0.6.0: This setting is obsolete and ignored. Themes should now use

use_jquery (optional)
Indicates whether the theme makes use of the jQuery library included in Engineer. Defaults to False.
use_lesscss (optional)
Indicates whether the theme makes use of the LESS CSS library included in Engineer. Defaults to False.
use_modernizr (optional)

Indicates whether the theme makes use of the Modernizr library included in Engineer. Defaults to True.

Changed in version 0.5.0: This setting now defaults to True instead of False.

use_normalize_css (optional)

Indicates whether the theme makes use of the normalize.css file included in Engineer. Defaults to True.

New in version 0.5.0.

use_tweet (optional)

Indicates whether the theme makes use of the Tweet library included in Engineer. Defaults to False.

Deprecated since version 0.5.0: This setting is obsolete and ignored. The Tweet library has been removed from Engineer. See the Release Notes for more information.

settings (optional)

A dictionary of all the themes-specific settings that users of your theme can provide via THEME_SETTINGS and their default values. If your theme supports custom settings, you must specify defaults. Due to the way Engineer loads your theme settings and a user’s site settings, your settings may not be created at all unless you specify them here.

New in version 0.2.3.

template_dirs (optional)

A list of paths, each relative to the path to the theme manifest file itself, that should be included when searching for theme templates. These paths are in addition to the templates folder within the theme’s folder itself, and will be searched in the order specified after the theme’s templates folder.

Like copy_content, this parameter is useful if you are creating multiple themes that share common templates. You can specify the paths to the common templates and they will be available during the build process.

template_dirs:
  - '../_shared/templates/'

New in version 0.4.0.

copy_content (optional)

A list of paths to files or directories that should be copied to the theme’s output location during a build. This is useful if you are creating multiple themes that all share some common static content (JavaScript files, images, etc.). By specifying this parameter, content will be copied to a central location for you during the build process so you can include it in your theme templates, LESS files, etc.

Tip

Since Engineer uses webassets to manage static content in version 0.6.0+, the copy_content setting should be used for content other than CSS and JavaScript files, such as images or web fonts. Style and script files should be managed using webassets bundles.

This parameter should be a ‘list of lists.’ Each entry in the list is a list itself containing two items. The first item is the path to the file or folder that should be copied. This path should be relative to the location of the theme manifest.

The second parameter should be the target location for the file or folder. The target path should be relative to the static/theme folder in the output folder.

For example, consider the following copy_content parameter in a theme manifest:

copy_content:
  - ['../Font-Awesome-More/font', 'font']
  - ['../bootswatch/img/', 'img']
  - ['../bootstrap/js/', 'js']

In this example, the ../Font-Awesome-More/font (a path relative to the location of the theme manifest file itself) will be copied to static/theme/font.

New in version 0.4.0.

Static Content

Starting with Engineer version 0.6.0, theme static content is managed using webassets. While themes can link directly to static content in their templates, using webassets is preferred. Webassets handles combining and minifying static content automatically.

New in version 0.6.0.

Bundles

Webassets uses ‘bundles’ to combine and minify static files. Bundles are essentially a collection of static files, as well as a set of filters that define what happens to the files (compiled to CSS/JS, minified, etc.), and an output file location.

Engineer includes some pre-defined bundles, which you can use in addition to defining your own. Bundles can include other bundles, so it’s easy to include the pre-defined bundles into your own if you wish. This also makes it easy to share common static content across multiple themes.

In order to define your own bundles for your theme, create a YAML file called bundles.yaml alongside your Theme Manifest. This file should contain all the bundles used in your theme. Note that while webassets itself supports defining bundles directly in Python code, Engineer currently only uses YAML input for custom theme bundles.

The bundle format itself is straightforward. As an example, this is the bundles.yaml file for the Dark Rainbow theme:

dark_rainbow_css:
  filters: less, cssmin
  contents:
    - foundation6_css
    - './static/stylesheets/dark_rainbow.less'
  output: dark_rainbow.%(version)s.css

dark_rainbow_css_bigfoot:
  filters: less, cssmin
  contents:
    - bigfoot_css
    - './static/stylesheets/bigfoot.less'
    - dark_rainbow_css
  output: dark_rainbow_bigfoot.%(version)s.css

Note that all the paths to files, both input and output, should be relative to the bundles.yaml file itself. Make sure that your output file name includes the version placeholder (%(version)s) for cache-busting purposes. See URL Expiry (cache busting) for more details.

Also, keep in mind that while all of the filters supported by webassets are available for you to use in your bundles, many of them require external dependencies that are not included in Engineer by default. If you don’t wish to require additional dependencies beyond what is included in Engineer, you should use only the cssmin, jsmin, and less filters. You can read more about all the webassets filters in the webassets documentation.

Included Bundles

Engineer includes several CSS/JavaScript libraries that you can use in your themes. These libraries are exposed as bundles. Simply add the appropriate bundle’s name to the contents of your own bundle.

jquery:
  contents:
    - './jquery-1.11.0.min.js'
  output: 'jquery.%(version)s.js'

less:
  contents:
    - './less-2.5.3.min.js'
  output: 'less.%(version)s.js'

modernizr:
  contents:
    - './modernizr-2.7.1.min.js'
  output: 'modernizr.%(version)s.js'

foundation2_css:
  contents:
    - './foundation/stylesheets/grid.css'
    - './foundation/stylesheets/mobile.css'
  output: 'foundation.%(version)s.css'
  filters: cssmin

foundation2_css_ie:
  contents:
    - './foundation/stylesheets/ie.css'
  output: 'foundation_ie.%(version)s.css'
  filters: cssmin

foundation2_js:
  contents:
    - './foundation/javascripts/foundation.js'
  output: 'foundation.%(version)s.js'
  filters: jsmin

foundation6_css:
  contents:
    - './foundation6/css/foundation.css'
  output: 'foundation6.%(version)s.css'
  filters: cssmin

foundation6_js:
  contents:
    - './foundation6/js/foundation.min.js'
  output: 'foundation6.%(version)s.js'

normalize:
  contents:
    - './normalize/normalize.css'
  output: 'normalize.%(version)s.css'
  filters: cssmin

bigfoot_css:
  contents:
    - './bigfoot/dist/bigfoot-default.css'
  output: 'bigfoot.%(version)s.css'
  filters: cssmin

bigfoot_js:
  contents:
    - './bigfoot/dist/bigfoot.js'
  output: 'bigfoot.%(version)s.js'
  filters: jsmin

Stylesheets

In addition to CSS, Engineer can automatically compile LESS stylesheets during a site build, so you are free to use LESS rather than CSS for your styles. When linking to your LESS stylesheet in your templates, you should use the render_less_link macro. This will ensure that the stylesheet is compiled as part of the site build process if needed.

Starting with Engineer 0.5.0, themes can include a ‘precompiled’ version of the LESS stylesheets they need. This is useful since in most cases users of your theme will not be making modifications to your LESS files. Thus, referencing a pre-built version of the stylesheet makes for faster builds.

In order to include a precompiled version of your stylesheets, simply add it alongside your regular stylesheet and append _precompiled to the name. For example, if your stylesheet is called dark_rainbow.less, then your precompiled version should be called dark_rainbow_precompiled.css. As long as you are referencing your stylesheet from your templates using the render_less_link macro, the precompiled version will automatically be picked up during a site build. No other changes are needed.

Required Templates

The following templates must be present in a theme’s templates/theme folder:

  • _single_post.html
  • base.html
  • post_archives.html
  • post_detail.html
  • post_list.html
  • template_page_base.html

You can of course include additional templates or template fragments, for use either internally in your theme, or that users of your theme can take advantage of to further customize their site.

You should also ensure that your theme templates load the Built-in Template Fragments that Engineer users will expect.

Images

The built-in img function will output content using a template fragment at templates/theme/_img.html. Individual themes can override this output by providing their own custom template.

The template is always passed the following keyword variables:

  • source
  • classes
  • width
  • height
  • title
  • alt
  • link

All except the source parameter are optional so the template should handle these cases appropriately. The default template looks like this:

{% if title %}
    <div class="image caption{% if classes %} {{ classes|join(' ') }}{% endif %}">
{% else %}
    <div class="image{% if classes %} {{ classes|join(' ') }}{% endif %}">
{% endif %}

{% if link %}
    <a href="{{ link }}"><img src="{{ source|trim }}"
                              {%- if width %} width="{{ width|trim }}"{%- endif %}
                              {%- if height %} height="{{ height|trim }}"{%- endif %}
                              {%- if alt %} alt="{{ alt|trim }}"{%- endif %}
                              {%- if title %} title="{{ title|trim }}"{%- endif %}/>
    </a>
{% else %}
    <img src="{{ source|trim }}"
         {%- if width %} width="{{ width|trim }}"{%- endif %}
         {%- if height %} height="{{ height|trim }}"{%- endif %}
         {%- if alt %} alt="{{ alt|trim }}"{%- endif %}
         {%- if title %} title="{{ title|trim }}"{%- endif %}/>
{% endif %}

{% if title %}
    <p>{{ title }}</p>
{% endif %}

</div>

See also

Including Images

New in version 0.5.0.

Sitemap Templates

Themes can provide custom templates for sitemap, just as individual sites can. These templates should be in the theme’s templates/theme folder.

New in version 0.3.0.

Referring to Custom Theme Settings in Templates

Custom theme settings are available in all Engineer templates. Every template is passed a context variable called theme that represents the current theme. Any custom settings specified are available as attributes on that object. For example, if your theme defines a custom setting called typekit_id, then you can refer to that setting in any Engineer template like so:

{# TYPEKIT #}
<script type="text/javascript"
       src="http://use.typekit.com/{{ theme.typekit_id }}.js"></script>
<script type="text/javascript">
   try {
       Typekit.load();
   } catch (e) {}
</script>

Useful Macros

TODO

Zipping Themes

You can optionally put your theme directory in a zip file. The file should have a .zip file extension. Engineer will unzip the folder to a temporary location during a build and load the theme from that temporary location.

New in version 0.2.3.

Sharing Your Theme

The simplest way to share your theme is to zip it up and make it available to download. Users can then download it and use it by placing it in their site’s themes directory or in another one of their THEME_DIRS.

You may wish instead to deliver your theme as an installable Python package. This allows users to download and install your theme via pip or any other tool. See Theme Plugins for more details.

Add Your Theme to Engineer

If you’d like to make your theme available with the main Engineer application, send a pull request on github.