Switching blog engines
I switched from Hugo to pelican. Which doesn't make super much sense, I guess, from a technical perspective. But, this is my personal website and I wanted to make it completely my own. I could never muster up the energy to dive into Hugo and how to make my own theme. The theme I was using used techniques I didn't understand, so it felt hard to modify it. Somehow, pelican seems more simplistic and approachable to me personally and I don't have crazy expectations that I need to "scale" this page.
The rest of this article assumes you want to use pelican with your own theme and that you use markdown for your pages.
Getting started
The official docs are handy as a reference.
Because we are in 2024 (let's see how this will age), install pelican with pipx
:
pipx install pelican[markdown]
pipx
installs a virtual environment to ~/.local/share/pipx/venvs/pelican
and this is a good time to add any extensions we want:
pipx inject pelican pymdown-extensions
Python-Markdown
to render Markdown files and the pymdown-extensions
package contains additional syntax extensions.
We now have the pelican
CLI command available.
Let's get started:
mkdir my_project
cd my_roject
pelican-quickstart
We should now have a basic setup.
Let's enable some markdown extensions in the pelicanconf.py
file:
MARKDOWN = {
"extensions": [
# Table of contents with [TOC]: https://python-markdown.github.io/extensions/toc/
"toc",
],
'extension_configs': {
'markdown.extensions.codehilite': {'css_class': 'highlight'},
'markdown.extensions.extra': {},
'markdown.extensions.meta': {},
# Code blocks in lists etc.
# https://facelessuser.github.io/pymdown-extensions/extensions/superfences/
"pymdownx.superfences": {"disable_indented_code_blocks": True},
},
'output_format': 'html5',
}
Let's take a look at our pages and automatically re-generate them whenver we do changes:
pelican --autoreload --listen
localhost:8000
from your browser.
!!!! Download simple scheme !!!
Pelican in a nutshell
Pelican uses generators to ... generate ... content. There are two main types:
- articles: articles are additionally collected into other pages.
Create any file in
content/
. - pages: pages are stand-alone pages that are linked from the menu.
Create any file in
content/pages/
.
Beyond rendering the articles, pelican uses them to create:
index.html
: List of article titles and summaries (IMO, should be namedposts.html
).archives.html
: A chronological list of articles and their summary.- Optional: period archives: Collects articles per year and optionally month in e.g.
posts/<year>/index.html
authors.html
: Collects all authors, plus a page for each author that collects their articles inauthor/
.tags.html
: Collection of tags used in the articles and one page per tag with all the relevant articles intag/
.categories.html
: Collection of categories used in the articles and one page per category with all relevant articles incategory/
.
For the content collection pages, pagination can also be activated such that instead of listing all available items, it only lists n items and a link to the next page.
A pelican theme uses jinja2 templates to render these pages and the required templates correspond to the list above.
base.html
is used for all generated pages and most templates extend it.
It contains the header (usually a title and the naviagation/menu bar) and footer.
We have (->
means 'extend', <-
means 'imports'/'includes'):
base.html
->article.html
: Renders a single article.article.html
<-translations.html
: Provides macros ("functions") to create lists of/links to the translated article version.
base.html
->page.html
: Renders a page article.page.html
<-translations.html
: See above.
base.html
->index.html
: Lists all articles.index.html
<-pagination.html
: Provides pagination feature.index.html
->author.html
: For each author, list all articles. Just replaces titles of the index page.index.html
->category.html
: For each category, lists all articles.index.html
->tag.html
: For each tag, lists all articels.
base.html
->authors.html
: Lists all authors.base.html
->archives.html
: See above.base.html
->categories.html
: Lists all categories.base.html
->tags.html
: Lists all tags.base.html
->period_archives.html
: time-period archives.
Customizing the site
Static landing page
Use one of the following:
Using a normal post
Create a post and save it to index.html
.
---
title: Welcome!
save_as: index.html
status: hidden
---
Hello, world!
You can also use an HTML page instead, see the docs or my own page.
We still want the page of blog posts which used to be written to index.html
, so edit pelicanconf.py
:
INDEX_SAVE_AS = "posts.html"
MENUITEMS = [
("posts", "posts.html"),
]
Using a template page
For a more complicated page you may want to use a separate jinja2 HTML template.
This can then be processed by pelican and the whole context is available to the template.
pelicanconf.py
:
TEMPLATE_PAGES = {
# Processes pages/home.html with jinja (so the context is available) and saves to index.html
"pages/home.html": "index.html",
}
INDEX_SAVE_AS = "posts.html"
MENUITEMS = [
("posts", "posts.html"),
]
References
Open points
- Custom 404 page.
- https://docs.getpelican.com/en/latest/tips.html#custom-404-pages
- https://forum.netcup.de/netcup-applications/ccp-customer-control-panel/10782-404-fehlerseite/
- Template pages: landing page as template page.