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

Weasyprint Bundle Laravel Package

pontedilana/weasyprint-bundle

Symfony bundle that integrates WeasyPrint to turn HTML and CSS into high-quality PDFs. Render Twig templates through a simple service, with configurable binary path and clean Symfony integration for invoices, reports, and printable documents.

View on GitHub
Deep Wiki
Context7

Product Decisions This Supports

  • Feature scoping for document output. Any roadmap item that ends in "…as a PDF" (invoices, quotes, statements, payslips, compliance reports, shipping labels, certificates) needs a rendering strategy. This package represents one concrete, low-dependency option: render the document as Twig/HTML, hand it to WeasyPrint, get a paginated PDF back.
  • Build vs. buy on the rendering engine. The real decision is not "this bundle or not" — it is "WeasyPrint, wkhtmltopdf, headless Chrome, or a hosted API (DocRaptor, PDFShift, Puppeteer-as-a-service)". WeasyPrint's differentiator is first-class CSS Paged Media: @page, running headers/footers, page counters, widow/orphan control, footnotes, and PDF bookmarks. That is genuinely hard to replicate with Chrome or a naive DOM→PDF library, and it is exactly what finance/legal-facing documents require.
  • Buy the engine, build (or borrow) the glue. The package itself is a thin Symfony integration: it wires Twig rendering and the Python process invocation together. That means the product decision is about adopting WeasyPrint as an engine; the bundle is an implementation detail worth roughly a day or two of engineering. Adopt the engine on its merits; treat the bundle as reference code.
  • Framework fit is a hard constraint, and this one fails it. Despite the brief describing a Laravel/PHP package, this is a Symfony bundle — a Bundle class, DI extension, Symfony config tree, and Symfony's Process component. It cannot be composer required into a Laravel app and used as-is. The 3.1.0 release reinforces this: it raises the minimum versions of symfony/http-foundation, symfony/http-kernel, and symfony/process, i.e. it is versioned against Symfony's support matrix, not Laravel's. For a Laravel codebase the honest decision path is: adopt WeasyPrint (or not) on engine merits, then write a ~150-line Laravel service provider / facade that does what this bundle does. The bundle remains useful as a validated design reference and a source of edge cases (font loading, base URL handling, temp-file cleanup, timeout/exit-code handling, URL-scheme allowlisting).
  • Roadmap sequencing for "templating-first" documents. Choosing HTML/CSS as the document source language means the same Twig/Blade templates that drive web views and previews can drive the PDF. That unlocks customer-facing template editors, per-tenant branding, and "preview in browser, download as PDF" parity — features that are expensive or impossible with coordinate-based PDF libraries (TCPDF/FPDF) or report DSLs.
  • Security posture of the template pipeline (now an explicit design question). If customers or tenants can author templates — the feature the previous point unlocks — then any option that accepts a URL (background images, stylesheets, @import, remote fonts) becomes an outbound-request primitive: SSRF against internal services, file:// reads, metadata endpoints. 3.1.0 adds a pdf.allowed_schemes config for precisely this, gated on php-weasyprint 2.6+. Treat scheme allowlisting (plus a network egress policy on the render worker) as a launch prerequisite for any self-service templating, not a follow-up.
  • Infrastructure and deployment decisions. WeasyPrint is a Python library with system-level dependencies (Pango, Cairo, GDK-Pixbuf, fontconfig, plus whatever fonts your brand needs). It implies either a Python sidecar service, a worker container, or python3 -m weasyprint invoked from a queue job. That is a real architectural decision — CPU-bound rendering belongs in a queue, never in a request cycle — and it should be made once, deliberately, rather than discovered during a traffic spike. Two operational details from this release feed straight into that decision: bare pdf.binary names are now resolved against PATH, so image builds must guarantee weasyprint is on PATH or set an absolute path; and the timeout can now be disabled entirely via process_timeout: false — a capability to keep out of any request-path configuration.
  • Pricing and tiering inputs. Rendering is CPU- and memory-hungry. Knowing the per-document cost (roughly hundreds of milliseconds for a few pages, seconds for image-heavy or long documents) feeds batch-size limits, async UX copy ("your statement is being prepared"), and whether PDF export is a free feature or a paid one.
  • Risk register entries. 40 stars and 0 dependents means effectively zero community validation and a single maintainer. MIT license is fine. 3.1.0 is a mildly encouraging signal — a security-motivated release that raises vulnerable-dependency floors is what a responsibly maintained package does — but it is a signal of active maintenance, not of stability or of a security-response track record. Any decision here should assume you may inherit the glue code. Budget for reading the source and pinning versions.

When to Consider This Package

Consider it (as a reference implementation, or directly if you are on Symfony) when:

  • Your documents are paginated, print-layout-sensitive: contracts, invoices with repeating table headers, regulatory filings, multi-page statements with "Page X of Y". This is WeasyPrint's sweet spot and where Chrome-based tools frustrate teams.
  • Your team already writes HTML/CSS/Blade or Twig and you want designers, not backend engineers, to own document layout.
  • You want no external SaaS dependency for documents that contain PII or financial data — self-hosted, deterministic, no data leaving your network. This is often the deciding factor over DocRaptor/PDFShift.
  • You need PDF/A or PDF/UA-style accessibility output and tagged PDFs — WeasyPrint has explicit support here; most JS-based alternatives do not.
  • Your volume is moderate and batchy: hundreds to low thousands per day, generated in queue workers, where a few hundred milliseconds of extra render time is irrelevant.
  • You are on Symfony 6/7 and want the DI wiring, config, and Twig integration handed to you rather than assembled. (3.1.0's raised minimum versions confirm current Symfony only; check the constraints against your LTS position before upgrading.)
  • You are rendering partly untrusted or user-authored HTML and want the scheme-allowlist behaviour already wired rather than reinvented — 3.1.0 exposes pdf.allowed_schemes for this, but verify the underlying php-weasyprint version is 2.6+ or the setting silently does nothing.

Look elsewhere when:

  • You are on Laravel. This bundle is not installable. Either port the ~150-line glue or use a Laravel-native wrapper. Do not let "it's a PHP package" obscure that Symfony's container and Process conventions are load-bearing here.
  • You need pixel-perfect fidelity to an existing web view. WeasyPrint implements a print-oriented subset of CSS; it will not match Chrome's rendering of flexbox/grid-heavy, JS-driven layouts. If "the PDF must look exactly like the web page", use headless Chrome (Browsershot/Puppeteer).
  • Your documents require JavaScript to build charts or hydrate data. WeasyPrint does not execute JS. You must pre-render charts server-side (a chart-to-SVG step) — an extra subsystem to own.
  • You cannot run Python. Managed PHP-only hosting, restrictive container policies, or a platform team that will not approve a second runtime. This is the most common blocker and it is organizational, not technical.
  • You need very high throughput (tens of thousands per hour) or interactive latency. Rendering belongs in a queue regardless, but at that scale a dedicated rendering service or a commercial API is the better buy.
  • You want a maintained, supported dependency with a security contact. Zero dependents and 40 stars means you are the first serious adopter. The 3.1.0 security bumps are a good sign, but they are upstream hygiene, not a support commitment.
  • Simple, low-fidelity output suffices — a receipt, a plain table dump. Dompdf is one composer require away, pure PHP, no second runtime, and is the pragmatic choice when layout ambition is low.

How to Pitch It (Stakeholders)

For executives — one paragraph: We need to generate PDFs for [invoices/statements/reports] as we scale [initiative]. There are two credible paths: rent a document API, or own the rendering in-house. Owning it costs roughly one to two engineer-weeks of setup plus modest ongoing infrastructure — a small service in our deployment — and removes per-document fees, vendor lock-in, and the compliance question of shipping customer financial data to a third party. At our projected volume the in-house path pays back within [one to two quarters], and it gives us unlimited iteration on layout, which is the part customers actually notice. The specific open-source package in front of us is a small, single-maintainer Symfony component (40 stars, no downstream users, MIT-licensed, actively released; the current 3.1.0 is a security-and-configuration release that raises its dependency floors and adds URL-scheme allowlisting). We should not take a dependency on it as a library. We should adopt the engine it wraps — WeasyPrint, a mature and widely used HTML-to-PDF renderer — and write our own thin integration, borrowing this package's design as a reference. That gets us the capability with none of the supply-chain risk, and at a cost of roughly two days of engineering over doing nothing.

For engineering — the technical framing:

  • The decision is WeasyPrint (engine) vs. headless Chrome vs. hosted API, not "this bundle vs. that bundle". The bundle is ~150 lines of Twig + Process glue; we can own that. 3.1.0 adds no new capability we couldn't port in an hour — it is a hardening release, not a feature release.
  • WeasyPrint's reason to exist is CSS Paged Media — @page margins and named pages, running headers/footers, counter(page)/counter(pages), break-inside: avoid, footnotes, and real PDF bookmarks. That is what makes multi-page invoices and statements look professional without hand-computing layout.
  • Costs we are accepting: a second runtime (Python + Pango/Cairo/fontconfig, ~300–500MB in the image), no JS execution (charts must be server-rendered to SVG), print-subset CSS (no full flexbox/grid parity with Chrome), and CPU-bound rendering that must run in a queue worker, not a web request.
  • In Laravel: implement a PdfRenderer contract backed by a queued job that writes the rendered HTML to a temp path and shells out to weasyprint with an explicit timeout, then cleans up. Add font assets to the image, pin the Python and WeasyPrint versions (and the php-weasyprint equivalent if we vendor the reference code), and add a golden-file snapshot test per document template so layout regressions are caught in CI rather than by a customer.
  • Apply three lessons from 3.1.0 in our own implementation: (1) allowlist URL schemes explicitly — default-deny to https (plus data: if needed), and pair it with egress restrictions on the worker, because template-driven PDF rendering is a classic SSRF path; (2) resolve the binary from a known absolute path rather than relying on PATH in a minimal container; (3) never disable the process timeout — keep a hard deadline per render and fail the job cleanly, since an unbounded WeasyPrint process on a stuck document is a worker-pool outage.
  • Recommended sequencing: spike one real document end-to-end (one day), decide on engine (day two), then ship behind a feature flag with a fallback path so a renderer outage degrades to "we'll email it to you" rather than a 500.
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.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle