3D Lab Website Development

Back in the day, I was a web developer. I actually learned how to program because I was too lazy to copy and paste footers, so I ended up writing my own parsers to read marked up text files into a sql database where I could use it to dynamically generate a static website. I was not looking forward to architecting a website for the 3D Lab. But when I sat down and started to put it together this weekend, I was, if nothing else, amazed by how far the html templating technology has come in the last 10 years.

I spent some time reviewing a variety of website templating tools, including Docpad and Jekyll. Both are impressively flexible, especially when coupled with Twitter's Bootstrap. But both seemed to have too steep of a learning curve for a weekend project.

Python is my language of choice for rapid prototyping, and I use Markdown for most of my writing these days.1 So I ended up settling on Pelican.


Here are the commands to quickly get it setup with the plugins I wanted to use.

$ mkvirtualenv pelican
$ pushd path/to/pelican-master/
$ python setup.py install
$ popd
$ pip install Markdown pelicanfly pybtex beautifulsoup4 watchdog

Fixes, Plugins, and Mods

Consolidating Build

I wrote a pelican plugin that consolidates articles and static data from a target shared directory, such as Dropbox. The idea is that individual authors can drop Markdown posts, images, and pubs into their own shared folders and the server will rebuild the site and post it. I used watchdog for the monitor script.

YAML Reader

For a some page types, I wanted to be able to create an index from a YAML marked up text database. In particular, the clincial services page. I modified the plugin code suggested at this post to work with Pelican 3.5 as well as to be somewhat more generic.


I eventually figured out that the subcategory plugin doesn't register its dictionary with the main generator module's metadata. It actually only required one line of code in subcategory.py, but took me about four hours to figure that out.

89. generator.context['subcategories'] = generator.subcategories


I also had to fix a bug in pelicanfly that assumed main.css exists. A simple fix is to create an empty main.css placeholder, but ideally it should be try/catched. Pelicanfly is also behind on the font awesome allowable icons. The provided update function does not handle all of the required modifications; make sure to add any additional icon names to the "icons" function in the font awesome markdown extension. (I'm not sure why it doens't just poll for all icon names.)


For the publications list, I am exporting from Zotero as (better)bibtex2 and using the pelican-bibtex plugin to parse it.

I made one fix to pelican-bibtex to support multiple bibtex files from collaborators.

55. parse_file(...) -> parse_files(...)

And another fix to pybtex/style/formatting/unsrt.py line 345 to use the Zotero dissertation type instead of PhD dissertation generically.:

# 'PhD thesis',

The publications page and search function is based on Mark Schenk's JabRef HTML export filter.

For site search I used the tipue search3 javascript plugin. This is a nice approach for a static site search; it generates a json index of the site text and then processes it on the search page using jQuery.


The page layout/look/feel is based on pelican-bootstrap3, which is a port of Twitter's Bootstrap. I'm using the Bootswatch Paper theme with Google's "Roboto" as the font-face and glyphs from Font Awesome.

Multiple Authors

Multiple authors fix

Be aware, Pelican's ({filename}/my_article.md) internal link style for markdown seems to have considerable problems with spaces, hyphens, slugs, and nested folders. It's possible that anything you want to link to has to be listed in articles_paths (ie, recursion doesn't work, even though it does for generating the articles in the first place). And note that you cannot link to a draft.

This seems like a fairly portable setup since the content in markdown and bibtex remains front-end agnostic until Pelican compiles it down into a static site. I am planning to use git for version control and rsync for deploying to the web host at http://brown.edu/Research/3DLab. Rsync can be used via ssh tunnels to traverse firewall bridges.

I can use Dropbox for contributor submissions and automatically rebuild the pages using a monitor service. In order to use Dropbox to effectively collaborate, I had to modify Pelican a bit and added a separate set of shared directories to watch for dynamic and static content. This allows me to assign a particular folder to each user.


  • Teaching

  • Lab

    • Research Updates
    • Ablation Planning
    • Endoscopy 2.0
    • Hydrocephalus
  • Clinic

    • Planning
    • Volumetry

Useful Tags

  • update
  • www
  • experiment
  • code
  • imaging
  • simulation
  • publication
  • presentation

Still To Do


  1. Thumbnails on publications

  2. Version control

  3. Add pull-image column to template for .pull_image metadata?

  4. (Low) Modify Markdown's admonitions extension to convert to bootstrap "alert" styles. (or alias admonitions class to warning-info or similar?) To some degree this can be accomplished with explicit html markup:

Warning goes here...
{:class="panel alert alert-info"}

Warning goes here...

  1. Note that there is no good way to include .class info for tables in markdown. So for a striped table, such as in the deadlines note, I used RestructuredText. For database-like pages, I use YAML. 

  2. The BetterBibtex (BBT) exporter allows you to protect title case capitalization, which is otherwise pushed to sentence case. I think this is very undesirable behavior.