Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Pdfjs Viewer Bundle Laravel Package

steamulo/pdfjs-viewer-bundle

A PHP bundle that integrates the Mozilla PDF.js viewer into your application, letting you render PDF files directly in the browser without plugins, with configurable viewer options and straightforward template integration.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and register

composer require steamulo/pdfjs-viewer-bundle

There is almost certainly no Symfony Flex recipe (0 stars, single-maintainer legacy bundle), so register it manually in config/bundles.php:

return [
    // ...
    Steamulo\PdfjsViewerBundle\SteamuloPdfjsViewerBundle::class => ['all' => true],
];

Look here first

  1. vendor/steamulo/pdfjs-viewer-bundle/README.md — the only real documentation.
  2. vendor/steamulo/pdfjs-viewer-bundle/DependencyInjection/Configuration.php — this is the authoritative list of configurable parameters (the README is likely stale). Every option you can set under steamulo_pdfjs_viewer: is defined here.
  3. vendor/steamulo/pdfjs-viewer-bundle/Resources/views/ — the Twig templates you'll likely need to override.
  4. vendor/steamulo/pdfjs-viewer-bundle/Resources/public/ (if present) — the bundled pdf.js build and whether it uses a CDN.

First use case

The canonical scenario is serving private PDFs behind authentication. You do not expose the file directly; you stream it through a controller (or a signed URL), then hand the URL to the bundle's viewer so pdf.js renders it in the browser:

// config/packages/steamulo_pdfjs_viewer.yaml
steamulo_pdfjs_viewer:
    # fill in from Configuration.php — typical keys are things like
    # pdf_url, viewer_path, cdn, default_scale, etc.

Then in a controller:

#[Route('/document/{id}/view', name: 'document_view')]
public function view(Document $document): Response
{
    return $this->render('document/view.html.twig', [
        'pdf_url' => $this->generateUrl('document_pdf', ['id' => $document->getId()]),
    ]);
}

And in the template, invoke whatever Twig helper the bundle exposes (check the README — it's usually a function like pdfjs_viewer(...) or an {% include %} of a bundle template). Start with the simplest inline embed, confirm the PDF loads, then start tuning parameters.

Implementation Patterns

Stream, don't link. The strongest reason to use a server-side bundle wrapping pdf.js is that the actual .pdf route can enforce IsGranted, tenant scoping, or watermarks, while the viewer just gets an opaque URL. Pattern: GET /doc/{id}/pdf returns a BinaryFileResponse (or a streamed response for range support), GET /doc/{id}/view renders the viewer passing that URL.

Range requests matter. pdf.js progressively fetches byte ranges. BinaryFileResponse handles Range reasonably on modern Symfony, but if you serve from S3/object storage, prefer a signed URL that supports Range rather than proxying the whole file through PHP.

Config layering. Set sensible defaults in the bundle config and override per-render where the bundle supports passing options into the Twig helper. Keep things like default_scale, page, and theme out of controllers and into config where possible; only the per-document pdf_url should be dynamic.

Template override pattern. Copy the bundle's viewer template into templates/bundles/SteamuloPdfjsViewerBundle/... and extend rather than fork. This is the standard Symfony bundle override mechanism and the cleanest extension point you have — the bundle is small and you'll almost certainly need to tweak the markup (add a download button, styling, a container class for your CSS framework).

Wrap it in a Stimulus/JS component. Don't let pdf.js options leak into every template. Create one Twig component (or one {% include %} partial) that takes pdf_url and a small options array, so the rest of your app never touches the bundle directly. That gives you a single seam to swap the bundle out later (see Gotchas).

Asset handling. If the bundle ships pdf.js in Resources/public/, you'll need bin/console assets:install --symlink (Symfony 4) or a mapping if you've moved to AssetMapper/WebpackEncore. Confirm where the pdf.worker.js file actually ends up and that the worker path is set correctly for your deployment (see Gotchas).

Gotchas and Tips

Symfony 4 only — verify before adopting. The description and 2023-01-31 release date suggest it was never updated for Symfony 5/6/7. On a modern app, expect the service definitions to fail (e.g. removed kernel.root_dir, autowiring changes) or the bundle to be outright incompatible. Check composer.json require constraints before installing; if it caps at ^4.0, treat this as a "read the code and copy the ~100 useful lines" package rather than a dependency.

Worker script is the #1 breakage. pdf.js fails silently (blank canvas, console error Setting up fake worker failed) when the worker file isn't served at the expected path. After assets:install, open the browser devtools Network tab and confirm both pdf.js and pdf.worker.js load with 200s. If you're behind a CDN or versioned asset path, the bundle's hard-coded worker URL will be wrong — override the template to fix it.

X-Frame-Options / CSP will bite you. If your app sets X-Frame-Options: DENY globally (common via nelmio/security-bundle), an embedded viewer iframe will be blank. Either render the viewer inline (not in a cross-origin iframe) or relax CSP frame-src/script-src/worker-src specifically for the viewer route. worker-src blob: is frequently needed too.

No Flex recipe → no magic config reference. bin/console config:dump-reference steamulo_pdfjs_viewer works once the bundle is registered; use it to discover parameters instead of trusting the README. If the bundle doesn't register a config tree (unlikely but possible), read Configuration.php directly.

Last release 2023, 0 stars, 0 dependents. This is effectively unmaintained. Budget for the possibility that you're the only person who will ever fix a bug in it. The pragmatic mitigation: encapsulate usage behind one Twig partial / one small Stimulus controller, so if you later replace it with a maintained alternative (e.g. symfony/ux-style custom integration or embedding pdf.js directly), the blast radius is one file.

Debugging order for a blank viewer: (1) does the raw pdf_url return the PDF with correct Content-Type: application/pdf? (2) does the worker load? (3) are the pdf.js and worker versions identical (mismatched versions fail loudly)? (4) any CSP violation in the console? (5) is the container element given a non-zero height? — number (5) is the classic "everything loaded but nothing shows" cause.

Extension points, in order of preference: (a) bundle config parameters; (b) Twig template override under templates/bundles/...; (c) subclass the bundle's viewer service and alias it in services.yaml; (d) fork — only do this if you've accepted you're maintaining it.

Lock the pdf.js version. If the bundle points at a CDN (cdnjs/unpkg) with a floating version, a future upstream release can break your viewer with no deploy on your side. Pin it in the bundle config, or copy the build into public/ and point at that.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels