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

Gotenberg Bundle Laravel Package

sensiolabs/gotenberg-bundle

Symfony bundle that generates, streams, and saves PDFs and screenshots from URLs, HTML, Markdown, or Office files via the Gotenberg API. Includes a profiler and testing helpers.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

What it is. A Symfony bundle that wraps the Gotenberg 8.x HTTP API: a typed, fluent-builder client for producing PDFs (from URL, HTML/Twig, Markdown, Office documents) and screenshots (URL, HTML, Markdown), plus merge/split/flatten/encrypt/embed/convert operations. It ships DI interfaces (GotenbergPdfInterface, GotenbergScreenshotInterface), a Twig integration with a gotenberg_asset() helper, router awareness for ->route(), a profiler panel, PHPUnit test doubles, and async/webhook support.

Architecture fit.

  • Strong fit: Symfony 6.4/7.x application with Twig already in the stack. The bundle is idiomatic Symfony: scoped HTTP client, autowired interfaces, Flex recipe, config tree.
  • Weak fit: Laravel or framework-agnostic PHP. The bundle depends on Symfony DI, HttpKernel, Twig and its own kernel/config conventions. In a Laravel codebase, treat it as not directly installable and evaluate gotenberg/gotenberg-php (the underlying client this bundle was inspired by) or a small internal HTTP service instead.
  • Real dependency: the package does not convert anything. You must run, secure, and scale a Gotenberg container yourself (Chromium + LibreOffice, heavy image). That service — not this bundle — dominates the operational surface.

Integration feasibility. Low friction where the stack matches: composer require, accept the Flex recipe, and you get a bundle registration, a config skeleton, a gotenberg service in docker-compose, and a GOTENBERG_DSN in .env. Manual setup is ~10 lines of YAML. The API is discoverable (->url()->url(...)->generate()->stream()), and the docs cover configuration, processing/saving, assets, fonts, webhooks, and every builder. That is unusually complete for a 240-star package.

Technical risk.

  • Version coupling to Gotenberg: 1.3.0 tracks Gotenberg 8.28/8.29 form fields (skipNetworkAlmostIdleEvent, bookmark fields, webhook event headers). Bundle upgrades and Gotenberg image upgrades must be treated as one change, not two.
  • Network topology: the classic failure is a blank PDF with no error, because Chromium inside Gotenberg cannot reach your app URL or rejects a self-signed cert. The README's FAQ addresses this (request_context.base_uri, --chromium-ignore-certificate-errors), but it is a recurring onboarding trap.
  • Ecosystem signal: 240 stars, 0 tracked dependents, single-vendor stewardship (SensioLabs). Mitigants are real: MIT license, active release cadence, CI with PHPUnit/PHPStan/php-cs-fixer, Dagger test matrix across PHP/Symfony versions, and per-minor UPGRADE-1.x.md guides.
  • Escape hatch is cheap: the bundle is a thin layer over HTTP. Worst case, replace it with direct HTTP calls in days.

Key questions for the team.

  1. Is the target application Symfony or Laravel — i.e., is this bundle even the right artifact?
  2. Which sources and operations are actually needed (Twig, URL, Office, Markdown; merge/split/encrypt/PDF-A/Factur-X)?
  3. Sync streaming or async with webhooks? What is the p95 latency and peak-concurrency budget?
  4. Where does the Gotenberg container run, and can it reach the app and any external URLs the PDFs reference?
  5. Data classification: do generated documents contain PII/regulated data, and are we comfortable sending that content to a self-hosted container?
  6. Who owns the Gotenberg image lifecycle (CVEs in Chromium/LibreOffice)?
  7. Is air-gapped or on-prem-only operation required?

Bottom line: a well-engineered, low-risk adapter with a high-quality developer experience inside Symfony, and a poor fit outside it. Approve as a productivity layer only if the container is owned as a first-class platform component.

Integration Approach

Stack fit.

  • Symfony: green. Standard install, autowiring, Flex recipe, Twig-native. The profiler panel materially shortens debugging of form-field and rendering issues.
  • Laravel: redirect. Options in order of preference: (a) gotenberg/gotenberg-php as a plain SDK wrapped in a Laravel service provider; (b) a thin internal HTTP client over the Gotenberg REST API (~100–200 LOC) with queued jobs; (c) a small Symfony microservice that owns this bundle and exposes an internal POST /render endpoint. Do not attempt to graft Symfony bundles into Laravel.

Migration path (assuming replacing wkhtmltopdf / Dompdf / mPDF / ad-hoc headless-Chrome scripts):

  1. Inventory every existing PDF/screenshot path and its templating source.
  2. Port templates to Twig satisfying the required structure — full <!DOCTYPE html><html><head><meta charset>…</head><body> wrapper, including for header and footer fragments.
  3. Replace hardcoded asset URLs with gotenberg_asset(), and set assets_directory if assets live outside assets/.
  4. Map each old option set onto the relevant builder; anything unsupported by a builder becomes a feature gap to log.
  5. Run old and new side by side behind a feature flag; diff output on a golden-file corpus (fonts, pagination, headers, page counts, embedded images).

Compatibility.

  • Pin three things together: PHP version, Symfony version, Gotenberg image tag. The bundle's CI matrix covers the PHP/Symfony axes; the Gotenberg axis is yours.
  • Read UPGRADE-1.x.md before each minor bump; the project publishes these per release.
  • Treat Gotenberg upgrades as deliberate, tested changes — new form fields land in the bundle within a release or two, but behavior changes in Chromium/LibreOffice can alter rendering.

Sequencing.

  1. Spike (1–2 days): run gotenberg/gotenberg:8 locally; hit URL→PDF and Twig→PDF, stream to the browser.
  2. Infra: scoped HTTP client in framework.http_client.scoped_clients, DSN in env, request_context.base_uri for local dev (host.docker.internal).
  3. Parity: port the real templates, header/footer, fonts, and images; validate against golden files.
  4. Async: move long-running and Office conversions to webhook-driven flows with durable artifact storage.
  5. Test harness: PHPUnit mock results and builder assertions so CI does not require a live container.
  6. Load and failure testing, then a canary rollout with the old path kept warm.

Operational Impact

Maintenance. The code you own is small; the surface you operate is not. Two independent upgrade axes — the Composer package (frequent, well-documented minors) and the Gotenberg container (Chromium/LibreOffice CVEs, image churn). Nominate a single owner for both, plus a quarterly image-refresh cadence.

Support. MIT, community-driven via GitHub issues, backed by SensioLabs so a support arrangement is a realistic commercial option rather than a hope. Bus factor is concentrated in a handful of named maintainers; the thin-HTTP escape hatch keeps that risk bounded.

Scaling.

  • Gotenberg is CPU- and memory-bound; scale horizontally with N replicas behind a load balancer and round-robin from the scoped client.
  • Offload to a queue plus webhooks for Office documents, merges, and batch jobs; keep the interactive path for small Twig→PDF renders.
  • Cache deterministic renders (same template + same data = same PDF) and store artifacts in object storage instead of regenerating.
  • Set explicit HTTP timeouts, concurrency caps, and container memory limits — the defaults will not save you under load.
  • Budget storage and egress for artifacts; PDFs of Office documents can be large.

Failure modes to design for.

  • Gotenberg unreachable, 5xx, or timeout — needs retry with backoff, circuit breaking, and a user-visible degradation path.
  • Blank or partial PDFs with HTTP 200: Chromium could not load the target URL (SSL trust, private DNS, host.docker.internal, firewall). This is the single most common support ticket; put it in the runbook.
  • OOM or LibreOffice conversion failure on large/malformed Office uploads — enforce upload size and extension allowlists before the request leaves the app.
  • Font substitution and layout drift after container upgrades — golden-file regression tests catch this.
  • Chromium sandbox and container hardening posture; avoid --no-sandbox in production if at all possible.
  • Webhook delivery failures and duplicate callbacks — webhook consumers must be idempotent and reconcile against stored job state.
  • Queue backlog under peak load; unbounded concurrency will degrade the whole Gotenberg pool.
  • Template/runtime errors surfacing as opaque 500s from Gotenberg — wrap and map errors at the client boundary.

Ramp-up.

  • Symfony developer: ~half a day to first streamed Twig→PDF; ~1 week to production-grade (container, networking, async, tests, observability).
  • Laravel developer using the raw Gotenberg client: +2–3 days, mostly learning Gotenberg's form-field semantics and per-source option sets.
  • Ops/DevOps: meaningful effort — container image lifecycle, resource limits, autoscaling policy, secrets/DSN management. Do not treat this as a "just a composer package" change.

Recommendation: proceed as a contained pilot inside one Symfony service with a clear owner for the Gotenberg runtime; gate broader adoption on the golden-file parity results and a load test at expected peak concurrency.

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.
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log
hsluv/hsluv
seampact/codegen
seampact/hooks
seampact/ir
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table