Alexandre Petit

Comment créer un site personnel en Python avec Pelican

Temps de lecture : 14 min.

Hello !

Dans cet article, on va voir comment créer un site personnel :

Le résultat final ressemble à ça.

If you don't give a shit about le contexte et mon processus de décision, tu peux sauter directement à la section "Créer le site". Si à un moment tu es perdu dans les explications, tu peux toujours regarder le code source de mon site.

Contexte

Cela fait plusieurs mois que j'expérimente différents supports d'écriture :

Une difficulté que je rencontre est que je n'ai pas de ligne éditoriale claire, pas de promesse.

J'ai envie d'écrire sur des sujets variés :

Et je n'ai pas envie de m'imposer de façon "push".

Pour ces deux raisons, un site personnel me semble être une bonne solution.

Aussi je veux réaliser 30 projets en Python en complément de The Developer's Brain. Créer un site personnel en python apparaît comme bon challenge !

Cadrer le projet

Ma motivation est de "claim a personal domain", de m'installer dans un coin de la carte.

Ce qui va être important pour moi est de :

Les risques que je perçois sont :

OK.

À présent, je suis mis en garde.

Choisir la technologie

Pour créer un site avec Python, j'ai d'abord pensé aux technologies suivantes :

Je me suis posé la question

Quelle framework choisir pour créer un site personnel ?

Je suis tombé sur ce fil Reddit Best framework for portfolio website?.

Les réponses sont unanimes : utiliser Django ou Flask revient à se compliquer la vie. Un générateur de site statique est plus simple, moins cher et plus rapide.

Un générateur de sites statique est une application qui prends en entrée des fichiers textes et les converti en fichiers HTML.

Les générateurs de site statique ont les avantages suivants : - Simplicité : ils sont en général plus simple à appréhender que les frameworks Fullstack qui présentent davantage de fonctionnalités comme de l'authentification, des interactions avec une base de donnée. - Prix : il existe de nombreuses solutions d'hébergement gratuit - SEO : les pages sont statiques et donc facilement indexables par les moteurs de recherche

Je me suis donc tourné vers les générateurs de site statique.

Choisir un générateur de site statique

Les solutions les plus tendances sont :

Jekyll existe depuis 2008. L'outil est écrit en Ruby. Plus de 180k sites web sont construit avec, et c'est la technologie qui est proposée par défaut pour Github Pages. Il bénéficie communauté, d'un écosystème de plugins. La galerie démontre qu'il est possible de faire des sites esthétiques et complets avec.

Hugo existe depuis 2013. Il est écrit en Go et se veut le générateur statique le plus rapide (en termes de compilation). Il est utilisé par presque 300k sites. Il dispose de fonctionnalités de localisation, et peut être associé à des frameworks CSS comme Tailwind.

Astro est un générateur de site statique qui permet de combiner Svelte, React et Vue. Je l'ai tout de suite écarté car un wrapper autour de frameworks indique une complexité élevée.

Et python ?

Il existe bien un générateur de sites statiques en python : Pelican.

Pelican existe depuis 2010 et a été créé par Alexis Metaireau. Il est utilisé par seulement 3500 sites, mais il dispose d'une documentation claire. Et comme il est écrit en python, je pourrai contribuer au code source au besoin. Au première abord, il dispose de toutes les fonctionnalités dont j'ai besoin : il y a une section blog, des pages on peut ajuster le style.

Je choisis donc Pelican.

Choisir une solution de déploiement

Il existe des dizaines de solutions pour déployer un site statique, parmi lesquelles :

Je veux une solution gratuite et simple.

J'ai entendu beaucoup de bien de Github Pages.

Je vais tester cette solution.

Créer le site

Ok, on entre dans le vif du sujet.

Dans la suite de l'article, on va suivre ensemble les étapes que j'ai suivi pour construire mon site personnel https://petitalx.io.

petitalx est mon username Github. Naturellement, vous pouvez remplacer toutes les occurrences de petitalx par votre username. Vous ne pourrez pas copier coller toutes les instructions. Mais cela fera travailler votre mémoire mécanique :).

Une version vidéo de ce tutoriel est disponible sur ma chaîne Youtube : https://www.youtube.com/watch?v=cdcrieAV6Wk

Créer un walking skeleton

Notre premier objectif est de configurer et déployer un site le plus rapidement possible. On pourra ensuite itérer pour ajuster le style, ajouter du contenu, et simplifier le code.

Pré-requis :

Initialisation du projet

On commence par créer le projet en local.

cd ~/dev
mkdir petitalxio
cd petitalxio

python --version 
python -m venv .venv
source .venv/bin/activate

Créer un fichier requirements.txt avec la lignepelican[markdown] :

echo "pelican[markdown]" > requirements.txt

Puis installer les dépendances

pip install -r requirements.txt

Lancer l'assistant de création de site

pelican-quickstart

OK !

Pour visionner le site en local, lancer les commandes

cd ~/dev/petitalxio/_pelican
pelican content
pelican --listen

Remarque : vous pouvez ensuite supprimer le dossier _pelican/output car dans la section suivante nous allons changer le chemin de sortie des fichiers.

Publier sur Github Pages

Rendez-vous sur votre compte Github : https://github.com/.

Créer un nouveau repository username.github.iousername est votre nom d'utilisateur Github. Ne pas initialiser le README ni le .gitignore à ce stade.

De retour sur votre poste, se replacer à la racine du projet

cd ~/dev/petitalxio`

Créer un fichier .gitignore avec le contenu suivant

.venv  
**__pycache__**/

(par exemples avec la commande echo ".venv \n**__pycache__**/" > .gitignore)

Initialiser le dépôt git

echo "# petitalx.github.io" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin https://github.com/petitalx/petitalx.github.io.git
git push -u origin main

La façon la plus simple de déployer le site est de générer le contenu du site à la racine du répertoire. Pour faciliter les manipulations, on va modifier le Makefile afin que la commande make publish génère le site à la racine du répertoire.

Ouvrir le fichier _pelican/Makefile et modifier la ligne OUTPUTDIR tel que

OUTPUTDIR=$(BASEDIR)/..

Lancer make publish depuis ~/dev/petitalxio/_pelican.

Depuis la racine du répertoire, lancer

git status
git add .
git commit -m "generate content"
git push

Vérifier que le déploiement est en cours dans le volet "Actions" du répertoire Github :

Une fois le déploiement terminé, votre site est accessible à l'adresse https://username.github.io

Notre site personnel est en ligne !

🚀

Ajouter les premiers contenus

Dans cette section, on va voir :

Depuis le dossier _pelican, lancer la commande make devserver afin de lancer le serveur et d'activer le mode auto-reload. Le mode auto-reload va générer les fichiers html locaux de façon automatique dès lors qu'un fichier est modifié.

Création d'une page now

À quoi bon créer un site personnel si l'on y met pas une page "now" ? 🤷‍♂️.

Une page now est une page qui indiquer au visiteur ce que l'on fait actuellement. Ton portfolio donne une bonne idée de ce que tu as réalisé par le passé. Ta page now donne un aperçu de ce qui t'occupe actuellement.

L'idée est de mettre dedans ce que tu raconterais à un amis que tu n'as pas vue depuis un an :

Créer un fichier now.md dans le dossier ~/dev/petitalxio/_pelican/content/pages :

---
Title: Now
---

> Mis à jour le 28 juillet 2024 à Rouen, France.

Je travail actuellement pour EDF en tant que Software Engineer où je développe un service de détection d'anomalies sur des séries temporelles.

Mon axe de travail sur les prochains mois sont de rassembler et synthétiser les 99 meilleurs livres sur le Software Engineering. 

En complément de ce projet axé sur la théorie, je réalise réaliser 100 challenges en Python. Ce site constitue l'un des challenges.

Et regarder le résultat sur la page http://127.0.0.1:8000

Si vous cherchez des exemples de pages "now", consultez

Création d'un premier article

Créer un fichier mon-premier-article.md dans le dossier ~/dev/petitalxio/_pelican/content/ :

Title: J'ai publié mon premier article !
Date: 2024-07-27

Hello les amis.

Voici mon premier article de blog. 

Il est expose les différents formats de markdown

Une liste non numérotée : 

- a
- b

Une liste numérotée : 

1. Cookie
2. Beurre

Une citation 

> When the student is ready, the master will appear - Bruce Lee

Un échantillon de code `print("hello")`

Visualiser et publier les mises à jour

Pour visionner le résultat en local, lancer :

cd ~/dev/petitalxio/_pelican
make devserver

Pour déployer, lancer

cd ~/dev/petitalxio/_pelican
make publish

cd ~/dev/petitalxio/
git add . ; git commit -m "update content"; git push

Vous avez maintenant toutes les clés en main pour ajouter du contenu sur votre site.

Pour aller plus loin, la documentation est là pour vous aider.

Mettre en forme

À présent que l'on a travaillé le fond, passons à la forme.

Dans cette section, je te propose de faire évoluer le design de notre site personnel vers ce style, qui est un mélange entre le site personnel de Derek Sivers, et la simplicité de http://bettermotherfuckingwebsite.com/

Pour cela, on va repartir d'un thème "simple".

Mise en place d'un thème explicite

Tout est à plat !

Ajout d'une feuille de style CSS

Coller le contenu suivant dans un fichier _pelican/themes/petitalxio/static/style.css

body {
  max-width: 650px;
  margin: 40px auto;
  padding: 0 10px;
  font: 18px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
  color: #444;
}

h1 > a {
    color: #444;
}

@media (prefers-color-scheme: dark) {
  body {
    color: #c9d1d9;
    background: #0d1117;
  }

  a:link {
    color: #58a6ff;
  }
}

Puis ajouter la référence à la feuille de style dans le fichier template base.html :

<!DOCTYPE html>
<html>
  <head>
    {% block head %}
      <title>{{ SITENAME|striptags }}</title>
      <meta charset="utf-8" />
      <meta name="generator" content="Pelican" />

      <!-- 👇👇👇👇👇👇👇 -->
      <link rel="stylesheet" type="text/css" href="{{ SITEURL }}/theme/style.css" />
      <!-- 👆👆👆👆👆👆👆 -->

      <!-- ... suite du template -->

Régénérer, et le tour est joué.

Attention, pour que pelican embarque la feuille de style sans configuration supplémentaire, il est nécessaire qu'elle se trouve dans un dossier qui soit nommé "static" placé à la racine du thème. L'exemple themes/petitalxio/static/style.css valide ces conditions.

Finalement, lancer les commandes suivantes afin de déployer votre site web :

shell
cd ~/dev/petitalxio/_pelican
make publish

cd ..
git status  
git add .
git commit -m "update website"
git push

Simplifier le template

On va à présent simplifier les templates suivants :

Commençons par le fichier base.html :

Continuer avec index.html :

Poursuivre avec le template article.html :

Et terminer avec page.html

Création d'une page Home personnalisée

Créer un fichier home.md dans `_pelican/content/pages/

---  
Title: Home
---  

## Moi en 10 secondes  

Je suis un développeur Python.  

Je suis né à Rouen.  

Et j'habite actuellement à Rouen.

[now](now) résulte en un lien html relatif à la l'url courante. Si on est à l'url petitalx.io/pages/home.html, cela donne petitalx.io/pages/now. Le pré-processeur {filename} ne semble pas fonctionner chez moi.

Ajouter les lignes suivantes dans le fichier pelicanconf.py. Cela va créer une variable globale HOME qui va contenir le contenu HTML.

# En tête de fichier :
from pelican.readers import MarkdownReader  
from pelican.settings import DEFAULT_CONFIG

# Plus bas :
config = DEFAULT_CONFIG.copy()  
HOME, _ = MarkdownReader(config).read("content/pages/home.md")

On peut à présent faire injecter le contenu de la variable HOME dans le template de l'index. Ajouter la ligne {{ HOME }} à la suite de la ligne {% block content %} dans le fichier _pelican/themes/petitalxio/templates/index.html. Le début de votre fichier doit alors resembler à cela :

{% extends "base.html" %}  
{% block content %}  

    {{ HOME }}

Régénérer, et admirer le résultat.

BONUS : Code minimalism

Ok, on a bien simplifié le design !

Maintenant, j'aimerais simplifier le code.

Cette étape peut paraître superflu. Mais vous allez voir, après on se sent mieux.

Chaque fichier, chaque ligne de code qui est dans notre projet représente un cout. C'est une ligne de plus à lire lorsque l'on cherche à faire évoluer notre site, un fichier en plus à maintenir, une information supplémentaire à traiter.

Dans cette section, on va éliminer le code inutile.

Ne plus générer les pages qui ne nous servent pas

Commencer par désactiver la génération des pages "Author", "Authors", "Tag", ... en ajoutant ces lignes au fichier pelicanconf.py :

TAG_SAVE_AS = ''  
TAGS_SAVE_AS = ''  
CATEGORY_SAVE_AS = ''  
CATEGORIES_SAVE_AS = ''  
AUTHOR_SAVE_AS = ''  
AUTHORS_SAVE_AS = ''  
ARCHIVES_SAVE_AS = ''

Nettoyer le dossier des templates pour ne conserver que les 4 fichiers suivants :

templates
├── article.html
├── base.html
├── index.html
├── page.html

Nettoyer le fichier de configuration

Nettoyer le fichier pelicanconf.py - supprimer la variable LINKS : c'était une variable custom du template initial - supprimer la variable SOCIAL : idem, elle ne sert plus - supprimer la variable DEFAULT_PAGINATION qui utilise déjà la valeur par défaut - supprimer le code commenté relatif à RELATIVE_URLS - supprimer le lignes qui annulent la génération du feed

Nettoyer le Makefile

Le Makefile généré par pelican-quickstart met à disposition des commandes utiles.

Je te propose de ne conserver que le strict minimum pour développer efficacement : - help : affiche l'aide du Makefile - clean : supprime les fichiers HTML et XML de sortie - devserver : lance le serveur local et le hot reload - publish : génère le site la config serveur - github : génère le site et upload notre repository sur Github

En regardant le détail de commande, on se rend compte que la commande clean est dangereuse en l'état. Comme on génère le site à la racine du repo, lancer make clean entraine la suppression de tous nos fichiers !

Aussi, la commande Github utilise ghp. Ce n'est pas l'option que nous avons choisi pour déployer.

Voici la version du fichier mise à jour (à partir de la ligne help) :

help:
    @echo 'Makefile for a pelican Web site                                           '
    @echo '                                                                          '
    @echo 'Usage:                                                                    '
    @echo '   make clean                          remove the generated files         '
    @echo '   make publish                        generate using production settings '
    @echo '   make devserver [PORT=8000]          serve and regenerate together      '
    @echo '   make github                         upload the web site                '
    @echo '                                                                          '
    @echo 'Set the DEBUG variable to 1 to enable debugging, e.g. make DEBUG=1 html   '
    @echo 'Set the RELATIVE variable to 1 to enable relative urls                    '
    @echo '                                                                          '

clean:
    rm $(OUTPUTDIR)/**.html; rm -rf "$(OUTPUTDIR)/feeds"; rm -rf "$(OUTPUTDIR)/pages"; rm -rf "$(OUTPUTDIR)/theme"

devserver:
    "$(PELICAN)" -lr "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(CONFFILE)" $(PELICANOPTS)

publish:
    "$(PELICAN)" "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(PUBLISHCONF)" $(PELICANOPTS)

github: publish
    git add -A
    git commit -m "Update site"
    git push origin $(GITHUB_PAGES_BRANCH)


.PHONY: help clean devserver publish github

Enfin, il est aussi possible de supprimer le fichier _pelican/tasks.py qui fait doublon avec notre Makefile.

Et voilà.

Le projet est finalement très simple :)

Conclusion

Ressources utiles

Je pose ici quelques pistes pour aller plus loin avec Pelican :

Publié le

Une remarque ? Dis-moi 💙