Skip to content

Artisan quickstart

Attach a ChromeRendererConfig to a NextPDF document, call writeHtmlChrome(), and save the Portable Document Format (PDF) file. Chrome renders the Hypertext Markup Language (HTML). The bridge imports the result as a Form XObject, and the text stays selectable.

writeHtmlChrome() is a method on the NextPDF core Document. The HasTextOutput concern provides it. The method validates the input and resolves the Artisan renderer. It then sends the HTML to Chrome, parses the returned PDF, and embeds page 0 as a Form XObject at the current cursor. The public signature is writeHtmlChrome(string $html, ?float $width = null, ?float $height = null): static — verified against nextpdf/coresrc/Core/Concerns/HasTextOutput.php.

quickstart.php
<?php
declare(strict_types=1);
use NextPDF\Core\Document;
use NextPDF\Artisan\ChromeRendererConfig;
require __DIR__ . '/vendor/autoload.php';
$config = new ChromeRendererConfig(
chromeBinaryPath: '/usr/bin/chromium',
);
$doc = Document::createStandalone();
$doc->setChromeRendererConfig($config);
$doc->addPage();
$doc->writeHtmlChrome('
<div style="display: flex; gap: 20px; font-family: sans-serif;">
<div style="flex: 1; background: #f0f0f0; padding: 24px;">
<h2>Revenue</h2><p style="font-size: 2em; color: #2563eb;">$124,500</p>
</div>
<div style="flex: 1; background: #f0f0f0; padding: 24px;">
<h2>Orders</h2><p style="font-size: 2em; color: #16a34a;">1,847</p>
</div>
</div>
');
$doc->save('/tmp/report.pdf');

This is the canonical flow from the package README.md. Chrome handles the Cascading Style Sheets (CSS) flex layout. The numbers remain selectable text in the output because the page is embedded as a Form XObject, not a raster image.

Pass explicit width and height in PDF points to fit a fixed page (A4 shown):

$doc->writeHtmlChrome($html, width: 595.28, height: 841.89);

When you supply both values, Chrome prints to exactly that paper size. When you omit the height (or pass null), the bridge fits to the measured content height and adds a small reflow safety buffer. See /integrations/artisan/production-usage/ for why that buffer exists and when to override it.

PropertyBehavior
TextSelectable and searchable (vector text, not rasterized)
Cascading Style Sheets (CSS)Chrome layout: flexbox, grid, complex selectors, web fonts through data Uniform Resource Identifier (URI) values
NetworkNo subresource fetches; remote Uniform Resource Locators (URLs) do not load (see /integrations/artisan/security-and-operations/)
PagesPage 0 of the Chrome output is imported
  • Empty HTML is a no-op. writeHtmlChrome('') returns the document unchanged (verified in HasTextOutput::writeHtmlChrome).
  • No page yet. If the document has no page, writeHtmlChrome() adds one before rendering.
  • Remote assets do not load. <img src="https://..."> renders empty. Inline assets as data: URIs. This is the network isolation posture, not a bug. See /integrations/artisan/security-and-operations/.
  • Bridge missing. If nextpdf/artisan is not installed, core raises a layout exception instead of a fatal error.

The first call includes Chrome startup and layout time. Subsequent calls reuse the live Chrome process through BrowserPool. For batch jobs or long-running workers, read the lifecycle and resource guidance on the /integrations/artisan/production-usage/ page.

The quickstart uses trusted, hard-coded HTML. Before you pass any user-influenced HTML to writeHtmlChrome(), read /integrations/artisan/security-and-operations/. The bridge isolates network access, but HTML rendering still has a threat surface.

This produces a PDF from HTML using the open-source bridge. To embed a compliant e-invoice Extensible Markup Language (XML) file into the same document, the Premium Pro tier supplies an embedder. The open-source path is unaffected when Premium is absent.

  • /integrations/artisan/install/
  • /integrations/artisan/configuration/
  • /integrations/artisan/production-usage/
  • /integrations/artisan/troubleshooting/
  • /integrations/artisan/security-and-operations/