Un mini CMS basé sur Laravel

Par Didier Sampaolo, CTO chez lvlup.

Puisqu'on bosse sur Laravel à longueur de journée, on s'est dit qu'il nous fallait un CMS basé sur ce framework.

Pourquoi réinventer la roue ?

C'est pas ce qu'on a l'impression de faire. Il existe déjà des solutions, comme OctoberCMS, mais elles ne font pas exactement ce qu'on voudrait.

Il nous faut un truc qu'on puisse utiliser en stand-alone sur un nom de domaine neuf, et qu'on puisse aussi ajouter à un projet existant, auquel on voudrait par exemple adjoindre un blog. Il faut que sa prise en mains soit rapide et facile. On doit avoir une optimisation SEO globalement bonne, avec une bonne gestion des liens internes.

Pour les projets où le CMS sera en stand-alone, il faut aussi qu'on puisse ajouter des liens d'affiliation, afin de monétiser le trafic du site.

Un CMS maison, c'est classe, ou pas ?

Au cours de ma carrière, j'ai déjà eu pour projet de créer des CMS ou des Frameworks. Le dernier en date était un framework PHP que j'avais appelé Bazooka, et qui me permettait de faire en 3h30 ce que j'aurais pris 4h à faire en "vanilla PHP", mais en ayant investi 200 heures de code dans le framework.

Là, ce n'est pas vraiment la même chose. Déjà, le besoin est clair et les enjeux business sont clairement identifiés. On veut un outil qui s'insèrera parfaitement dans le workflow de notre entreprise. Les juniors de la team doivent aussi se faire la main sur l'édition de site et prendre l'habitude d'identifier leurs propres besoins avant de les traduire en code. Sur les plus gros projets de la boîte, évidemment, on les aide là-dessus. Sur ce projet, ils sont 100% autonomes, et l'instruction qu'ils reçoivent le plus souvent est "démerde-toi" :D

Fonctionnalités

Les admins peuvent créer des catégories et des posts, et leur ajouter des images. On a des champs séparés pour le titre du post, la balise title et le H1 de la page. On utilise la syntaxe Markdown : ça suffit amplement pour de la mise en page simple, et ça se prend en mains en 10 minutes chrono.

Images

Lorsqu'on ajoute une image, elle est redimensionnée : on a des fichiers plus légers sur les pages "liste" (home, catégorie...) que sur le post, où l'image est affichée en grand.

Au départ, on avait pensé à redimensionner l'image, si besoin, au moment de l'affichage de la vue. On a préféré le faire quand l'image est uploadée, pour ne pas dégrader les performances à l'affichage : on aurait été obligés de faire des accès disque pour vérifier si le fichier aux bonnes dimensions était déjà présent ou non, ou "hacker" les pages 404 pour qu'elles s'en occupe, et ça nous semblait un peu crade. A la place, on a un fichier de configuration où on spécifie la listes des tailles, et une commande à lancer si on veut ajouter une ou des tailles, qui retraite toutes les images à la suite.

Indexation

Par défaut, on a un flux RSS (au format Atom - bref, un flux RSS classique) et un sitemap XML, spécialement pour Google.

Structure de liens internes

Là, on s'est un peu cassés la tête. On a fait un système qui permet d'ajouter un lien, depuis une page, vers une autre, sur l'ancre qui nous intéresse. Le lien s'insère au moment du rendu de la page : si l'URL de la destination a changé, le lien change lui aussi.

Dans la sidebar des articles, on affiche les derniers posts de la même catégorie (pour la sémantique), et les posts les plus récents (pour les aider à s'indexer). Si un article reçoit déjà un lien depuis le contenu du post, on l'enlève de la sidebar, pour éviter les liens en double vers la même URL.

Le système nous permet aussi, sans quitter le backoffice du site, de surveiller le profil des ancres qui pointent vers chaque article, et le nombre de liens entrants et sortants de chaque post.

Responsive

On a fait un premier thème avec TailwindCSS. J'aime beaucoup ce framework, ça permet d'aller vite sans compromettre la qualité. J'aime bien les designs épurés, ça tombe bien. Le framework permet de gérer tout ce qui est responsive assez simplement, on en a bien profité. On passe les feuilles de style par PurgeCss ensuite, qui les allège énormément en retirant les déclarations qu'on n'utilise pas.

Thèmes

Comme sur un Wordpress, il est possible d'utiliser un thème. Les vues fournies par défaut sont suffisantes pour motoriser le site, mais on aimerait pouvoir le customiser au maximum. Il suffit d'ajouter des vues perso dans un répertoire resources/views/themes/mon_theme et elles seront chargées en lieu et place de celles de base.

Affiliation

Sur chaque post, on peut ajouter un ou des produits, tirés d'une base générale (un peu comme le "Media Library" de Wordpress, mais pour les liens d'affil). Pour chaque produit, on stocke les clics sortants, et sur quel post ils ont eu lieu (on peut avoir le même produit sur plusieurs posts). À terme, je pense qu'on ajoutera aussi des produits au hasard pour compléter l'offre, et qu'on laissera le système déterminer lesquels semblent les plus rentables.

Les liens d'affiliation sont ajoutés en Javascript (sans framework, hein), depuis un fichier qui est bloqué dans le robots.txt du site. Aucune URL n'est présente sur les pages de post, ni en clair, ni en chiffré. On passe l'ID du produit dans l'URL du lien. Au clic, on charge l'URL correspondante depuis la base de données et on redirige.

Si un post n'a pas de produits associés, on en tire 3 au hasard. S'il y en a déjà, mais pas assez, on complète avec des produits au hasard.

Baptême du feu

On a pris un blog Wordpress sur lequel est ajouté régulièrement du contenu. Sans rentrer dans les détails, c'est un site de niche, mais avec des expressions assez recherchées, et un bon potentiel d'achats "plaisir-mais-pas-que" en affiliation.

On a environ 150 articles de 300 à 600 mots chacun. Le contenu est vraiment propre, et intéressant. Point pub : c'est réalisé par une des rédactrices de Soumettre.fr, qui a une affinité particulière avec la thématique.

Un mini-serveur de chez Scaleway plus tard, provisionné par Ansible, on a déployé le projet pour la première fois en prod, via Capistrano.

Performances

On a passé le site dans PageSpeed : 100/100 pour desktop et 99/100 pour mobile. On charge une police depuis Google Fonts, ça nous coûte un point... Bref, pas mal du tout en terme de vitesse d'affichage. Sur la Search Console, le nombre de pages crawlées par jour est passé d'une quarantaine à quasiment deux cent. Évidemment, c'est surtout parce que la structure du site a changé en profondeur, mais on dirait aussi que les pages qui chargent en 120ms en moyenne, ça plait bien à GoogleBot.

J'apporte ma pierre à l'édifice
T'en veux encore ?