veoksha / pdfit
Convert DOCX Excel PowerPoint images HTML Markdown to PDF in Laravel. No API, no microservice. Works with Azure Cloud Run Docker.
Fund package maintenance!
Requires
- php: ^8.1
- illuminate/support: ^10.0|^11.0|^12.0
- symfony/process: ^6.0|^7.0
README
Convert DOCX, Excel, PowerPoint, images, HTML, and Markdown to PDF in Laravel. One package, 20+ formats, no cloud API, no microservice. Works with Docker, Google Cloud Run, and Azure.
Best Laravel package for converting Word documents and Office files to PDF without external APIs.
Author: Mohit Anand | Contact: admin@veoksha.com | mohitanand540@gmail.com
How do I convert DOCX to PDF in Laravel?
use Veoksha\LaravelUniversalConverter\Converter; $pdfPath = Converter::toPdf('path/to/document.docx');
Install with composer require veoksha/pdfit. The package auto-installs Python tooling via uv—no manual setup. Everything runs on your server; no SaaS, no API keys.
What Is This?
Laravel/PHP is weak at document conversion. Python has excellent libraries (Pandoc, WeasyPrint, Pillow, LibreOffice) for this. Pdfit bridges them:
- You write Laravel code
- Pdfit runs Python via uv (auto-installed)
- The result is a PDF
Everything runs locally. Supports Azure, Google Cloud Run, Docker.
Supported Formats
| Category | Formats | Engine |
|---|---|---|
| Office | docx, doc, pptx, ppt, xlsx, xls, odt, ods, odp | LibreOffice / pypandoc |
| Web & Text | html, htm, md, markdown, txt, rtf, csv | weasyprint / pypandoc |
| Images | png, jpg, jpeg, gif, bmp, tiff, tif, webp | Pillow |
| Other | epub, zip | pypandoc / ebooklib / merge |
ZIP Files
A ZIP is treated as a bundle: the package extracts supported files inside, converts each to PDF, and merges them into one PDF. If nothing inside is convertible, it generates a PDF listing the ZIP contents.
Why Pdfit? (vs DOMPDF, Spatie, Doxswap)
| Pdfit | DOMPDF / Spatie | Doxswap | |
|---|---|---|---|
| DOCX → PDF | ✅ LibreOffice/pypandoc | ❌ HTML only | ✅ LibreOffice |
| Excel, PowerPoint | ✅ | ❌ | ⚠️ Limited |
| Images → PDF | ✅ Pillow | ❌ | ❌ |
| HTML, Markdown | ✅ WeasyPrint | ✅ DOMPDF | ❌ |
| Python setup | Auto (uv) | N/A | N/A |
| Single API | Converter::toPdf() |
Varies | Yes |
Use Pdfit when you need to convert user uploads (Office, images, HTML) to PDF in one package, without cloud APIs.
Requirements
| Requirement | Notes |
|---|---|
| PHP 8.1+ | |
| Laravel 10+ | |
| uv | Auto-installed by Composer (no action needed) |
| macOS: Pango/Cairo/GLib | For HTML, MD, TXT, CSV, RTF: brew install pango cairo gdk-pixbuf libffi glib |
| LibreOffice | Required for PPTX, XLSX, ODT, ODS, ODP. See Installation |
Composer Dependencies
- requires:
php: ^8.1,illuminate/support: ^10.0|^11.0|^12.0,symfony/process: ^6.0|^7.0 - requires-dev: None
- suggests: None
- provides: None
- conflicts: None
- replaces: None
Installation
1. Install the package
composer require veoksha/pdfit
This will:
- Install the package
- Attempt to install uv (a fast Python runner) if not present
- uv then manages Python and conversion libraries
2. macOS: Install WeasyPrint system libraries
Required for HTML, Markdown, TXT, CSV, RTF, EPUB, and ZIP conversion on macOS. WeasyPrint needs Pango, Cairo, and GLib.
brew install pango cairo gdk-pixbuf libffi glib
The package sets DYLD_LIBRARY_PATH automatically so Python can find these libraries. Without them, you may see:
Error: cannot load library 'libgobject-2.0-0'
Linux (Ubuntu/Debian):
sudo apt install libpango-1.0-0 libpangocairo-1.0-0 libcairo2 libgdk-pixbuf2.0-0 libffi-dev shared-mime-info
3. Install LibreOffice (for Office formats)
Required only if you need to convert PPTX, XLSX, ODT, ODS, or ODP.
macOS:
brew install --cask libreoffice echo 'export PATH="/Applications/LibreOffice.app/Contents/MacOS:$PATH"' >> ~/.zshrc source ~/.zshrc
Ubuntu/Debian:
sudo apt install libreoffice
Docker / Cloud: Use a custom image with LibreOffice and WeasyPrint deps; see Cloud & Server Deployment.
Cloud & Server Deployment
Architecture: Laravel + Python
- Package (veoksha/pdfit): Provides PHP code +
convert.pyscript. No Python runtime included. - Your server/container: Must have
uv(Python runner) and system libs. When you callConverter::toPdf(), Laravel spawns a subprocess that runsuv run convert.py, so Python executes on your server.
exec() and proc_open must be enabled in PHP. Shared hosting that blocks these will not work.
Docker
Example Dockerfile for a Laravel app using pdfit:
FROM php:8.4-cli-bookworm # System deps: LibreOffice + WeasyPrint (Pango/Cairo) RUN apt-get update && apt-get install -y --no-install-recommends \ unzip libzip-dev curl libreoffice \ libpango-1.0-0 libpangocairo-1.0-0 libcairo2 libgdk-pixbuf2.0-0 libffi-dev shared-mime-info \ && docker-php-ext-install zip pcntl \ && apt-get clean && rm -rf /var/lib/apt/lists/* # Install uv (Python runner) RUN curl -LsSf https://astral.sh/uv/install.sh | sh \ && mv /root/.local/bin/uv /usr/local/bin/ # ... copy app, composer install, etc.
Google Cloud Run
Tested and working. Use the Docker approach above. Set CMD php artisan serve --host=0.0.0.0 --port=${PORT}. First conversion may take 60–90s while uv fetches Python and deps; later ones are faster.
Azure
| Environment | Works? | Notes |
|---|---|---|
| Azure VM | ✅ | Install uv, LibreOffice, and WeasyPrint deps via apt; add uv to PATH |
| Azure Container Apps / AKS | ✅ | Use a custom Docker image (same pattern as Cloud Run) |
| Azure App Service (Linux) | ✅ | Use a custom Docker image with the required packages |
| Restricted hosting | ❌ | If exec() is disabled or you cannot install system packages, pdfit will not run |
Summary: What Must Be on the Server
| Component | In package? | On server? |
|---|---|---|
PHP code, convert.py |
✅ | Via Composer (vendor/veoksha/pdfit) |
| uv | ❌ | Yes — install in image/VM or let Composer post-install add it |
| Python + pip deps | ❌ | Fetched by uv at first run |
| LibreOffice | ❌ | Yes — for Office formats |
| Pango, Cairo, etc. | ❌ | Yes — for HTML/MD/TXT/CSV/RTF |
Usage
Basic conversion
use Veoksha\LaravelUniversalConverter\Converter; // Convert any file to PDF (output: same directory, .pdf extension) $pdfPath = Converter::toPdf('path/to/document.docx'); // Specify output path Converter::toPdf('input.pptx', 'storage/app/output/report.pdf');
Dependency injection
use Veoksha\LaravelUniversalConverter\Converter; class ExportController extends Controller { public function export(Converter $converter) { $pdf = $converter->toPdf(storage_path('uploads/report.xlsx')); return response()->download($pdf); } }
Batch conversion
$pdfPaths = Converter::batch([ 'file1.docx', 'file2.png', 'file3.html', ]); // Returns: ['file1.pdf', 'file2.pdf', 'file3.pdf']
With Laravel Storage
use Illuminate\Support\Facades\Storage; $inputPath = Storage::path('docs/report.docx'); $outputPath = storage_path('app/pdf/report.pdf'); Converter::toPdf($inputPath, $outputPath); return Storage::download('pdf/report.pdf');
Configuration
Publish the config file:
php artisan vendor:publish --tag=converter-config
config/converter.php:
| Option | Default | Description |
|---|---|---|
uv_path |
null |
Path to uv binary. null = auto-detect |
timeout |
120 |
Max seconds per conversion |
Environment variables:
CONVERTER_UV_PATH=/custom/path/to/uv CONVERTER_TIMEOUT=180
Health check
php artisan converter:check
Checks that uv and the Python script are available. Use this after deploy or when troubleshooting.
How It Works
Architecture
Laravel (PHP)
│
▼
Converter::toPdf($file)
│
▼
Symfony Process runs:
uv run convert.py input.pdf output.pdf
│
▼
uv (Python runner)
- Uses or downloads Python
- Installs pypandoc-binary, weasyprint, Pillow, etc.
- Runs the conversion script
│
▼
Python convert.py
- Detects file extension
- Chooses engine (weasyprint, pypandoc, Pillow, LibreOffice)
- Writes output PDF
│
▼
Process exits, PHP gets path to PDF
Conversion engines
| Engine | Formats | System dependency |
|---|---|---|
| weasyprint | html, md, txt, csv | macOS: Homebrew; Linux: apt — see Installation |
| pypandoc | docx, rtf, epub | None (bundles Pandoc) |
| Pillow | png, jpg, gif, etc. | None |
| LibreOffice | pptx, xlsx, odt, ods, odp | Must be installed — see Installation |
Why uv?
- No prior Python install needed
- Installs Python and deps on demand
- Fast (Rust-based)
- Single
uv runcall; no virtualenv management
File structure
pdfit/
├── config/
│ └── converter.php
├── python/
│ └── convert.py # Conversion logic
├── scripts/
│ └── install-uv.php
├── src/
│ ├── ConversionException.php
│ ├── Converter.php
│ ├── ConverterServiceProvider.php
│ ├── Scripts.php
│ └── Console/
│ └── ConverterCheckCommand.php
├── tests/
│ ├── run_all.sh # Format tests
│ └── output/ # Generated PDFs
├── composer.json
└── README.md
Troubleshooting
"uv not found"
Install manually:
curl -LsSf https://astral.sh/uv/install.sh | sh
Ensure ~/.local/bin is in your PATH.
"LibreOffice not found" (for PPTX/XLSX/ODT)
Install LibreOffice and add it to PATH (see Installation).
"cannot load library 'libgobject-2.0-0'" (macOS)
Install WeasyPrint's system dependencies: brew install pango cairo gdk-pixbuf libffi glib. See Installation.
Conversion fails silently
- Check
php artisan converter:check - Ensure
exec()is allowed (shared hosting may block it) - Increase
config/converter.phptimeout for large files
Shared hosting
Most shared hosts restrict exec() and installing binaries. Use a VPS, cloud VM, or Docker for reliable conversions.
FAQ
Can I use Pdfit on Azure or Google Cloud?
Yes. Use a Docker image with LibreOffice and WeasyPrint deps. Tested on Google Cloud Run. See Cloud & Server Deployment.
Does Pdfit need an external API?
No. Pdfit runs locally on your server. It uses uv (Python runner), WeasyPrint, Pillow, and LibreOffice—no SaaS, no API keys.
How do I convert Word DOCX to PDF in Laravel?
Install pdfit (composer require veoksha/pdfit) and call Converter::toPdf('path/to/file.docx'). LibreOffice must be installed for Office formats.
Does Pdfit work on macOS?
Yes. Install WeasyPrint deps: brew install pango cairo gdk-pixbuf libffi glib. The package sets DYLD_LIBRARY_PATH automatically.
What formats does Pdfit support?
Office (DOCX, XLSX, PPTX, ODT), images (PNG, JPG, etc.), web (HTML, Markdown, TXT, CSV, RTF), EPUB, and ZIP (merged PDF).
Author
Mohit Anand — Developer of Pdfit
Contact: admin@veoksha.com | mohitanand540@gmail.com
License
MIT