Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Sidecar Browsershot Laravel Package

wnx/sidecar-browsershot

Run Browsershot on AWS Lambda via Sidecar for Laravel. Generate PDFs and screenshots without installing Node, Puppeteer, or Google Chrome on your server—headless Chrome runs on Lambda instead. Install via Composer, register the function in sidecar.php, and deploy with sidecar:deploy.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. This package is a thin, well-placed adapter rather than a framework of its own. It swaps Spatie\Browsershot\Browsershot for Wnx\SidecarBrowsershot\BrowsershotLambda, which serialises the Browsershot call and hands it to a Sidecar-registered Lambda function that runs headless Chromium. From a TPM's perspective the strategic value is architectural: it removes Node, Puppeteer, and Chrome — three of the most painful binaries to keep patched and provisioned — from the application servers, and replaces them with a managed AWS dependency. That is a genuine reduction in the operational surface of the app tier. It is not a general-purpose rendering platform; it is the right fit only if you are already on (or willing to adopt) both Spatie Browsershot and Hammerstone Sidecar, and already running on AWS.

Integration feasibility. Low-to-moderate effort, front-loaded into infrastructure rather than code. The application-side change is close to a find-and-replace plus a config registration, and the package explicitly claims parity with existing Browsershot APIs and chains. The real work is AWS account setup (sidecar:configure), IAM execution role, Lambda deployment (sidecar:deploy --activate), an S3 disk for the large-payload paths, and a decision on warming instances. The testing story is a signal here: the package's own suite requires a live AWS account and a deployed function, so "run the tests" is not a locally reproducible safety net. Budget for a dedicated non-production AWS account for integration verification.

Technical risk. Concentrated in four areas. (1) Platform coupling — you inherit AWS Lambda's payload ceilings and synchronously-coupled latency; the package mitigates this with readHtmlFromS3 and saveToS3, but those are opt-in, and teams routinely hit the request-size wall only after shipping. (2) Architecture lock — the changelog shows an explicit x86_64-only constraint, so any Graviton/arm64 cost strategy on Lambda is off the table. (3) Upgrade choreography — the README states the Lambda function must be redeployed whenever spatie/browsershot is upgraded, which converts a routine composer update into a deploy event. (4) Adoption signal — 236 stars and zero dependents on Packagist is thin for something in the critical path of PDF invoice generation. It is a single-maintainer package (Stefan Zweifel, with Aaron Francis credited), MIT-licensed, actively released, but not a vendor with an SLA.

Key questions.

  • Is AWS the destination cloud, and is a Lambda/S3 footprint already accepted by platform and security?
  • What is the actual volume and latency profile of PDF/screenshot generation — synchronous in a request cycle, or queueable?
  • Which documents must be pixel-identical across releases (invoices, statements, contracts), and who owns visual regression testing?
  • Does the security model permit rendering user-supplied or third-party HTML in a Lambda with an S3-write execution role?
  • What is our exit plan if the package stalls — can we fall back to self-hosted Chromium, or to a commercial rendering API?
  • Are we on PHP 8.2+/Laravel 10+ and Browsershot v4 (v2.x line), or pinned to the older v1.x line?

Integration Approach

Stack fit. Clean, provided you are on the modern matrix: PHP 8.2/8.3, Laravel 10/11, spatie/browsershot v4, hammerstone/sidecar, and spatie/image v3+ if any fit()/resize manipulation is required. The dependency chain is shallow and all MIT/actively maintained, so there is no licence or procurement friction. Because BrowsershotLambda mirrors the Browsershot surface, existing view/HTML-building code stays untouched — that is the single biggest integration win and the strongest argument for adoption over a bespoke Lambda renderer.

Migration path. Effectively a strangler-fig swap at the call site. Inventory every place Browsershot is currently invoked, replace the import, and route file output through one of three sinks: local path, saveToS3, or bodyHtml() into a Laravel disk. The package's stated goal is that Puppeteer and Chrome need not be installed for Browsershot, so you can retire the server-side puppeteer npm step in the same change. Treat the v1→v2 boundary as the only real migration: sidecar-browsershot.layer was renamed to sidecar-browsershot.layers, PHP 8.0/8.1 and Laravel 8/9 were dropped, and spatie/image became a separate install for image manipulation. If the app is on the older matrix, plan for a v1 tail rather than attempting both migrations at once.

Compatibility. Two compatibility traps worth calling out in the plan. First, version drift between the PHP-side Browsershot and the Chromium/puppeteer-core baked into the deployed Lambda layers — v2.1.0 moved to puppeteer-core v22/Chromium 121, v2.2.0 to Node 20 — so the deployed function and the Composer lock must be advanced together, not independently. Second, image manipulation behaves differently by sink: with fit() plus saveToS3, the file is downloaded from S3, manipulated on the app server, and re-uploaded, which reintroduces local CPU cost and a round-trip you may have assumed you had eliminated. Decide per use case whether manipulation happens in Lambda or in the app.

Sequencing.

  1. Provision a non-production AWS account, run sidecar:configure, and stand up the function end to end with the package's own setup command.
  2. Register BrowsershotFunction::class in sidecar.php, publish config, deploy and activate.
  3. Pick one low-risk, asynchronous document as a pilot — not invoices.
  4. Establish visual regression baselines before swapping any user-facing output.
  5. Migrate remaining call sites, then remove Node/Puppeteer/Chrome from the build image and confirm cold app-server memory and CPU drop.
  6. Add custom fonts to resources/sidecar-browsershot/fonts and verify emoji rendering via the bundled Noto Color Emoji.
  7. Tune SIDECAR_BROWSERSHOT_WARMING_INSTANCES against measured latency, not guesswork.
  8. Only then retire the old rendering path.

Operational Impact

Maintenance. Modest but non-zero, and it is a different kind of maintenance than the status quo. You trade "patch Chrome and Puppeteer on N app servers" for "keep a Lambda layer, a Composer lock, and an AWS execution role in sync, and redeploy on every Browsershot bump." Most teams will find the second cheaper. The hidden cost is calendar-driven: Node runtime and Chromium layer versions age out, so this package needs a standing quarterly review rather than the annual scramble the current setup probably gets. Pin versions and treat the Lambda deploy as part of the release, not an afterthought.

Support. The primary support risk is bus factor, not code quality. One maintainer, no dependents, no commercial backing, and a test suite that cannot run without live AWS credentials means your team is the de facto second-line support. Mitigate by keeping a documented fallback to self-hosted Browsershot behind a feature flag, and by having at least one engineer who has read the deploy path. The README, changelog, and release history are genuinely good — better than most single-maintainer packages — which materially lowers the knowledge-transfer cost.

Scaling. Lambda absorbs the bursty, CPU-heavy part, which is the whole point: a traffic spike in PDF generation no longer starves the app server. Three constraints to model before committing. Lambda account concurrency limits become your rendering throughput ceiling, and the package consumes that shared pool. Warming instances (SIDECAR_BROWSERSHOT_WARMING_INSTANCES) buy latency at the cost of always-on spend — size it against p95 latency targets and document the trade-off explicitly, because it is the line item finance will ask about. And because renders are synchronous invocations, per-request latency includes a network hop to AWS; anything on a user-facing page load should move behind a queue.

Failure modes. Enumerate these in the runbook. Large HTML sources or large response bodies exceeding Lambda payload limits — the reason readHtmlFromS3 and saveToS3 exist; default to S3 for anything over a few megabytes. Missing S3 write permission on the Sidecar execution role, which fails saveToS3 at runtime rather than deploy time. Lambda timeout on pathological pages or slow third-party assets, which surfaces as a generic invocation error rather than a useful render error. Cold-start latency causing intermittent slow PDFs that look like flakiness. Region misconfiguration — v1.6.1 fixed saveToS3 to use sidecar.aws_region, a reminder that region/env drift is a real class of bug here. And the silent one: a Browsershot upgrade applied via Composer without a Lambda redeploy, producing subtly wrong output rather than an exception. Instrument every render with function duration and outcome, and alert on failure rate and p95 separately.

Ramp-up. Plan roughly a sprint for a mid-level Laravel engineer to go from zero to a verified pilot in a non-production account, assuming someone with AWS/IAM familiarity is available for the first day. The Laravel-side work is a few hours; the AWS work — account, credentials via sidecar:configure, execution role, S3 disk and permissions, deploy and activate — is where the time goes. The genuinely non-obvious part is visual verification: someone must own reference-image comparison (the project itself uses Pixelmatch) for any document where fidelity matters. If your team has never operated Lambda, add a day for cold-start and concurrency tuning. If they have, this is a comfortable, low-drama adoption with a clear, cheap rollback.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log