Let's create social share images using Laravel. The images shown, when a public link is shared on Facebook, LinkedIn and X. In this post I'm going to share how I implemented this feature in my project Wire in the Wild, an open and free collection of Laravel Livewire projects.
Summary
In this tutorial we will be using the spatie/browsershot
package to create and store a share image for each project. We will create route and a template and an artisan command that takes a screenshot every time a new project gets published.
What is a Social Share Image?
Social share images may display on social networks or in text messaging applications when you share a URL from your site.
Here is an example of a share image we are about to create in this tutorial:
Creating the route for our template
Depending on your setup, it will be different for you, but here is the simple route I'm using in Wire in the Wild. This code is added to my routes/web.php
file:
Route::get('project/{project}/share-image',
function (Project $project) {
return view('share-image', [
'project' => $project,
]);
})->name('project.share-image');
As you can see, we are feeding the Project
into the view share-image.blade.php
which we will be creating next.
The view for our share images
I'm using Tailwind CSS for the styling and decided to simply create the entire page without extending any existing layout in my application. Here is the markup for the screenshot above:
This is it from a template perspective. As our target size for the screenshot will be 1200 x 630 pixels, I tested and tweaked it quite a bit using the responsive view in the developer tools of the browser to get it just right.
Installing the Browsershot package
Let's hop into the terminal and install the necessary dependencies in your Laravel project:
composer require spatie/browsershot
Now we need to install puppeteer which is used by the package under the hood. Check out the guide from Spatie on how to install it in your environment. For our local machine, we do the following:
npm install puppeteer
Ok, now that we are set, let's actually take a screenshot using a custom artisan command.
Taking the screenshot and storing the image
In your terminal scaffold a new artisan command, I used the following:
php artisan make:command GenerateOpenGraphImage
Now open the newly created file and change the code to this:
The command structure
We allow an optional {project?}
to be added and as I'm using the slug
as the model key, calling the command for a single project looks something like this:
php artisan open-graph-image:generate mailcoach
In case there is no project, all the images will be regenerated one by one.
Taking and storing the image
It all comes down to the browsershot part in the generateOpenGraphImage
method, so let's have a look:
Browsershot::url(route('project.share-image', $project))
->windowSize(1200, 630)
->deviceScaleFactor(2)
->save(Storage::disk('public')->path("share/{$project->slug}.png"));
- We let browsershot know the route it has to navigate to. It's the route we defined earlier.
- Next we set the browser window size to 1200 x 630 pixels for the shot.
- To improve image quality, we set the device scale factor to 2, which will take the screenshot at a higher resolution.
- At the end we store the image to our public disk using the slug.
Wrapping up
Creating the social share image
In my case, whenever a project is published, I call the artisan command from my code using a listener:
You can call this from wherever it suits you in your project.
Using the social share image
Now you can add the social share image to your page, for example using the archtechx/laravel-seo
package or similar. So sharing a link to a project can look like this:
And the markup of the generated page will look something like this:
That's it! You now have beautiful share images for your routes. Let me know if this was useful to you.