Introduction et contexte
Suite à la refonte de mon site ilogus.fr, j'ai découvert plusieurs packages qui méritent clairement d'être partagés.
Pour poser le contexte, le site repose sur Laravel (version 13 sous PHP 8.4) avec un système de pages Blade assez simple. Je ne vais pas détailler Laravel ici, mais si vous ne connaissez pas encore le framework, la documentation officielle est très bien faite : https://laravel.com
Lors de cette refonte, j'ai dû mettre en place plusieurs briques classiques mais essentielles :
- un rendu Markdown pour le blog,
- la génération d'images Open Graph,
- la gestion du sitemap.
Plutôt que de tout faire moi-même, je me suis tourné vers les packages de Spatie.
Spatie est une agence web belge spécialisée dans Laravel, connue pour la qualité de ses packages open source. Ils en maintiennent des dizaines (permissions, backups, media, etc.), souvent devenus des standards dans l'écosystème.
Laravel Markdown
Pour le blog, j'ai fait le choix simple de stocker le contenu des articles en Markdown dans mon modèle Article.
Il fallait ensuite transformer ce Markdown en HTML.
Première approche : Str::markdown
Au départ, j'utilisais simplement :
Str::markdown($content);
Ça fonctionne bien, sans dépendance supplémentaire, puisque Laravel s'appuie déjà sur le package league/commonmark.
Mais rapidement, une limite est apparue : je voulais afficher du code avec une vraie coloration syntaxique.
Passage à spatie/laravel-markdown
C'est en cherchant une solution pour le rendu du code que je suis tombé sur https://spatie.be/docs/laravel-markdown/v1/introduction
Ce package simplifie beaucoup l'intégration via un composant Blade :
<x-markdown>{!! $content !!}</x-markdown>
Deux gros avantages :
- la coloration syntaxique est intégrée,
- le rendu est automatiquement mis en cache.
Résultat : moins de logique côté contrôleur et de meilleures performances.
Personnalisation avec AttributesExtension
J'ai aussi voulu garder du contrôle sur le rendu HTML, notamment pour styliser les images.
J'ai ajouté l'extension AttributesExtension de CommonMark :
// config/markdown.php
'extensions' => [
\League\CommonMark\Extension\Attributes\AttributesExtension::class,
],
Ce qui permet d'écrire directement en Markdown :
{.shadow-lg .rounded-lg}
Et d'obtenir :
<img src="/images/photo.jpg" class="shadow-lg rounded-lg" alt="Mon image">
C'est une petite astuce, mais elle évite de bricoler du HTML ou des transformations côté Blade.
Laravel OG Image
Quand on partage un article, l'image Open Graph fait toute la différence. C'est souvent la première chose visible sur Twitter, LinkedIn ou Slack.
Créer ces images à la main est vite pénible, donc j'ai utilisé https://spatie.be/docs/laravel-og-image
Le principe : définir un template Blade, et générer l'image automatiquement.
Exemple :
<div class="w-full h-full bg-gradient-to-br from-slate-900 to-slate-700 text-white flex items-center justify-center p-16">
<div class="space-y-4">
<span class="bg-blue-500 text-sm font-semibold px-3 py-1 rounded-full">
{{ $category }}
</span>
<h1 class="text-5xl font-bold leading-tight">
{{ str($title)->limit(80) }}
</h1>
<p class="text-xl opacity-70">
{{ $author }}
</p>
</div>
</div>
Puis dans la page :
<x-og-image view="og-images.article" :data="[
'title' => $article->title,
'category' => $article->category,
'author' => $article->author->name
]" />
Le package génère l'image, ajoute les meta tags (og:image, etc.) et met le tout en cache.
Sans Chrome grâce à Cloudflare
Un point que j'ai trouvé particulièrement intéressant : pas besoin de Chrome headless.
On peut utiliser le driver Cloudflare :
// AppServiceProvider.php
use Spatie\OgImage\Facades\OgImage;
public function boot(): void
{
OgImage::useCloudflare(
apiToken: env('CLOUDFLARE_API_TOKEN'),
accountId: env('CLOUDFLARE_ACCOUNT_ID'),
);
}
Résultat : pas de dépendance lourde côté serveur, et une génération externalisée via API.
Laravel Sitemap
Pour le SEO, impossible de faire l'impasse sur un sitemap propre.
Avec https://spatie.be/docs/laravel-sitemap la génération est très simple.
Génération automatique
use Spatie\Sitemap\SitemapGenerator;
SitemapGenerator::create('https://ilogus.fr')
->writeToFile(public_path('sitemap.xml'));
Génération manuelle (plus de contrôle)
Dans mon cas (blog), je préfère contrôler les URLs :
use Spatie\Sitemap\Sitemap;
use Spatie\Sitemap\Tags\Url;
Sitemap::create()
->add(Url::create('/')
->setPriority(1.0)
->setChangeFrequency(Url::CHANGE_FREQUENCY_DAILY))
->add(Url::create('/blog')
->setPriority(0.9)
->setChangeFrequency(Url::CHANGE_FREQUENCY_WEEKLY))
->add(Article::all()->map(fn ($article) => Url::create("/blog/{$article->slug}")
->setLastModificationDate($article->updated_at)
->setChangeFrequency(Url::CHANGE_FREQUENCY_MONTHLY)))
->writeToFile(public_path('sitemap.xml'));
Ensuite, une tâche planifiée suffit pour garder le fichier à jour.
Multi-langues et hreflang
Le site étant multilingue, j'ai séparé les sitemaps (sitemap-fr.xml, sitemap-en.xml, etc.).
Le package gère aussi les balises hreflang :
Url::create('/blog/mon-article')
->addAlternate('fr', 'https://ilogus.fr/blog/mon-article')
->addAlternate('en', 'https://ilogus.fr/en/blog/my-article')
->addAlternate('hu', 'https://ilogus.fr/hu/blog/my-article-hu');
Les balises sont générées automatiquement dans le sitemap, conformément aux recommandations SEO.
Conclusion
Ces packages m'ont fait gagner beaucoup de temps sur la refonte de ilogus.fr.
Ils sont bien pensés, bien documentés, et s'intègrent parfaitement dans un projet Laravel sans friction.
J'utilise aussi whitecube/laravel-cookie-consent pour la gestion du consentement cookies. J'ai écrit un article complet à ce sujet : Gérer le consentement sans CMP payant.
Si vous travaillez avec Laravel, je recommande vraiment de jeter un œil à leurs packages : https://github.com/spatie https://spatie.be