Weave Code
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

Laravel Sign Pad Laravel Package

creagia/laravel-sign-pad

Laravel package for capturing pad signatures tied to Eloquent models. Adds signing flows, stores signatures and optional signed/certified PDF documents, with configurable disks, routes, and redirects. Includes install command, migrations, and publishable JS assets.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the package:

    composer require creagia/laravel-sign-pad
    php artisan sign-pad:install
    php artisan vendor:publish --tag=sign-pad-assets
    
  2. Prepare your model (e.g., Contract):

    use Creagia\LaravelSignPad\Concerns\RequiresSignature;
    use Creagia\LaravelSignPad\Contracts\CanBeSigned;
    
    class Contract extends Model implements CanBeSigned
    {
        use RequiresSignature;
    }
    
  3. Add the signature form to your Blade view:

    @if (!$contract->hasBeenSigned())
        <form action="{{ $contract->getSignatureRoute() }}" method="POST">
            @csrf
            <x-creagia-signature-pad />
        </form>
        <script src="{{ asset('vendor/sign-pad/sign-pad.min.js') }}"></script>
    @endif
    

First Use Case: Basic Signature Collection

  • Trigger: User clicks "Sign" on a Contract record.
  • Flow:
    1. Render the signature pad via x-creagia-signature-pad.
    2. User draws a signature and submits the form.
    3. Package saves the signature image to storage/app/signatures/{uuid}.png and attaches it to the Contract model via the signature relation.
    4. Redirect to a confirmation page (configurable via redirect_route_name in config/sign-pad.php).

Implementation Patterns

Core Workflows

1. Model Integration

  • Trait-Based: Use RequiresSignature to auto-load the signature relation and lifecycle methods (e.g., bootRequiresSignature for model events).
  • Contracts: Implement CanBeSigned (mandatory) and optionally ShouldGenerateSignatureDocument for PDF generation.
  • Example:
    class Invoice extends Model implements CanBeSigned, ShouldGenerateSignatureDocument
    {
        use RequiresSignature;
    
        public function getSignatureDocumentTemplate(): SignatureDocumentTemplate
        {
            return new SignatureDocumentTemplate(
                signaturePositions: [new SignaturePosition(page: 1, x: 100, y: 200)]
            );
        }
    }
    

2. PDF Generation

  • Templates: Support for:
    • Blade Templates: Inject the model into Blade views (e.g., resources/views/pdf/invoice.blade.php).
    • PDF Templates: Merge signatures into existing PDFs using PdfDocumentTemplate.
  • Positions: Define multiple signature positions per page:
    signaturePositions: [
        new SignaturePosition(page: 1, x: 50, y: 50),
        new SignaturePosition(page: 2, x: 150, y: 100),
    ]
    

3. Frontend Integration

  • Component Customization: Pass props to <x-creagia-signature-pad /> for styling/UX:
    <x-creagia-signature-pad
        border-color="#3b82f6"
        pad-classes="border-2 border-dashed"
        submit-name="✍️ Sign Contract"
        :disabled-without-signature="true"
    />
    
  • Multiple Pads: Use unique IDs for multiple pads on a single page:
    <x-creagia-signature-pad id="pad-1" />
    <x-creagia-signature-pad id="pad-2" />
    

4. Backend Logic

  • Signature Retrieval:
    $signaturePath = $contract->signature->getSignatureImageAbsolutePath();
    $pdfPath       = $contract->signature->getSignedDocumentAbsolutePath();
    
  • Deletion:
    $contract->deleteSignature(); // Deletes image + DB record
    

5. Certified PDFs

  • Prerequisites:
    1. Generate a certificate (e.g., storage/app/certificate.crt).
    2. Configure config/sign-pad.php:
      'certify_documents' => true,
      'certificate_file'  => storage_path('app/certificate.crt'),
      'certificate_info'  => [
          'country' => 'US',
          'state'   => 'California',
          // ...
      ],
      
  • Trigger: Signatures are automatically certified on generation if config is set.

Integration Tips

With Storage Systems

  • Custom Disks: Override config/sign-pad.php to use S3 or other disks:
    'disk' => 's3',
    'signature_path' => 'contracts/signatures',
    'document_path'  => 'contracts/documents',
    

With Queues

  • Async Processing: Dispatch PDF generation jobs:
    use Creagia\LaravelSignPad\Jobs\GenerateSignatureDocument;
    
    GenerateSignatureDocument::dispatch($contract)->onQueue('pdf-generation');
    

With Notifications

  • Post-Signature Emails: Use Laravel Notifications to send signed PDFs:
    $contract->signature->generateDocument();
    Mail::to($contract->user)->send(new ContractSigned($contract));
    

With Policies

  • Authorization: Restrict signature actions:
    class ContractPolicy
    {
        public function sign(User $user, Contract $contract)
        {
            return $user->can('sign_contracts');
        }
    }
    

Gotchas and Tips

Pitfalls

1. Double Submissions

  • Issue: Users might submit the form twice if not handled.
  • Fix: Use the disabled-without-signature prop or add client-side validation:
    document.querySelector('form').addEventListener('submit', (e) => {
        if (!document.getElementById('signature-pad').isEmpty()) {
            e.preventDefault();
            alert('Please draw a signature first.');
        }
    });
    

2. Certificate Errors

  • Issue: TCPDF fails silently if the certificate is invalid or missing.
  • Debugging:
    • Verify certificate_file path in config/sign-pad.php.
    • Check certificate format (PEM/DER) and permissions.
    • Enable TCPDF logging:
      \TCPDF::setLogger(new \TCPDFLogger(\TCPDFLogger::LEVEL_DEBUG));
      

3. Signature Position Offsets

  • Issue: Signatures appear misaligned in the PDF.
  • Fix: Use SignaturePosition with precise coordinates (test with page: 1, x: 100, y: 100 as a baseline).

4. Blade Template Injection

  • Issue: Model data not available in Blade templates.
  • Fix: Ensure the template path is correct and the model is passed:
    // In your controller
    return view('pdf.contract', ['model' => $contract]);
    

5. Disk Permissions

  • Issue: Signed files not saved or deleted.
  • Fix: Ensure the configured disk (config/sign-pad.php) has write permissions:
    chmod -R 755 storage/app/signatures storage/app/documents
    

Debugging Tips

Log Signature Data

  • Dump the signature relation to verify data:
    dd($contract->signature->toArray());
    

Check File Paths

  • Verify paths are correct:
    $this->assertFileExists($contract->signature->getSignatureImageAbsolutePath());
    

Test PDF Generation

  • Manually trigger generation to isolate issues:
    $contract->signature->generateDocument();
    

Extension Points

1. Custom Signature Validation

  • Override the validateSignature method in your model:
    public function validateSignature(array $data): bool
    {
        return strlen($data['signature']) > 100; // Custom logic
    }
    

2. Dynamic Signature Positions

  • Fetch positions from a database or API:
    public function getSignatureDocumentTemplate(): SignatureDocumentTemplate
    {
        $positions = $this->signaturePositions()->get();
        return new SignatureDocumentTemplate(
            signaturePositions: $positions->map(fn ($p) => new SignaturePosition(
                page: $p->page,
                x: $p->x,
                y: $p->y
            ))
        );
    }
    

3. Webhook Triggers

  • Dispatch events after signature:
    // In your model's boot method
    static::signed(function ($model) {
        event(new ContractSignedEvent($model));
    });
    

4. Multi-Step Signatures

  • Use the signature relation to store intermediate states:
    $contract->signature->update(['status' => 'pending_review']);
    

Configuration Quirks

Redirect Route

  • The redirect_route_name in config/sign-pad.php must match a named
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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport