Customizing Pelican for Static and Dynamic Content

Posted by Mischa Fisher in Technology   
Sun 13 September 2015

As is typical with these sorts of things, the online community has been very helpful in sorting out exactly how I wanted to customize this site when I recently rebuilt it using the Python static site generator Pelican.

A brief summary of a few changes I think were extremely helpful in tweaking the stock Pelican build:

Using Math

Mathjax seemed to be the simplest solution. Embedding the information via a short snippet of code linking to their CDN, and then using simple LaTeX notation within Markdown takes only a minute or two:

<script         src=''></script>

Using Bootstrap for Responsive CSS

Erik Flowers Bootstrap grid introduction is a very nice resource (Click Here)

Customizing Your Own Theme

Web developer Robert Iwancz made a great bare bones framework on which one can build out almost anything. (Click Here for his VoidyNullness Theme)

Using Pelican for a Static Landing Page

Find your .md markdown file that you want to use as your home page content and add the following metadata to the top of the file: (the second change is to prevent your home page from appearing in the menu twice, depending on your theme).

save_as: index.html
status: hidden

Then in a separate .md file that will become your blog content, add the metadata identifier at the top to assign the appropriate HTML template from your templates folder:

Title: (Your Blog Title)
Date: (The Date)
Category: Page
Template: (the title of your blog template, without the .html extension

Finally, copy the content generating loops from the default page templates into your new blog html template:

{% block content_body %}
{% block article %}
{% if articles %}
  {% for article in (articles_page.object_list if articles_page else articles) %}
    {% include "includes/" + file %}
  {% else %}
    {% include "includes/article_header.html" %}
  {% endfor %}

  {% if ARTICLE_FULL_FIRST is defined and loop.first and not articles_page.has_previous() %}
    <div class="content-body">
    {% if article.standfirst %}
      <p class="standfirst">{{ article.standfirst|e }}</p>
    {% endif %}
    {{ article.content }}
    {% include "includes/comments.html" %}
  {% else %}
    {% include "includes/index_summary.html" %}
  {% endif %}

<hr />
  {% endfor %}
{% endif %}
{% endblock article %}

{% block pagination %}
<nav class="index-pager">
{% if articles_page and articles_paginator.num_pages > 1 %}
    <ul class="pagination">
    {% if articles_page.has_previous() %}
        <li class="prev">
          <a href="{{ SITEURL }}/{{ articles_previous_page.url }}">
        <i class="fa fa-chevron-circle-left fa-fw fa-lg"></i> Previous
{% else %}
    <li class="prev disabled"><span>
        <i class="fa fa-chevron-circle-left fa-fw fa-lg"></i> 
{% endif %}

{% for num in articles_paginator.page_range %}
  {% if num == articles_page.number %}
    <li class="active"> <span>{{ num }}</span> </li>
  {% else %}
      <a href="{{ SITEURL }}/{{ }}">{{ num }}</a>
  {% endif %}
{% endfor %}

{% if articles_page.has_next() %}
    <li class="next">
      <a href="{{ SITEURL }}/{{ articles_next_page.url }}">
        Next <i class="fa fa-chevron-circle-right fa-fw fa-lg"></i>
{% else %}
    <li class="next disabled">
      <span><i class="fa fa-chevron-circle-right fa-fw fa-lg"></i> Next</span>
{% endif %}
{% endif %}

Hiding Pages from the Menu

Quite simple, just change the metadata on any given page's .md file to:

Status: Hidden

Embedding Data from a CSV

To generate my reading list, I use a piece of javascript that references the base .csv containing all the books. The script is fantastic because it allows all the flexibility of using a .csv to store the data, without needing a server side scripting language (which a static site on Amazon S3 doesn't have the luxury of relying on).

<div class="d3-chart"></div>

<script src=""></script>
<script src="d3.min.js?v=3.2.8"></script>

<script type="text/javascript"charset="utf-8">
    d3.text("/images/data.csv", function(data) {
    var parsedCSV = d3.csv.parseRows(data);

    var container =".d3-chart")


    .data(function(d) { return d; }).enter()
    .text(function(d) { return d; });

Using a Contact Form

FormSpree is ridiculously headache free and works very well (Click Here).

Adding a Parallax Effect

Using Javascript is an option since the browser does the work, rather than a server; however, I found a pure CSS approach to be cleaner and easier. Keith Clark's demo HERE is superb.