I was working on a client project where we needed to process uploaded PDFs before sending them to an AI model. The documents were multi-page city directory scans, and the AI worked best when fed individual pages rather than entire documents. Simple enough, I just needed to split PDFs.
So I started looking for a Laravel package. I found a few options, but nothing that felt right.
The Problem with PDF in the Laravel Ecosystem
The Laravel ecosystem offers excellent packages for generating PDFs, such as Spatie's laravel-pdf. However, when it comes to manipulating existing PDFs (e.g. splitting, merging, extracting pages or adding watermarks), the story is different.
Some of this can be done with existing tools. For example, FPDI can combine pages, and you can wrap CLI tools like qpdf or Ghostscript to split documents. But that leaves you writing all the integration code yourself. There's no filesystem disk support, no service container integration, and no fluent API.
I wanted something with a facade, chainable methods, and proper Storage integration. Something that feels like writing Eloquent queries, not fighting a CLI tool.
Meet Collate
under the hood. Here's what my original problem looks like with it:
use Johind\Collate\Facades\Collate;
$pages = Collate::open($request->file('directory-scan'))
->split('ai-processing/scan-page-{page}.pdf');
// $pages → Collection ['ai-processing/scan-page-1.pdf', ...]
// Now feed each page to your AI pipeline
That's it. The uploaded file is handled, pages are split, temp files are cleaned up automatically, and you get a collection of paths back.
But once I had the foundation in place, I kept going. I felt like this was missing in the ecosystem, and honestly it was just fun to build, so it grew into a full toolkit.
What Else Can You Do?
Merge multiple documents:
Collate::merge('cover.pdf', 'report.pdf', 'appendix.pdf')
->save('complete-report.pdf');
Watermark a document with an overlay:
Collate::open('proposal.pdf')
->overlay('branding/confidential-stamp.pdf')
->save('stamped-proposal.pdf');
Chain a whole workflow together. Add standard terms, set metadata, encrypt, and push to S3 in one go:
Collate::open($request->file('document'))
->addPages('legal/standard-terms.pdf')
->withMetadata(title: 'Client Report 2025')
->encrypt('client-password')
->toDisk('s3')
->save('reports/final.pdf');
Extract or remove specific pages:
Collate::open('document.pdf')
->onlyPages([1, 2, 3])
->save('first-three-pages.pdf');
Collate::open('document.pdf')
->removePages('5-10')
->save('trimmed.pdf');
Rotate pages, flatten forms, optimize for web:
Collate::open('scanned.pdf')
->rotate(90, range: '1-3')
->flatten()
->linearize()
->save('cleaned-up.pdf');
Read metadata and page counts without modifying anything:
$meta = Collate::inspect('document.pdf')->metadata();
$meta->title; // 'Quarterly Report'
$meta->author; // 'Taylor Otwell'
$count = Collate::inspect('document.pdf')->pageCount();
Everything chains.
Built for Laravel
A few things that make it feel native:
Storage disk integration. Read from S3, write to local, or the other way around. Collate handles the temp file dance for remote disks transparently:
Collate::fromDisk('s3')
->open('uploads/contract.pdf')
->toDisk('local')
->save('processed/contract.pdf');
It's Responsable. Return a PendingCollate directly from a controller and Laravel streams it to the browser. There's also download() and stream() if you need more control:
public function show()
{
return Collate::open('invoice.pdf');
}
Conditional operations via Laravel's Conditionable trait:
Collate::open('document.pdf')
->when($request->boolean('watermark'), fn ($pdf) => $pdf->overlay('watermark.pdf'))
->when($request->boolean('flatten'), fn ($pdf) => $pdf->flatten())
->save('output.pdf');
Macros for your own reusable operations:
PendingCollate::macro('stamp', function () {
return $this->overlay('assets/stamp.pdf');
});
Collate::open('contract.pdf')->stamp()->save('stamped.pdf');
Requirements
Collate requires PHP 8.4+, Laravel 11 or 12, and .
→
I'm actively working on the package, so feedback and issues are very welcome.
SOCIAL SHARE CARD GENERATOR