The Artisan package has two linked responsibilities: rendering Hypertext Markup Language (HTML) through Chrome and importing the resulting Portable Document Format (PDF) page into a NextPDF document. When you debug issues, keep the Chrome, parser, and importer boundaries separate.
Use this guide when you write renderer integrations, long-lived workers, parser diagnostics, or tests for nextpdf/artisan.
Layer Owned by Responsibility Do not put here Application Application Authorize HTML generation and choose renderer configuration. Browser process management. HTML policy Application and package Reject unsafe or oversized HTML before rendering. Tenant authorization or business decisions. Chrome renderer nextpdf/artisanRender HTML into a standalone PDF produced by Chrome. General PDF repair or arbitrary PDF editing. Parser/importer nextpdf/artisanParse the rendered PDF and import one page as a form XObject. Full PDF conformance validation. Core engine nextpdf/nextpdfPlace imported form objects and write the final document. Chrome DevTools Protocol (CDP) lifecycle.
Stage Behavior Developer action Config creation ChromeRendererConfig defines the binary, timeout, Cascading Style Sheets (CSS), input-size, and sandbox behavior.Use environment-specific configuration instead of hard-coded runtime guesses. Renderer creation ChromeHtmlRenderer owns a BrowserPool.Reuse the renderer inside a worker, then close it during shutdown. HTML validation Security policy checks size and wraps the document in default CSS. Validate caller authorization before this stage. Chrome print CDP renders a standalone PDF. Keep external resources blocked unless a reviewed policy allows them. PDF parse PdfReader::parse() reads xref data, pages, objects, resources, and revisions.Treat parser failures as render failures unless diagnostics are the goal. Page import PageImporter::import() extracts page content, media box, resources, and embedded objects.Import page 0 unless the workflow deliberately chooses another page.
Path Purpose app/Pdf/Renderers/*Application wrapper around ChromeHtmlRenderer. app/Pdf/Templates/*HTML template rendering and data transfer object (DTO)-to-view mapping. app/Pdf/Policies/*HTML size, resource, and tenant rendering policy. tests/Pdf/Renderer/*Renderer smoke tests with small HTML fixtures. tests/Pdf/Parser/*Parser fixtures for imported Chrome output.
Keep template rendering separate from browser rendering. Pass the renderer final HTML and a known page width.
use NextPDF\Artisan\ ChromeHtmlRenderer ;
use NextPDF\Artisan\ ChromeRendererConfig ;
use NextPDF\Artisan\ PageImporter ;
use NextPDF\Parser\ PdfReader ;
$renderer = new ChromeHtmlRenderer ( new ChromeRendererConfig (
$result = $renderer -> render ( $html , widthPt: 595.28 );
$reader = new PdfReader ($ result -> getPdfData ());
$form = ( new PageImporter ()) -> import ( $reader );
Create one renderer per worker process or per request scope. Reuse it to avoid repeated Chrome startup cost. Close it explicitly to prevent process leaks during worker shutdown.
final class InvoiceChromeRenderer
public function __construct (
private readonly ChromeHtmlRenderer $renderer ,
public function renderInvoice ( string $html ) : string
-> render ( $html , widthPt: 595.28 )
public function close () : void
$this-> renderer -> close ();
Use the parser application programming interfaces (APIs) when Chrome output fails to import. Keep diagnostics read-only, and avoid mutating parser state after a successful import.
Diagnostic question API to use Expected signal Does the file parse? PdfReader::parse()Throws for invalid PDF structure. Does page 0 exist? PdfReader::getPage(0)Returns a PdfObject. Is there content? PdfReader::getPageContentStream($page)Non-empty content stream. Are resources present? PdfReader::getPageResources($page)Resource dictionary array. Are there incremental revisions? PdfReader::getRevisionCount()Count greater than one. Which object failed? PdfTokenizer::getOffset() and parser exception context.Byte offset for fixture reduction.
Extension point Use it for Constraint ChromeRendererConfig::fromArray()Framework configuration mapping. Unknown or mistyped optional values fall back to defaults. HtmlSecurityPolicyInterfaceParse-layer HTML policy. Does not replace transport, process, or authorization controls. LoggerInterfaceRender and browser diagnostics. Do not log HTML content by default. BrowserPoolLong-lived Chrome process reuse. Must be closed on worker shutdown. PageImporterEmbedding a parsed external page. Reader must be parsed first. Parser classes Diagnostics and imported Chrome output. Not a general PDF repair toolkit.
Reproduce the HTML fragment in a minimal render test.
Validate maxHtmlSize, default CSS, and Chrome binary path.
Render with a fixed width in points.
Parse the returned PDF bytes with PdfReader::parse().
Import page 0 unless the workflow deliberately chooses another page.
Add fixture tests for the smallest HTML that reproduces each failure.
Close the renderer in worker shutdown hooks.
Failure Where it should be handled Recommended response Chrome binary missing Deployment check and renderer construction path. Fail readiness before accepting render traffic. Oversize HTML HTML policy. Reject before starting Chrome. Browser timeout Renderer boundary. Fail the render, and record template name, size, width, and timeout. Parser failure Import boundary. Store a small sanitized fixture for debugging when policy allows it. Browser process leak Worker lifecycle. Close on shutdown and restart after controlled render counts.
Concern Default When to override Render timeout 30 seconds.Increase for measured, bounded documents only. Max HTML size 5,000,000 bytes.Lower for public endpoints. Sandbox Enabled. Disable only when container constraints require it, and the host is isolated. Height Auto when heightPt <= 0. Use fixed height for strict layout contracts. External resources Blocked by renderer policy. Allow only through a reviewed resource policy.
Render tests cover representative HTML and CSS.
Security tests cover oversize HTML and blocked resource attempts.
Import tests assert the returned form object has content, media box, and resources.
Parser tests cover cross-reference (xref) table, xref stream, object stream, and malformed fixture cases.
Worker tests call close() and verify no browser process remains.
Performance tests record render time by template and content size.