Asset Pipeline
BladePDF resolves images, stylesheets, fonts, JavaScript files, SVG files, and other local references through the framework-agnostic core. Laravel configures safe defaults; cloud templates can use dashboard assets and per-request overrides.
Local HTML assets
When you call fromView(), the package first renders your Laravel view to HTML, scans it for local file references, uploads those files with the render request, and rewrites references to asset:///... URLs.
1<link rel="stylesheet" href="{{ asset('css/invoice.css') }}">
2<img src="{{ asset('images/logo.png') }}" alt="Logo">
The Laravel adapter maps URL paths through public_path(), searches public_path() and storage_path('app'), and recognizes the APP_URL host plus localhost, 127.0.0.1, and ::1. The plain PHP and Node.js SDKs read no local files until you configure roots explicitly.
Allowed roots and security
Every automatically discovered path is resolved to its canonical filesystem location and must remain inside an allowed root. Directory traversal, absolute paths or file:// URLs outside a root, and symlinks that escape a root are rejected. Laravel deliberately does not allow base_path(), preventing document HTML from reading .env and application source by default.
Publish config/bladepdf.php and append narrowly scoped directories to asset_roots when documents need additional files. See the Laravel 2.0 root migration, PHP SDK roots, or Node.js SDK roots.
Scanned references
| Location | Examples |
|---|---|
| HTML attributes | src, href, poster, data-src, data-href |
| Responsive images | srcset |
| Inline styles | style="background:url(...)" |
| Style blocks | <style> with CSS url() and @import |
| CSS files | Nested url() references such as fonts and background images |
| External files | <script src> JavaScript and referenced SVG files |
External URLs
External http:// and https:// URLs are preserved. Availability depends on your plan and network settings. Unsafe destinations and unsupported protocols are blocked.
Protocol-relative CDN URLs, data:, blob:, javascript:, mailto:, tel:, and existing asset:/// references are not rewritten. Query strings and fragments are preserved, including font.woff2?v=1 and sprite.svg#icon.
The referenced files are transferred, but their contents are not traversed. BladePDF does not parse JavaScript imports, dynamic imports, fetch(), runtime URLs, SVG contents, or dependencies inside SVG.
Disable automatic resolution
Automatic asset resolution is enabled by default. If you want BladePDF to leave your HTML and CSS references untouched, disable it globally with an environment variable:
1BLADEPDF_AUTO_RESOLVE_ASSETS=false
Or disable it for one render:
1return BladePDF::fromView('pdf.invoice', ['invoice' => $invoice])
2 ->withoutAssetResolution()
3 ->render()
4 ->response();
Manual assets added with withAsset() or overrideAsset() are still uploaded. Only the automatic scan-and-rewrite step is skipped.
If you prefer a toggle-style call, resolveAssets(false) is equivalent to withoutAssetResolution().
Manual assets
Use withAsset() when your HTML already references an asset:///... URL, when you want full control over the request asset name, or when the caller intentionally approves one file outside the automatic roots.
1$html = '<img src="asset:///brand-logo.png">';
2
3return BladePDF::fromHtml($html)
4 ->withAsset(public_path('images/logo.png'), 'brand-logo.png', 'image/png')
5 ->render()
6 ->response();
Cloud template assets
Cloud templates can reference dashboard assets using the asset:/// scheme. If a request provides an override with the same asset name, the uploaded file is used for that render only.
Node.js files and generated assets
The Node.js SDK uses assetFile() for an intentional filesystem file and assetData() for a Buffer, Uint8Array, or ArrayBuffer. A generated asset requires an explicit target:
1render.assetData(chartBuffer, {
2 target: 'chart.png',
3 mimeType: 'image/png',
4}); 1<img src="asset:///bladepdf-old-logo-colored.png" alt="Logo">
2<link rel="stylesheet" href="asset:///invoice.css">
Per-request overrides
Use overrideAsset() to replace a cloud asset for one render request. This is useful for tenant logos, one-off attachments, and generated images.
1return BladePDF::fromTemplate('invoice.standard', $context)
2 ->overrideAsset('bladepdf-old-logo-colored.png', public_path('tenant-logo.png'))
3 ->render()
4 ->response();
Override targets may contain letters, numbers, dots, underscores, and hyphens. Use names such as logo.png or invoice.css.
Asset metrics
Render details include asset timing and counts:
assets_resolve_msassets_resolved_countassets_cache_hitsassets_uploaded_count
These metrics appear in the dashboard render detail and help explain how assets affected a render.
Troubleshooting
| Problem | Check |
|---|---|
| Image missing from local view render | Confirm the file exists under public_path() or is reachable as a local host asset. |
| Cloud asset missing | Confirm the asset exists in the dashboard and the template references the correct asset:///... key. |
| Override rejected | Use a simple override name like logo.png, not a nested path. |
| External URL blocked | Use stored assets or confirm your plan allows internet access. |