rekalogika/gotenberg-pdf-bundle
A Symfony bundle that integrates Gotenberg, the Docker-powered PDF generation service, into your PHP app. Generate PDFs from HTML, URLs, or Markdown through a simple service or Twig, with configurable hosts, timeouts, and assets. Simplifies PDF creation without managing headless browsers yourself.
What the package actually is. Despite appearing in a PHP package index, rekalogika/gotenberg-pdf-bundle is a Symfony bundle, not a Laravel package. It is a thin integration layer that registers a Gotenberg HTTP client, exposes it through Symfony's DI container, and wires configuration (Gotenberg base URI, timeouts, defaults) into Symfony's config tree. It sits on top of a framework-agnostic core library (rekalogika/gotenberg-pdf), which is the part with real reuse value. Gotenberg itself is an external service — a Docker image exposing a Chromium/LibreOffice-backed HTTP API that converts HTML, URLs, Markdown, and Office documents into PDFs.
Architecture fit — poor for Laravel, adequate for Symfony. The bundle's value proposition is container integration: autowiring, service aliases, config schema, environment-specific defaults. Laravel has no bundle registration mechanism, no Bundle class, no autowired service graph in the Symfony sense. In a Laravel application you would install the package, then bypass essentially everything it advertises, leaving you with a client object wrapped in a composer dependency you could have consumed directly — or reimplemented in ~200 lines. If your stack already contains Symfony services (a hybrid estate, a Symfony admin API alongside a Laravel app), the calculus flips entirely and this is a clean, idiomatic fit.
Integration feasibility. Technically possible in Laravel, but only by ignoring the bundle layer. Practical path: install rekalogika/gotenberg-pdf (the library), bind it in a Laravel service provider, define a PdfRenderer contract, and hide it behind an adapter. Feasibility is therefore moderate for the underlying library and low for the bundle itself. Note that the bundle carries Symfony-version constraints and a PHP floor that may lag or lead your Laravel version's transitive symfony/http-client — a routine but real source of composer resolution friction.
Technical risk — high, concentrated in dependency, not in code quality.
Gotenberg-Trace and output-filename). A thin wrapper is exactly the layer that breaks on a Gotenberg upgrade.file:// reads, remote asset fetching, font/asset exfiltration. This risk is inherent to the approach, not the wrapper, but it must be designed for.composer require.Key questions to answer before proceeding.
Stack fit — mismatch by design. Treat this as a Symfony-ecosystem component. In a Laravel application the realistic integration is not the bundle but the layer underneath it:
PdfRenderer::render(DocumentTemplate): PdfBinary). Every subsequent decision — Gotenberg, Browsershot, a SaaS PDF API, a fake in tests — becomes an implementation detail. This is the single decision that de-risks the whole evaluation./forms/chromium/convert/html, honoring Gotenberg-Trace for correlation). Whether that adapter leans on rekalogika/gotenberg-pdf or 150 lines of Illuminate\Support\Facades\Http is an implementation preference; the latter removes the maintenance dependency at modest cost.config/pdf.php (base URI, timeout, retry, queue, disk).Where the bundle is the right answer. If the PDF work lives in a Symfony service, install it normally: enable the bundle, configure the Gotenberg base URI via environment, inject the renderer service, and let the bundle own the client lifecycle. Do not build an abstraction there for its own sake.
Migration path. (1) Containerize Gotenberg alongside the app in local/CI compose with a healthcheck; (2) implement the adapter and a FakePdfRenderer for tests; (3) run a thin-slice proof of concept on the two or three most complex real documents (long tables, non-Latin script, embedded images, headers/footers with page numbers); (4) only then decide dependency vs in-house client; (5) roll out behind the interface so a swap is a one-file change.
Compatibility. Verify PHP floor against your runtime, Symfony component constraints against the symfony/http-client already resolved by your Laravel version, and — critically — pin the Gotenberg image tag to a specific major and record its API contract in an ADR. Do not use :latest; the wrapper and the server must be upgraded as a pair.
Sequencing. Infrastructure → contract/adapter → template and asset pipeline → storage and delivery (signed URLs, retention) → observability → load test → async queue if p95 latency exceeds the request budget. Resist introducing the queue first; measure, then queue.
Maintenance. For a Laravel team, adopting this package means owning a dependency you cannot meaningfully contribute to (READ-ONLY mirror repo; PRs go elsewhere) and whose update cadence is driven by a single maintainer's spare time. Realistic posture: pin an exact version, vendor or fork if you depend on it in production, and budget a recurring line item for "verify compatible after each Symfony/Gotenberg major." An in-house client of comparable size is often the lower-TCO choice precisely because it has no upstream to track.
Support. No commercial backing, no SLA, small issue backlog. Internal escalation resolves to "read the source" — viable here because the source is small. Plan for one engineer to become the named owner and to have read the Gotenberg API docs directly; that knowledge, not the package, is the actual asset.
Scaling. Scaling pressure is on Gotenberg, not PHP. Chromium conversions are CPU- and memory-bound; concurrency must be capped and the container given explicit memory limits, or a single pathological document OOMs the worker. Horizontal scale means multiple Gotenberg instances behind a load balancer (or Gotenberg's own multi-instance mode) with the app treating it as a pool. Synchronous rendering inside an HTTP request will not survive document spikes or large files — the queue is where this belongs in any serious deployment, with a worker pool sized separately from web traffic. PDF binaries should go straight to object storage, not through the request/response cycle for large payloads.
Failure modes to design for.
Ramp-up. Low-to-moderate for a PHP engineer: the concepts (render HTML → POST multipart → receive bytes) are simple and the library surface is small. The real onboarding cost is operational — container limits, queue behavior, template/asset hygiene, and the security posture of running a browser as a service. Estimate a few days for a working slice and two to three weeks to make it production-grade with queueing, observability, golden-file tests, and pinned version policy.
Recommendation. Conditional no-go for a Laravel-only stack — the bundle's integration layer is inert there, and the adoption signal is too weak to justify the dependency. Go where a Symfony service is in play and the bundle's DI wiring is actually exercised. In both cases, adopt Gotenberg deliberately as a platform component behind an application-owned interface, pin the image, and assume you will own the client code.
How can I help you explore Laravel packages today?