# laravel-sign-pad turns an Eloquent model into something you can sign

> laravel-sign-pad is a Laravel package that adds a signature pad canvas to a model, stores the drawn signature, and can generate a PDF with the signature placed at coordinates you define, optionally certified with TCPDF. It supports PHP 8.2 to 8.5 and Laravel 11 to 13.

**creagia/laravel-sign-pad** — A Laravel package to sign documents and optionally generate certified PDFs associated with Eloquent models.

- Repository: https://github.com/creagia/laravel-sign-pad
- Stars: 550 · Forks: 53
- Language: PHP
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/creagia-laravel-sign-pad

## A signature belongs to a model, not to a form

laravel-sign-pad is described as a Laravel package to sign documents and optionally generate certified PDFs associated with Eloquent models.

The framing is what makes the package interesting. The signature is not a controller action that posts an image to a form handler. It is a trait and an interface applied to a model, so the signature becomes part of that model's data. Retrieving it is a relation, the README calls it the Eloquent relation $myModel->signature, and the path helpers hang off that relation.

The mechanics are a canvas in your Blade template, a route on the model, and a stored image.

The install is a Composer requirement.

```bash
composer require creagia/laravel-sign-pad
```

Then the package publishes its config and migrations and migrates the database in one command.

```bash
php artisan sign-pad:install
```

And the JavaScript assets are published separately, into the public directory.

```bash
php artisan vendor:publish --tag=sign-pad-assets
```

That last step copies the package assets inside the public/vendor/sign-pad/ folder, which is the path the template later references. The separation between the install command and the asset publishing is a small thing, but it is the kind of detail that costs an afternoon if you skip it, because the form renders and then does nothing.

The requirements are explicit: PHP 8.2 to 8.5 and Laravel 11 to 13. The primary language of the repository is PHP, and the licence recorded for the project is MIT.

## Two contracts and one trait, and a template for the document

Preparing a model takes a trait and an interface. The README says to add the RequiresSignature trait and implement the CanBeSigned class on the model you would like.

```php
<?php

namespace App\Models;

use Creagia\LaravelSignPad\Concerns\RequiresSignature;
use Creagia\LaravelSignPad\Contracts\CanBeSigned;

class MyModel extends Model implements CanBeSigned
{
    use RequiresSignature;

}

?>
```

If you also want PDFs with the signature in them, there is a second contract, ShouldGenerateSignatureDocument, and you implement it by defining the document template through a getSignatureDocumentTemplate method.

```php
<?php

namespace App\Models;

use Creagia\LaravelSignPad\Concerns\RequiresSignature;
use Creagia\LaravelSignPad\Contracts\CanBeSigned;
use Creagia\LaravelSignPad\Contracts\ShouldGenerateSignatureDocument;
use Creagia\LaravelSignPad\Templates\BladeDocumentTemplate;
use Creagia\LaravelSignPad\Templates\PdfDocumentTemplate;
use Creagia\LaravelSignPad\SignatureDocumentTemplate;
use Creagia\LaravelSignPad\SignaturePosition;

class MyModel extends Model implements CanBeSigned, ShouldGenerateSignatureDocument
{
    use RequiresSignature;
```

The template object is where the interesting part lives. It takes an outputPdfPrefix, optionally a template, which is either a BladeDocumentTemplate with a path to a Blade template or a PdfDocumentTemplate with a path to a PDF template, and a list of signaturePositions.

Each SignaturePosition carries a page number and x and y coordinates, and the example places signatures on page 1 at 20 and 25 and on page 2 at 25 and 50. So the signature is not stamped at a fixed point, it is placed at coordinates you choose per page, and multiple positions are supported because a document may need a signature in more than one place.

The README also notes that a $model object is automatically injected into the Blade template, so the template can read the model's properties directly.

## The form, the component and the canvas asset

The usage section says that all you need is to create the form with the sign pad canvas in your template, and to call the getSignatureRoute() method from the instance of the model you prepared.

```html
@if (!$myModel->hasBeenSigned())
    <form action="{{ $myModel->getSignatureRoute() }}" method="POST">
        @csrf
        <div style="text-align: center">
            <x-creagia-signature-pad />
        </div>
    </form>
    <script src="{{ asset('vendor/sign-pad/sign-pad.min.js') }}"></script>
@endif
```

Three details in that snippet carry the design. The form posts to a route derived from the model, so there is no controller to write. The canvas is a Blade component, x-creagia-signature-pad, rather than raw markup. And the whole block is wrapped in a hasBeenSigned check, so the form disappears once the model is signed.

The script tag points at the published asset path, vendor/sign-pad/sign-pad.min.js, which is exactly where the earlier publish command put the files.

The component is configurable from the same template. The README lists the properties: border-color, a hex value for the canvas border; pad-classes and button-classes, strings indicating which classes apply to the sign area or to the submit and clear buttons; clear-name and submit-name, which modify the default Submit and Clear button labels; and disabled-without-signature, a boolean that disables the submit button when the user has not signed yet.

```html
  <x-creagia-signature-pad
      border-color="#eaeaea"
      pad-classes="rounded-xl border-2"
      button-classes="bg-gray-100 px-4 py-2 rounded-xl mt-4"
      clear-name="Clear"
      submit-name="Submit"
      :disabled-without-signature="true"
  />
```

The example uses Tailwind classes, which tells you the component emits plain markup and leaves styling to you.

## Retrieving, deleting, and where the configuration lives

Once signed, the signature is reached through the Eloquent relation $myModel->signature, and four helper methods are available on it.

```php
echo $myModel->signature->getSignatureImagePath();
echo $myModel->signature->getSignedDocumentPath();
```

getSignatureImagePath and getSignatureImageAbsolutePath give the stored signature image, and getSignedDocumentPath and getSignedDocumentAbsolutePath give the generated PDF. The distinction between relative and absolute is a small one that matters when you are writing to a disk with a non-public root, which is why the config file lets you set the disk.

Deletion is on the model rather than the relation.

```php
echo $myModel->deleteSignature();
```

The config file, config/sign-pad.php, is where the operational choices live. The README says you can configure many important aspects of the package there, such as the route name where users are redirected after signing the document, and where you want to store the signed documents. You can customise the disk and the route used to store signatures and documents.

One detail is worth copying exactly. The redirect_route_name will receive the parameter $uuid with the uuid of the signature model in the database. So your route definition has to accept that parameter, and if it does not, the redirect after signing fails in a way that looks like a routing problem rather than a configuration mistake.

The repository also ships an UPGRADING.md file, which is a reasonable signal for a package that is on version 3.x and supports three Laravel generations at once.

## Certifying the PDF means bringing your own certificate

The certification section is the one that makes this package more than a drawing pad, and it is also the one with a manual step in it.

To certify your signature with TCPDF, you have to create your own SSL certificate with OpenSSL. Otherwise you can find the TCPDF demo certificate, and the README links a specific file in the TCPDF repository for that.

The command to create your own is in the README.

```
cd storage/app
openssl req -x509 -nodes -days 365000 -newkey rsa:1024 -keyout certificate.crt -out certificate.crt
```

Two things to notice in that line. The key is generated in the storage/app directory, and the key and the certificate are written to the same filename, certificate.crt, which is what the config expects. The days value is 365000, which is a long life, and the key size is rsa:1024, which is a small key by current standards. The README points at the TCPDF documentation for more, including the example on certifying documents.

After generating the certificate, you change the value of the variable certify_documents in the config/sign-pad.php file and set it to true. When that variable is true, the package searches the file allocated in the certificate_file path to sign the documents, and you can modify the location or the name of the certificate file by changing that value.

The consequence is that certification is a deployment decision with a cryptographic artefact attached to it, and the demo certificate is a placeholder, not something to ship.

## Where laravel-sign-pad is the wrong choice

Three cases, and the first is the one that matters most in production.

A drawn signature is not an identity. The package captures pixels and stores an image, and a certified PDF proves that the document was signed with a particular certificate, not that the person who drew the signature is who they say they are. If your use case needs to know who signed, or needs a legally qualified electronic signature, or needs the signer to prove possession of a key, this is the wrong shape of tool, and the package does not pretend otherwise.

The second is the version range. PHP 8.2 to 8.5 and Laravel 11 to 13 is a narrow band, and the repository's own version numbering tells you about the release cadence: 3.0.0 in March 2026, 3.0.1 in the same month, 3.0.2 in September. An active major line, and one that moves with the Laravel versions it supports.

The third is the asset pipeline. The package ships a compiled JavaScript bundle built with webpack, the build script in package.json is webpack with webpack.config.js, and the runtime dependency is signature_pad at version 4. That means the canvas behaviour is whatever signature_pad does, and if you need to change how the pad behaves, the change is in your own fork of the asset rather than in the PHP package.

One loose end to close before you ship. The repository is recorded as MIT licensed, with a LICENSE.md file, but the package.json in the repository declares the licence as ISC. The two records disagree, and the difference matters for a package that sits in a document signing flow.

## Conclusion

Adopt laravel-sign-pad if you need a signature captured on a web form, attached to an Eloquent model, and optionally stamped into a generated PDF, and you want that to look like part of your application rather than a third party iframe. Do not adopt it if you need legally meaningful identity verification, since a drawn signature proves nothing about who drew it. Before you build on it, confirm your PHP and Laravel versions fall inside the stated range, read the certified PDF section because it requires you to generate and configure an SSL certificate yourself, and check the licence records in the package metadata, which do not match the repository.

## FAQ

### How do I install laravel-sign-pad?

Run composer require creagia/laravel-sign-pad, then php artisan sign-pad:install to publish the config and migration files and migrate the database, and php artisan vendor:publish with the tag sign-pad-assets to copy the JavaScript assets into public/vendor/sign-pad/. The package requires PHP 8.2 to 8.5 and Laravel 11 to 13.

### How do I place a signature on a generated PDF with laravel-sign-pad?

Implement the ShouldGenerateSignatureDocument contract on your model and return a SignatureDocumentTemplate from getSignatureDocumentTemplate, with a list of SignaturePosition entries giving the page number and x and y coordinates for each signature. A Blade template receives the $model object automatically.

### How do I enable certified PDFs in laravel-sign-pad?

Create your own SSL certificate with OpenSSL, or use the TCPDF demo certificate, then set certify_documents to true in config/sign-pad.php. The package signs documents using the file at the configured certificate_file path, which you can change in the same config file.

### How do I retrieve or delete a signature in laravel-sign-pad?

Retrieve it through the Eloquent relation $myModel->signature, then use getSignatureImagePath, getSignatureImageAbsolutePath, getSignedDocumentPath or getSignedDocumentAbsolutePath. Deletion is done on the model with the deleteSignature method.

## Sources

- [creagia/laravel-sign-pad on GitHub](https://github.com/creagia/laravel-sign-pad)
- [Issues](https://github.com/creagia/laravel-sign-pad/issues)
- [License: MIT](https://github.com/creagia/laravel-sign-pad/blob/main/LICENSE)
- [README](https://github.com/creagia/laravel-sign-pad/blob/main/README.md)
- [Releases](https://github.com/creagia/laravel-sign-pad/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/creagia-laravel-sign-pad
