Installing Pelican themes the default way is not very pleasant:

As a workaround I've been packaging my Pelican themes into simple Python packages with a sole __init__.py:

from pkg_resources import resource_filename
def path():
    '''
    Return path to theme templates and assets
    Use this value for THEME in Pelican settings
    '''
    return resource_filename(__name__, '')

This adds a dependency on setuptools but it's already present in most Python venvs anyways, so not a big deal. pkg_resources exposes full path to wherever pip installs the theme. It also handles unpacking to temporary directory if required (in case of wheels and zipped installs).

I have been using this trick for some time already, but only recently I noticed that Pelican plugins have officially transitioned to being pip-installable. They use a clever hack of adding extra packages to pelican.plugins namespace and I though it would be cool to use the same approach with themes.

Turns out it's not easy to do with setuptools, but is pretty straightforward with poetry. As a result I can now publish my themes to PyPI and provide easy invocation instructions:

# pelicanconf.py
from pelican.themes import smallweb
THEME = smallweb.path()

All the end users need to do is to add another line mentioning my theme to whichever file they use to create their Pelican venv.

On developer side we need to create pelican/themes/themename folder structure and point poetry at pelican for top-level package name. All theme files should be placed into pelican/themes/themename and one extra __init__.py file should be added there to provide path() method. See SmallWeb repository for an example.