Skip to content

Instantly share code, notes, and snippets.

@ollieread
Created March 30, 2026 15:33
Show Gist options
  • Select an option

  • Save ollieread/4ad432e46895174d1596a4c572a4d51f to your computer and use it in GitHub Desktop.

Select an option

Save ollieread/4ad432e46895174d1596a4c572a4d51f to your computer and use it in GitHub Desktop.
<?php
declare(strict_types=1);
namespace App\Services;
use HeadlessChromium\Browser;
use HeadlessChromium\BrowserFactory;
use HeadlessChromium\Clip;
use Illuminate\Contracts\View\Factory as ViewFactory;
use Illuminate\Filesystem\Filesystem;
final class OgImageGenerator
{
private ?Browser $browser = null;
public function __construct(
private readonly ViewFactory $viewFactory,
private readonly Filesystem $filesystem,
)
{
}
/**
* @param string $view
* @param array<string, mixed> $data
* @param string $outputPath
*
* @return void
* @throws \HeadlessChromium\Exception\CommunicationException
* @throws \HeadlessChromium\Exception\CommunicationException\CannotReadResponse
* @throws \HeadlessChromium\Exception\CommunicationException\InvalidResponse
* @throws \HeadlessChromium\Exception\CommunicationException\ResponseHasError
* @throws \HeadlessChromium\Exception\FilesystemException
* @throws \HeadlessChromium\Exception\NavigationExpired
* @throws \HeadlessChromium\Exception\NoResponseAvailable
* @throws \HeadlessChromium\Exception\OperationTimedOut
* @throws \HeadlessChromium\Exception\ScreenshotFailed
*/
public function generate(string $view, array $data, string $outputPath): void
{
$directory = dirname($outputPath);
if (! $this->filesystem->isDirectory($directory)) {
$this->filesystem->makeDirectory($directory, 0755, true);
}
$html = $this->viewFactory->make($view, $data)->render();
$page = $this->browser()->createPage();
try {
$page->setViewport(1200, 630);
$page->navigate('data:text/html,' . rawurlencode($html))->waitForNavigation();
$page->screenshot([
'clip' => new Clip(0, 0, 1200, 630),
])->saveToFile($outputPath);
} finally {
$page->close();
}
}
public function close(): void
{
$this->browser?->close();
$this->browser = null;
}
private function browser(): Browser
{
if ($this->browser === null) {
$chromePath = config()->string('services.browsershot.chrome_path', '');
$browserFactory = new BrowserFactory($chromePath);
$this->browser = $browserFactory->createBrowser([
'noSandbox' => true,
'windowSize' => [1200, 630],
]);
}
return $this->browser;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment