danteb918/livewire-pdf-preview
A Laravel Livewire package for displaying inline PDF previews directly in your components. Add a simple, customizable viewer to dashboards, admin panels, and document lists so users can browse PDFs without leaving the page.
This package integrates Mozilla's pdf.js viewer into a Laravel application, giving you a client-side PDF renderer without relying on the browser's native PDF plugin. It is a viewing/rendering package, not a PDF generation or server-side parsing library.
php artisan vendor:publish --tag=pdf-assets
php artisan vendor:publish --tag=pdf-config
Confirm that pdf.js and pdf.worker.js land in your public assets directory.Content-Type: application/pdf and Content-Disposition: inline, then pass that URL into the package's Blade component/directive. This is the fastest way to validate that assets, worker path, and CSP are all correct.Where to look first:
Content-Security-Policy middleware, since pdf.js needs worker-src and often script-src adjustments.Authenticated/private PDFs. Do not expose storage paths directly. Route through a controller that authorizes the request, then streams or redirects:
Route::get('/documents/{document}/view', function (Document $document) {
Gate::authorize('view', $document);
return response()->file(
Storage::disk('local')->path($document->path),
[
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'inline; filename="'.$document->filename.'"',
]
);
})->name('documents.view');
Then hand route('documents.view', $document) to the viewer. This keeps authorization in Laravel while rendering stays in pdf.js.
Signed/temporary URLs. For large or sensitive files, prefer URL::temporarySignedRoute(...) and validate with the signed middleware. This avoids long-lived public links and works well when the viewer fetches the PDF asynchronously.
Custom worker path for CDN/offline deployments. Use the new 1.0.2 option when assets are not served from the default path, for example a versioned CDN prefix or a Vite-built asset URL:
// config/pdf.php
'worker_path' => env('PDF_WORKER_PATH', '/vendor/pdf/pdf.worker.js'),
Pair this with asset versioning so the worker is cached correctly and never mismatches the main pdf.js build.
Blade component usage. Keep the viewer component in a layout slot and pass only the URL and display options. Avoid embedding raw PDF bytes in HTML; always use a URL so pdf.js can range-request and stream.
Livewire/Inertia integration. The viewer is JavaScript-driven. In Livewire, initialize the viewer after the component is mounted and re-initialize when the PDF URL changes. In Inertia, initialize in onMounted. Do not assume the viewer survives DOM morphing without re-init.
Upload-then-preview workflows. A common day-to-day pattern: upload a PDF, store it, then immediately render the preview route in the viewer. Validate MIME type and size server-side before the preview is generated, and keep the preview route authorized even for the uploader.
Versioned asset publishing. After upgrading the package, re-publish or rebuild assets. The 1.0.2 pdf.js upgrade means the main script and worker are a matched pair; treat them as one deployable unit.
Worker version mismatch. pdf.js and pdf.worker.js must be the same version. If you upgrade the package but serve a stale cached worker, rendering fails with obscure errors. After 1.0.2, clear caches and confirm both files have the new build. If you use the custom worker path, make sure it points at the upgraded worker, not an old copy.
Worker path is easy to misconfigure. A wrong worker_path often produces a blank viewer or a console error about the worker failing to load. Check the network tab first: the worker request should return JavaScript with an HTTP 200, not HTML (a common symptom of a route fallback catching the request).
CSP and cross-origin workers. If you serve the worker from a CDN, add worker-src and possibly script-src entries. Cross-origin workers are restricted; the worker must be served with appropriate CORS headers, or you should keep it same-origin.
MIME type matters. Serve PDFs as application/pdf. A generic application/octet-stream may cause pdf.js to fail or fall back unexpectedly. Also ensure Laravel is not adding X-Content-Type-Options: nosniff in a way that conflicts with a misconfigured MIME type.
Range requests and large files. pdf.js performs range requests. If your controller loads the entire file into memory, large PDFs will be slow and memory-heavy. Prefer response()->file() or a streamed response, and ensure your web server supports Range.
Caching after upgrades. Published assets are static. Browsers may keep the old pdf.js while fetching the new worker, causing a mismatch. Add a version query string or use your asset pipeline's cache busting.
Installation command rename in 1.0.2. If you have deployment scripts, Dockerfiles, or onboarding docs calling the old install command, update them. This is a documentation/automation break, not a runtime break, but CI will fail if it references the old name.
Not a server-side renderer. Do not expect this package to extract text, generate thumbnails, or render PDFs on the server. If you need thumbnails or text extraction, use a server-side library and store the results; use this package only for the interactive viewer.
Extension points. The config file and published views are the intended customization surface. Override the viewer view rather than patching vendor assets, and keep custom JS initialization in your own module so package upgrades do not overwrite it.
Mobile and accessibility. Client-side PDF rendering can be heavy on low-end mobile devices. For large documents, consider lazy-loading the viewer only when it scrolls into view, and provide a direct download link as a fallback.
How can I help you explore Laravel packages today?