Laravel Packages (Spatie) I Discovered While Redoing ilogus.fr

Discover the Spatie packages that saved me a lot of time during the ilogus.fr redesign: Markdown, OG Image, and Sitemap.

Introduction and Context

Following the redesign of my website ilogus.fr, I discovered several packages that are definitely worth sharing.

For context, the site is built on Laravel (version 13 on PHP 8.4) with a fairly simple Blade page system. I won't go into detail about Laravel here, but if you're not yet familiar with the framework, the official documentation is excellent: https://laravel.com

During this redesign, I had to implement several classic but essential features:

  • Markdown rendering for the blog,
  • Open Graph image generation,
  • Sitemap management.

Rather than building everything myself, I turned to Spatie packages.

Spatie is a Belgian web agency specializing in Laravel, known for the quality of their open-source packages. They maintain dozens of them (permissions, backups, media, etc.), many of which have become standards in the ecosystem.

Laravel Markdown

For the blog, I made the simple choice to store article content in Markdown in my Article model.

The next step was to transform this Markdown into HTML.

First Approach: Str::markdown

Initially, I simply used:

Str::markdown($content);

This works well, without additional dependencies, since Laravel already relies on the league/commonmark package.

But quickly, a limitation appeared: I wanted to display code with proper syntax highlighting.

Switching to spatie/laravel-markdown

While looking for a solution for code rendering, I came across https://spatie.be/docs/laravel-markdown/v1/introduction

This package greatly simplifies integration via a Blade component:

<x-markdown>{!! $content !!}</x-markdown>

Two major advantages:

  • syntax highlighting is integrated,
  • rendering is automatically cached.

Result: less logic in the controller and better performance.

Customization with AttributesExtension

I also wanted to keep control over the HTML rendering, especially for styling images.

I added the AttributesExtension extension from CommonMark:

// config/markdown.php
'extensions' => [
    \League\CommonMark\Extension\Attributes\AttributesExtension::class,
],

This allows writing directly in Markdown:

![My image](/images/photo.jpg){.shadow-lg .rounded-lg}

And getting:

<img src="/images/photo.jpg" class="shadow-lg rounded-lg" alt="My image">

It's a small trick, but it avoids tinkering with HTML or transformations on the Blade side.

Laravel OG Image

When sharing an article, the Open Graph image makes all the difference. It's often the first thing visible on Twitter, LinkedIn, or Slack.

Creating these images manually is quickly tedious, so I used https://spatie.be/docs/laravel-og-image

The principle: define a Blade template, and generate the image automatically.

Example:

<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>

Then in the page:

<x-og-image view="og-images.article" :data="[
    'title' => $article->title,
    'category' => $article->category,
    'author' => $article->author->name
]" />

The package generates the image, adds meta tags (og:image, etc.), and caches everything.

Chrome-Free Thanks to Cloudflare

One point I found particularly interesting: no need for headless Chrome.

You can use the Cloudflare driver:

// AppServiceProvider.php
use Spatie\OgImage\Facades\OgImage;

public function boot(): void
{
    OgImage::useCloudflare(
        apiToken: env('CLOUDFLARE_API_TOKEN'),
        accountId: env('CLOUDFLARE_ACCOUNT_ID'),
    );
}

Result: no heavy dependency on the server side, and external generation via API.

Laravel Sitemap

For SEO, it's impossible to skip a proper sitemap.

With https://spatie.be/docs/laravel-sitemap, generation is very simple.

Automatic Generation

use Spatie\Sitemap\SitemapGenerator;

SitemapGenerator::create('https://ilogus.fr')
    ->writeToFile(public_path('sitemap.xml'));

Manual Generation (More Control)

In my case (blog), I prefer to control the 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'));

Then, a scheduled task is enough to keep the file up to date.

Multi-language and hreflang

The site being multilingual, I separated the sitemaps (sitemap-fr.xml, sitemap-en.xml, etc.).

The package also handles hreflang tags:

Url::create('/blog/my-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');

The tags are automatically generated in the sitemap, following SEO recommendations.

Conclusion

These packages saved me a lot of time on the redesign of ilogus.fr.

They are well thought out, well documented, and integrate perfectly into a Laravel project without friction.

I also use whitecube/laravel-cookie-consent for cookie consent management. I wrote a full article on this: Manage Cookie Consent Without a Paid CMP.

If you work with Laravel, I really recommend checking out their packages: https://github.com/spatie https://spatie.be