Last updated:

Installing system requirements

You’ll need Python 3 (at least version 3.6) and pipenv to be installed.


On macOS this is pretty straightforward; after installing Homebrew you can install these things with:

brew install python
pip3 install --user pipenv

and then add the following line to your login script (usually ~/.bash_profile):

export PATH=$HOME/Library/Python/3.7/bin:$PATH

As an alternative to homebrew you can install Python 3.6 or later from the Python website or using your package manager of choice.


Your distribution probably provides packages for python3; make sure to get python 3.6 or later, and to also install pip3 (Ubuntu keeps this in the python3-pip package; other distributions will vary).

Afterwards, you can install pipenv with either:

sudo pip3 install pipenv


pip3 install --user pipenv

If you do the latter, make sure your pip user directory is on your PATH; this will probably be $HOME/.local/bin but it might vary based on your distribution.

Also, if pip3 doesn’t work, try running just pip instead; not all distributions differentiate between Python 2 and 3 anymore.


Note: I haven’t yet managed to get Publ working under Windows. Perhaps someone with more Windows and Python experience could help me out? In the meantime, the Windows Subsystem for Linux might be a good way to go, or you could run Ubuntu under Virtualbox or the like.

  1. Install Python

    When you install, make sure to check the option for “add python to your PATH” and if you customize the installation, make sure it installs pip as well

  2. Install the Visual Studio Build Tools

    This is necessary for some of the libraries Publ depends on. If you already have Visual Studio installed with C++ support you can probably skip this step.

  3. From the command prompt, run pip install pipenv

Making a website

Copying this one (recommended)

The files for this website are in a git repository. You should be able to clone or fork that repository in order to have your own instance of it, and then you can start a local server for experimenting with:

./    # Install Publ and do various setup steps
./      # Start running the server locally

at which point connecting to http://localhost:5000 should do what you want. If you want to run on a different port you can set the PORT environment variable, e.g.:

PORT=12345 ./

will run the site at http://localhost:12345 instead.

Setting one up from scratch

Creating the environment

To make your own Publ-based site, you’ll need to use virtualenv+pip or pipenv to set up a sandbox and install the Publ package to it; I recommend pipenv for a number of reasons but if you’re familiar with virtualenv or are using a hosting provider that requires it, feel free to do that instead.

If you’re using pipenv the command would be:

pipenv --three install Publ

and if you’re doing the virtualenv approach it would be:

virtualenv env
env/bin/pip3 install Publ

Next, you’ll need a file. The absolute minimum for that is simply:

import os
import publ

APP_PATH = os.path.dirname(os.path.abspath(__file__))

config = {
    # Leave this off to do an in-memory database
    'database_config': {
        'provider': 'sqlite',
        'filename': os.path.join(APP_PATH, 'index.db')
app = publ.publ(__name__, config)
if __name__ == "__main__":'PORT', 5000))

Now, you’ll need directories for your site content:

mkdir -p content templates static

Then you can launch your (not yet very functional) site with

pipenv run python3

if you’re using pipenv, or


if you’re using virtualenv.

Now you have a site running at http://localhost:5000 that does absolutely nothing! Congratulations!

Basic templates

The following template files are available from the publ site repository.

For a fairly minimal site, create the file templates/index.html:

<!DOCTYPE html>
<title>{{ or 'My simple site' }}</title>

<h1>{{ or 'My simple site'}}</h1>
{% for entry in view.entries %}
<h2><a href="{{entry.permalink}}">{{ entry.title }}</a></h2>
{{ entry.body }}

{% if entry.more %}
<a rel="more" href="{{entry.permalink}}">More...</a>
{% endif %}
{% endfor %}


and templates/entry.html:

<!DOCTYPE html>
<title>{{ entry.title }}</title>

<h1><a href="{{}}">{{ or 'My simple site' }}</a></h1>
<h2>{{ entry.title }}</h2>

{{ entry.body }}
{{ entry.more }}


Now you can finally create a content file; for example, create a file called in the content directory:

Title: My first entry!

This is my first entry on this website.


This is the extended text.

After Publ sees the content file, it should now get some extra stuff in the headers, namely a Date, an Entry-ID, and a UUID. These are how Publ tracks the publishing information for the entry itself. It’s a good idea to leave them alone unless you know what you’re doing.

Anyway, read on for more information about how to build a bigger site!

What does what

Looking at the files for this site, here are some key things to look at:

  • Pipfile: Configures pipenv
  • Configures the Publ site
  • A Passenger wrapper, used for running the site on Dreamhost and other Passenger-WSGI hosting providers
  • Procfile: Configures the site to run on Heroku (and possibly other providers)
  • templates/: The site layout files (i.e. how to lay your content out). Some you can look at:
    • index.html: What renders when you view a “directory” (e.g. /manual)
    • entry.html: What renders when you look at an individual page (like this one)
    • feed.xml: The Atom feed
    • error.html: The error page (for example)
    • sitemap.xml: Produces a sitemap for search engines
  • content/: The content on this site (for example, this page’s content is stored in content/manual/getting
  • static/: Things that never change; for example, stylesheets and Javascript libraries. For example, this site has:
    • style.css: the global stylesheet
    • lightbox: A library used for presenting images in a gallery (example page)
    • pygments.default.css: A stylesheet used by the Markdown engine when formatting code

For more information about templates, see the manual on template formats.

For more information about content, see that manual page.

I also have made some of my own website templates available.

Putting it on the web

Getting a Publ site online depends a lot on how you’re going to be hosting it. If you’re savvy with Flask apps you probably know what to do; otherwise, check out the deployment guides to see if there’s anything that covers your usage.

Next steps

If you do end up using Publ, please let me know so that I can check it out — and maybe add it to a list of featured sites!