Draft Forbes Group Website (Build by Nikola). The official site is hosted at:
License: GPL3
ubuntu2004
Setup
Environment
The results are shown in Installed Packages at the bottom of this notebook.
I also would like to use Sass since the HTMP5UP themes come Sass-enabled, so this needs to be installed. First you will need to install Ruby for your platform and make sure that Gems is installed. Once this is done, you can install Sass with:
Initialize a Website
To initialize a new site, activate the environment and then run
(The --demo
option will add some initial posts. If you have not use Nikola before, then you should start with this.)
Now you can build and inspect the default website:
This should build the site (all the files go into the output
folder) and then serve it at http://localhost:8000. The auto
command will watch and rebuild the site if you modify any files.
Create the Theme
Now we want to create a new theme. Since we would like to share this theme, we will create a repository for it on github. I am basing the theme on base-jinja
because I want the simplest theme (most of the styling will come from the HTML5UP templates, so I don't need anything fancy from the theme) and prefer to use the Jinja2 templating engine. (Apparently Mako is more powerful, but several people commented that for HTML, Jinja is easier to edit as it visually stands out from the HTML code.)
This places the theme into the themes/html5-massively
directory. Now I want to version control this, so I clone my version from github and put everything here:
(Note: I prefer using mercurial so I am am using the hg-git
Mercurial plugin here.)
Use the Theme
To use the theme, edit conf.py
and change the line:
Structure
Nikola Theme
Nikola themes inherit from their parent, so our theme is functional because it has base-jinja
as the parent. To better understand what is here, we can copy the base-jinja
theme for inspection.
(With some themes you can install them using nikola theme --install
to copy them, but the base themes are pre-installed and so will not be copied. If you try to install the theme, you will see where it is located.)
The theme is organized as follows:
Here is the structure of the theme. At the top level, a site is composed of posts and pages. These each have their own templates. The main entry-points are:
post.tmpl
: Use for blog posts.page.tmpl
: Use for blog posts.slides.tmpl
: Use for image slideshows.
These "extend" various other templates using the following inheritance structure:
In addition, there are a variety of helper files that are "imported":
HTML5UP Massively
The HTML5UP Massively template uses Sass for building its CSS so you ensure you have this installed (see Setup) and configured by changing the following in conf.py
:
Here is the structure of the HTML5UP Massively template:
(See below for the full Masively structure.)
The design decision here is how to merge this structure with the template structure. At one extreme, we can simply replace the top-level templates such as post.tmpl
with the Massively html files. At the other extreme, we could map every Nikola feature to a feature in the HTML template.
First we must understand the Massively structure. The structure is:
Intro: (optional). This is the massive initial display that you see when on the main page. Note that it does not appear for the generic pages. This is special and we will probably need some way of specifying it in the index file. Not sure yet.
Header: This appears after you scroll down on the main page or at the top of the generic pages. It should probably be the site title.
Navigation: These are the navigation tabs at the top of the page. They should probably be generated by some sort of post list for the site. Also included here are the social media icons which should probably be specified in the
conf.py
file.Main: This is the main content of the page. The example shown contains post elements with various classes such as
featured
which results in a large full-width post dominating top of page.Footer: Links to further pages etc., contact information.
Copyright:
Scripts: Links to various javascript etc.
My initial impression is that we should provide a specialized directive for specifying the "Intro" if that is desired on a page, use tags etc. to decide which pieces to include in navigation, and then structure subpages.
Stage 1: Minimal
Our initial minimal strategy will be to keep all of the Massively styling and just implement the HTML files as templates. To do this, we keep the HTML5UP contents in a subdirectory html5up
and make appropriate links to satisfy the Nikola theme organization requirements. Note: I originally tried the following
Following the instructions about Creating a Site (Not a Blog) with Nikola we adjust the conf.py
file as follows:
This prevents the blog part of the software from generating the main index page. Now we can create our own index page pages/index.rst
.
The next step is to insert the contents of the Massively index.html
page etc. into templates. We start by creating a special page_html5up.tmpl
template. By adding this to the conf.py
file we can use this to generate the content of the index page (only):
(Note: The order is important - more specific rules must come first.)
This gets the contents, but fails to render properly because the resources are not where they are expected to be. In particular, Massively expects the assets to be at the same level as the HTML file, but Nikola has inserted this file into the pages
subdirectory. This is easily fixed by making all the references to assets absolute src="assets/..."
→ src="/assets/..."
.
This demonstrates that everything is in place, but is not useful. The next step is to move the various bits of the Massive template into the Jinja templates. To do this, I copied all of the base templates and started editing them:
By systematically going through the templates, I was able to insert various pieces of the Massively index.html
file into the templates, preserving as much of the Nikola functionality as possible. To make things easier to test, I added the following flag to my conf.py
file:
Then, in templates, I could start by inserting the raw bits from the Massively index.html
file verbatim:
This gets something compiling quickly, then I can start merging the two once I understand things better.
A few things than need to be checked:
There is code in Nikola to use bundled css files. This needs to be check to see that it works properly. (The Massive template uses a
<noscript>...
flag to fallback if javascript is disabled... should this be bundled?)There are css files such as
nikola_rst.css
that contain formatting for RST features like admonitions. These likely will not look good with Massively and will need reformatting.To get the images working I symlinked them to the main
images
directory which makes sure they are copied over. Not sure if this is ideal. I remember that images should be managed carefully so that thumbnails get created etc. but am not sure if this should apply to background images which should instead be maintained with the theme assets.
Stage 2
The next step is to think about content: where does the content information come from? Here we need to look at how Massively is setup.
Post lists: The content of the
index.html
page is a set of teasers for posts. This should be generated by a customized post-list directive.Navigation: Nikola provides a dictionary of
NAVIGATION_LINKS
inconf.py
. We should use this to setup the main navigation (tabs). We have integrated this intobase_header.tmpl
. In order for the correct navigation tab to be highlighted, the template uses a test like{% if rel_link(permalink, url) == "#" %}
. We can use a similar test{% if permalink == "/" %}
to check if we are on the langing page. I am not sure how robust this is, but am using this for now to trigger generation of the main Info. panel inbase.tmpl
.
Deviations/Issues
CSS: The default Massively styling uses direct selectors to work. For example, the posts list styling is
#main > .posts > article
. This will break if there are intervening DIVs inserted, as is done by the post-list-directive for example. There may be some way of designing the main page to work properly with this restrictive CSS, but the easier solution is probably to remove the>
and just have the styling apply to the directed structure#main .posts article
which would allow nested DIVs. This seems to work but needs some testing. Doing so also violates the principle of minimal changes to the HTML5UP styling. We should pay and ask the author if this would be safe in general.Read more...: The Massively style provides custom "Full Story" buttons. In principle, these should be the automatically inserted "Read more..." links defined in the
INDEX_READ_MORE_LINK
variable ofconf.py
, but in order to better customize the posts. When we generate these, we thus use{{ post.text(teaser_only=True, show_read_more_link=False) }}
. This will break translation though so for a complete solution, the "Full Story" text should also be translated.Post Images: The post images play a central role in the site design, so we specify these as part of the metadata for the pages rather than as an
.. image::
. Pages should thus use a template like:
Photos
One issue that needs a good solution is figuring out how to manage images.
Default (Manual) Solution
The default solution for images is to include them in the /images
folder of the project. Then they can be references absolutely from the pages and posts. This requires manually managing the photos which is a bit of a pain, but works quite simply.
Photo Library
A preferred solution would be to manage the photos using appropriate software like iPhoto, and then programmatically import them from the library. Here we consider some options.
Use 1 of These Photo Managers If You Care About Your Photo Collection
ExifRead: Loading metadata from image files.
Reading XMP sidecar files with Python and libxmp: This is the format that Adobe Bridge uses to store metadata.
Photos (iPhoto)
Since I work with a Mac, Photos (which replaced iPhoto) is a good option for me. It appears that there is some support for using iCloud and Photos with Windows, but I have to explore this more.
The problem is how to programmatically interact with the iPhoto library. The following options exist which may meet our needs:
PyiCloud: A python interface to iCloud.
To Do
Intro: To display the "Intro" on the main page only, I used the test
{% if permalink == "/" %}
inbase.tmpl
. I do not know how robust this is.Feature Post: Add a directive for the "feature post".
Pagination: I am not sure where pagination should go. For now, there is a stub in a new block
{% block main_footer %}
inpost.tmpl
which is included inside the<div id="main></div>
. This should be autofilled when a post list takes multiple pages.
Gotchas
Here are a few things that caught me off guard:
The global context is not available in post lists. So you can't use the
html5up
variable for example to toggle behavior. (Not sure why... this is annoying.)By default, restructured text will gobble the first header and sub-header and treat them as defining the page title and subtitle. The information, however, is not actually used to change the Nikola title which is specified in the post meta-data instead. The following flags (shown with their default values) affect the behavior:
USE_REST_DOCINFO_METADATA=False
: IfTrue
, then the gobbled title will be used as post metadata. This is discussed in issue 2987.NO_DOCUTILS_TITLE_TRANSFORM=False
: IfTrue
, then disable the gobbling. Discussed in issue #2382.
I find it best to disable this "feature" setting
NO_DOCUTILS_TITLE_TRANSFORM=True
.
Resources
Nikola
Theming Nikola: Core theming documentation.
Themes for Nikola: Demonstration of Nikola themes available through the Theme Repository.
nikola-theme-html5up-massively
: My GitHub repository for the theme.Comparing Jinja and Mako:
A Better Approach For Initializing New Nikola Themes (since v7.7.5)
Logs
Installed Packages
Here are the packages that I have installed.
Structures
base-jinja
Structure
Here is the structure of the theme:
My original attempt to link this was the following:
Note: I originally tried the following
This failed, however, for a couple of reasons:
I needed to add a
sass/targets
file to specify which style sheets should be compiled. Since at this point I do not want to modify the HTML5UP source files, I needed to link the appropriate files into my ownsass
directory.Once these targets were specified, they conflicted with the pre-generated CSS files, so I also had to create that. The final structure is thus: