Refonte Front (Astro)
Contexte
Depuis quelque temps, j’ai eu le besoin d’ajouter de nouveaux types de contenus sur mon site. Des commentaires de liens, un peu à la façon d’un retweet, mais surtout inspiré par les notes de Jim Nielsen. Et puis à force de commenter, j’ai parfois eu envie de m’exprimer plus longuement, dans un éditeur de texte. Et de garder un trace de quelques pensées fugaces sur la société, le monde ou ma perception des deux. Enfin, ces devlogs, juste pour garder une trace de ce que je fais, pour réfléchir et prendre du recul en faisant.
Ça a donné lieu à un second site, fait avec eleventy, un générateur de sites statiques. Le process de publication est top, ce que ça livre est bien, j’ai pu utiliser un template, même mixer plusieurs types de liens dans un même flux. Mais bon, j’avais malgré tout un sentiment de perte quand je comparais ce blog à mon site où toute l’UI me plait énormément, même après plusieurs années : J’ai passé beaucoup de temps dessus et elle correspond bien à ce que j’aime, un peu de densité, du custom, des éléments flottants etc.
J’ai considéré porter mon thème sur le blog eleventy, mais franchement la courbe d’apprentissage était forte. Et l’autre problème, c’est que je n’avais pas envie d’avoir deux sites, surtout que j’ai déjà une page de blog.
Un site statique
Mais l’expérience du site généré m’a tellement plu que ça m’a travaillé. Mon site était en Next.js 14, un framework que je trouve overkill pour ce que je faisais et que je n’ai jamais bien maîtrisé (j’ai tenté de faire des intercepting routes, sans succès la moitié du temps le site naviguait et l’autre moitié du temps il ouvrait le dialog comme il aurait dû. La génération serveur est lente, l’intégration leaflet est pénible. Bref rien ne va.)
Au boulot j’ai utilisé un peu astro.js, et vibe-codé un “blog” de tout ce que je ne sais pas, un site d’articles généré par IA, suite à des recherche effectuées en suivant une méthodo documentée dans un skill. Pratique pour découvrir un sujet, son jargon, ses sources primaires et les enjeux. Ça m’a permis de tester et déployer un site statique et franchement, je ne voyais pas pourquoi faire autrement pour mon site qui n’a pas grand chose de dynamique.
Claude m’a filé un coup de main et on a reconstruit page par page mon site en ne faisant que de la génération statique à partir de contenus que j’ai fini par normaliser en .md avec les métadonnées en frontmatter.
Enfin, pas complètement
Mais comme toujours avec les sites statiques, ça se complique quand on veut ajouter du contenu sans repasser par l’étape de build ! Et mon site me permet de faire cela pour les liens (utilisation quotidienne) et la liste de lecture (de temps en temps, mais l’écriture du commentaire n’est JAMAIS un moment où je suis devant mon ordi prêt à ouvrir un projet de code, et remplir plein de métadonnées en markdown est laborieux).
Le résultat est ce nouveau site repris en astro avec un build incrémental (une partie des pages n’est pas re-générée) effectué sur le serveur, et re-déclenché à chaque ajout de contenu depuis mon API (qui me sert à plein de choses). L’API crée les documents markdown et republie le site. Le jour où je n’ai plus cette API, je peux toujours publier mon site via le build. Mes données sont archivées avec le code, et je n’ai plus de dépendance à typesense qui me servait d’index de recherche.
Mais, et la recherche ?
Ah oui, la recherche ! Non seulement j’ai conservé la recherche dans les liens, très utile au quotidien, mais j’ai aussi ajoute une recherche globale. J’aurais pu passer par typesense, mais je voulais commencer à réduire ma dépendance à des technos un peu complexes que je risque d’avoir du mal à maintenir sur le long terme.
J’ai parcouru quelques options et je me suis fixé sur une base SQLite générée au build avec des table Full Text Search (FTS5). Ça permet de faire du BM25 (ce que typesense ne permet pas, à mon grand damn). Ce n’est pas parfait, mais c’est super light, durable dans le temps, sans dépendance. J’aurais pu accepter la solution postgres, ce qui était mon choix initial car mon API s’appuie déjà sur une base postgres pour d’autres contenus, mais l’argument BM25 m’a poussé à tester SQLite. Peut être que je reviendrai vers PostgreSLQ plus tard, dans un soucis de cohérence.
Mes données ne vivent pas toutes dans mon repo, les liens sont trop nombreux et pas si importants pour moi, donc je les garde hors du repo, dans des dossiers rclonés et dont je fais des sauvegardes régulières. Le build du site statique va donc mettre à jours la base sqlite pour ses collections, et un script déclenché à chaque modification de lien va synchroniser les liens en sqlite en plus des modifications de fichiers.
Et t’es fier de toi ?
Franchement, je sens que ce n’est pas parfait, ça me laisse encore l’impression d’une usine à gaz, mais c’est une petite usine à gaz, sobre. Un genre de micro-usine à gaz écolo qui fait juste quelques petits prouts de temps en temps.
Ce que j’aime bien dans tout ça c’est le fait que tout réside sur le système de fichiers: code, collection et même l’index de recherche (bon il est jetable donc on s’en fiche un peu).
Je peux archiver tout ça assez facilement et le repo git me garantit une certaine pérennité de mes contenus (face à un incendie de data-center par exemple 😉).
Et maintenant ?
Mon prochain projet est de me débarrasser de typesense. Non pas que je n’aime pas typesense, mais comme je le disais, c’est une brique de plus à maintenir dans le temps. Un serveur linux, Node, Postgres me suffisent.
Donc les prochaines étapes vont être de reprendre mes trois sites qui reposent encore sur typesense pour servir des données live (mais, jamais les stocker durablement):
- Le site d’hommage à Claude Carrez, plusieurs contenus textuels et des références à des fichiers audio. Ça ira très bien dans une base postgres, et la recherche dans les ~1000 fichiers pourra passer soit par un index SQLite FTS5, soit ce sera l’occasion de tester les colonnes
tsvector, assez sobre mais sans BM25. - Le site d’hommage à Albert Ezerzer, ~300 randonnées et 2 à 4x plus de variantes. Les données sont des GPX. La solution sera sûrement un mix de pmtile (représenter les tracés) et de postgresql pour les meta-données.
- Mon Stava à moi qui stocke également des GPX et des photos avec quelques méta-données sur la rando. Un pmtile pour la carte globale est sûrement une bonne idée et les fichiers servis statiquement suffiront pour le reste.