Skip to content

NextPDF Artisan overview

NextPDF Artisan is the Chrome bridge for NextPDF. It sends a Hypertext Markup Language (HTML) fragment to a headless Chrome process over the Chrome DevTools Protocol (CDP), captures the printToPDF output, and embeds the result in the target Portable Document Format (PDF) document as a Form XObject. The embedded text stays selectable and searchable.

The Artisan package (nextpdf/artisan) extends the open-source NextPDF engine with a renderer that delegates layout to Chrome. NextPDF’s native HTML pipeline already covers a broad Cascading Style Sheets (CSS) subset. Use the Artisan bridge for documents that need Chrome-grade layout, including CSS flexbox and grid, custom web fonts loaded from data Uniform Resource Identifier (URI) sources, and complex selectors, while still producing vector text instead of a rasterized screenshot.

The bridge runs as a pipeline of small, single-purpose components. ChromeHtmlRenderer orchestrates a render. ChromeSecurityPolicy validates the input and wraps it in a locked-down HTML document. BrowserPool owns the Chrome process lifecycle. ViewportCalculator maps PDF points to CSS pixels. The NextPDF\Parser reader parses the Chrome output, and PageImporter converts it to a Form XObject. Every component is final, constructor-injected, and typed at PHPStan level 10.

The bridge is bound by external dependencies. It needs the chrome-php/chrome library (^1.15) and a Chrome or Chromium binary that the PHP process can reach. Neither one is bundled. When the library is absent, the bridge raises ChromeNotAvailableException instead of failing silently; see /integrations/artisan/failure-modes/ on the /integrations/artisan/troubleshooting/ page.

The renderer never sends content to Chrome until the input passes ChromeSecurityPolicy::validate(). The document Chrome receives is always wrapped with a strict Content Security Policy (CSP) through the Content-Security-Policy header and a defense-in-depth CDP network block. Because the bridge processes potentially untrusted HTML, the /integrations/artisan/security-and-operations/ page documents its transport and isolation model instead of summarizing it here.

This page describes the package behavior as shipped, verified against src/Artisan/ and the tests/Unit/Artisan/ suite. It is not a claim of pixel-for-pixel parity with an interactive Chrome browser: animations are captured at their final frame, layout does not rely on JavaScript, and only the first Chrome page is imported.

HTML fragment

ChromeSecurityPolicy::validate()

ChromeSecurityPolicy::wrapHtml()

CSP + reset CSS

BrowserPool

headless Chrome

CDP: Network.setBlockedURLs '*'

Page.setDocumentContent

Chrome printToPDF

NextPDF\\Parser\\PdfReader

PageImporter → Form XObject

Embedded in target PDF

(text selectable)

Diagram
ComponentResponsibilitySource
ChromeHtmlRendererOrchestrates a single render; returns ChromeRenderResultsrc/Artisan/ChromeHtmlRenderer.php
ChromeRendererConfigImmutable configuration value objectsrc/Artisan/ChromeRendererConfig.php
ChromeSecurityPolicyInput validation + secure HTML envelopesrc/Artisan/ChromeSecurityPolicy.php
BrowserPoolChrome process lifecycle and restart policysrc/Artisan/BrowserPool.php
ViewportCalculator72 pt/inch ↔ 96 px/inch conversionsrc/Artisan/ViewportCalculator.php
ChromeRenderResultTyped render output (ChromeRenderResultInterface)src/Artisan/ChromeRenderResult.php
PageImporterParsed Chrome page → ImportedFormXObjectsrc/Artisan/PageImporter.php
EInvoiceServiceFactoryContainer-free factory for Premium e-invoice contractssrc/Artisan/EInvoiceServiceFactory.php
  • Version lineage. The published Composer artifact is tagged v0.1.0. Source docblocks carry @since 1.7.0 (Chrome bridge) and @since 1.1.0 (e-invoice factory), both inherited from the pre-rename nextpdf/core version line; the package was renamed to nextpdf/artisan in the 2.0.0 CHANGELOG entry. Treat the Composer tag as the authoritative install version, and treat the @since markers as engine-version history.
  • First page only. PageImporter::import() defaults to page index 0. Content that overflows to a second Chrome page is clipped unless you supply an explicit height, as covered on the /integrations/artisan/production-usage/ page.
  • No dependency injection (DI) container. Artisan is containerless. EInvoiceServiceFactory gives environments without a service container a consistent way to instantiate services; see /integrations/artisan/boot-and-discovery/.

Each render pays the Chrome page-load and printToPDF cost once per call. BrowserPool keeps the Chrome process alive between renders and restarts it every 100 renders to bound memory growth. Chrome’s layout work, not the bridge itself, dominates Big-O behavior. For the measured budget of this page’s reference flow, see performance_budget in frontmatter and the /integrations/artisan/production-usage/ page.

The bridge renders potentially untrusted HTML inside Chrome. Input is size- and content-validated before Chrome sees it. The wrapped document carries default-src 'none'. A CDP-level block stops every subresource request. The full transport and isolation model, including the explicit limits of the Chrome sandbox flag, is on the /integrations/artisan/security-and-operations/ page. Do not treat this section as the complete security posture.

The open-source bridge renders HTML to PDF. The Premium tiers add compliant e-invoice embedding (Pro) and validation (Enterprise) on top of the rendered document. When those tiers are not installed, EInvoiceServiceFactory returns null, so the open-source path stays fully functional without them.

  • /integrations/artisan/install/
  • /integrations/artisan/configuration/
  • /integrations/artisan/quickstart/
  • /integrations/artisan/chrome-renderer-setup/
  • /integrations/artisan/security-and-operations/
  • /integrations/artisan/production-usage/