Laravel 13 – Digital Signature Integration with Sign Pad.
Laravel 13 – Digital Signature Integration with Sign Pad.
In this tutorial, we will learn how to integrate a digital signature feature in Laravel 13 using the Sign Pad package. We will cover installation, setup, backend logic, and frontend views to build a complete signature workflow.
Quick Overview
This guide walks you through adding a digital signature feature to your Laravel 13 application. You can start with a fresh project or an existing one, then install the laravel-sign-pad package and publish the required configuration and migration files. After that, the User model and routes are configured to support signature functionality, while a UserController handles storing and retrieving user data along with their digital signatures. Blade views are created to collect user information and signatures, as well as to display the saved agreement in a structured layout. Finally, you can test the complete workflow by submitting the form and accessing the saved record using the user’s ID.
Step # 1 : Create a Fresh Laravel 13 Project Called Signature.
Before we dive in, you’ll need a fresh Laravel installation. You can either create a brand-new project or use an existing one. For this guide, we’ll start from scratch and name our project signature. Make sure Composer is installed on your system since Laravel depends on it for package management. It’s also recommended to install the Laravel Installer globally for faster project creation. If you don’t already have the Installer, run the following command.
composer global require laravel/installer
Next, create a new Laravel 13 project using the following command.
laravel new signature
During the installation process, Laravel will prompt you to choose a few configuration options. Select the following settings.
- Starter kit → Select None to keep the project clean and minimal.
- Testing framework → Choose Pest for a modern testing experience.
- Laravel Boost → Select No since it is not required for this project.
- Database → Choose SQLite for a lightweight and simple database setup.
- Run npm install and build assets → Select Yes to automatically install and compile frontend assets.
As a result, you now have a fresh Laravel 13 project named signature, fully configured with your chosen setup options and ready for development.
Step # 2 : Move into the Laravel Project Directory.
Open your terminal (Git Bash, Terminal, or Command Prompt) and navigate to your Laravel project directory by running.
cd c:xampp/htdocs/signature
This will move you into your project folder so you can start working on your Laravel application.
Step # 3 : Install the Laravel SignPad Package.
To implement digital signature functionality in your Laravel application, we will use the SignPad package. It provides an easy way to capture digital signatures drawn by users and store them securely in your project. Install the package by running the following command.
composer require creagia/laravel-sign-pad
Once installed, it gives you all the necessary tools to collect, process, and store digital signatures in a clean and structured way within your Laravel application.
Step # 4 : Publish SignPad Configuration, Migrations, and Assets.
After installing the SignPad package, the next step is to publish its configuration files, database migrations, and required assets so the package can function properly within your Laravel application. Run the following command.
php artisan sign-pad:install
During the installation process, Laravel will prompt you to run the migrations. Type yes to proceed. You may also be asked whether you want to star the package repository on GitHub you can choose yes or no depending on your preference. Next, publish the frontend assets required by the signature pad by running.
php artisan vendor:publish --tag=sign-pad-assets
Once this is done, the SignPad package is fully set up in your Laravel project. The database structure and assets are now in place, so you’re ready to start working with digital signatures in your application.
Step # 5 : Add Signature Support to the User Model.
To enable digital signatures in your application, we need to update the User Model so it can handle signature functionality. This is done by adding the required trait and implementing the contract provided by the SignPad package. Replace the content of your User Model with the following code.
<?php
namespace App\Models;
// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Database\Factories\UserFactory;
use Illuminate\Database\Eloquent\Attributes\Fillable;
use Illuminate\Database\Eloquent\Attributes\Hidden;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
// Enables digital signature capability for the model
use Creagia\LaravelSignPad\Concerns\RequiresSignature;
use Creagia\LaravelSignPad\Contracts\CanBeSigned;
#[Fillable(['name', 'email', 'password'])]
#[Hidden(['password', 'remember_token'])]
class User extends Authenticatable implements CanBeSigned
{
/** @use HasFactory<UserFactory> */
use HasFactory, Notifiable;
// Provides signature relationship and signing behavior for this model
use RequiresSignature;
/**
* Define attribute casting for the model.
*
* - email_verified_at: treated as a Carbon datetime instance
* - password: automatically hashed when set
*/
protected function casts(): array
{
return [
'email_verified_at' => 'datetime',
'password' => 'hashed',
];
}
}
With this update, the User Model is now capable of handling digital signatures. Each user can be associated with a signature, which allows your application to support signing functionality in a structured way.
Step # 6 : Define Application Routes.
Next, we need to define the routes that will handle the main flow of the application. These routes are responsible for showing the form, processing the submitted data, and displaying the saved signature details. First, import the UserController in your web.php file.
use App\Http\Controllers\UserController;
Now define the routes.
// Display the user creation form
Route::get('/', [UserController::class, 'create']);
// Handle form submission and store user data along with signature
Route::post('/confirm', [UserController::class, 'store']);
// Show the saved user agreement with signature
Route::get('/show/{user}', [UserController::class, 'show']);
These routes handle the full flow of the application, starting from the form, saving the user’s data along with their signature, and finally showing the completed record.
Step # 7 : Create UserController to Handle Signature Logic.
To handle the signature workflow, we need a controller that manages form display, user creation, signature storage, and displaying the final agreement. Create the controller using the following Artisan command.
php artisan make:controller UserController
Next, open the newly created UserController.php file and replace its content with the following code.
<?php
namespace App\Http\Controllers;
use App\Models\User;
use Creagia\LaravelSignPad\Signature;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
class UserController extends Controller
{
/**
* Show the signature form.
*/
public function create()
{
return view('sign');
}
/**
* Handle form submission and store user + signature data.
*/
public function store(Request $request)
{
// Validate incoming data
$validatedData = $request->validate([
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:8',
'sign' => 'required',
]);
// Store user record
$user = User::create($validatedData);
// Convert base64 signature to image
$signatureData = str_replace('data:image/png;base64,', '', $validatedData['sign']);
$signatureData = base64_decode($signatureData);
// Save signature image
$imageName = 'signatures/' . Str::uuid() . '.png';
Storage::disk('public')->put($imageName, $signatureData);
// Store signature metadata
$signature = new Signature();
$signature->model_type = User::class;
$signature->model_id = $user->id;
$signature->uuid = Str::uuid();
$signature->filename = $imageName;
$signature->document_filename = null;
$signature->certified = false;
$signature->from_ips = json_encode([request()->ip()]);
$signature->save();
return redirect()->back()->with('success', 'Employment Agreement submitted successfully!');
}
/**
* Display user along with their signature.
*/
public function show(User $user)
{
$user->load('signature');
return view('show', compact('user'));
}
}
User controller handles the complete signature workflow through three main methods. The create() method is responsible for displaying the form where users can enter their details and draw their signature. The store() method takes care of validating the incoming request, creating a new user, processing the base64 encoded signature, saving it as an image in storage, and storing its reference in the database. Finally, the show() method retrieves the user along with their saved signature and displays the final agreement view.
Step # 8 : Create Storage Link.
To make uploaded files accessible from the browser, we need to create a symbolic link between the storage directory and the public folder. Run the following Artisan command.
php artisan storage:link
This ensures that any files saved in the storage directory can be accessed publicly through the application, which is essential for displaying uploaded signatures.
Step # 9 : Create the Views.
Now we will create the main UI for the application. Start by creating a file named sign.blade.php inside the resources/views directory. This view contains a form where users can enter their details and provide a digital signature to complete the agreement.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Code Shotcut - Laravel 13 SignPad Example</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
.sign-pad-button-submit,
.sign-pad-button-clear {
margin-top: 10px;
padding: 0.75rem 1.25rem;
font-weight: 600;
border-radius: 0.75rem;
transition: all 0.2s ease;
font-size: 1rem;
}
/* Submit button (primary) */
.sign-pad-button-submit {
background-color: #6366f1; /* indigo-500 */
color: white;
}
.sign-pad-button-submit:hover {
background-color: #4f46e5; /* indigo-600 */
}
.sign-pad-button-submit:active {
background-color: #4338ca; /* indigo-700 */
}
/* Clear button (neutral secondary) */
.sign-pad-button-clear {
background-color: #374151; /* gray-700 */
color: white;
}
.sign-pad-button-clear:hover {
background-color: #4b5563; /* gray-600 */
}
.sign-pad-button-clear:active {
background-color: #1f2937; /* gray-800 */
}
</style>
</head>
<body class="min-h-screen bg-gradient-to-br from-gray-950 via-gray-900 to-gray-800 flex items-center justify-center p-6 text-gray-100">
<form action="/confirm" method="POST"
class="w-full max-w-2xl backdrop-blur-xl bg-white/10 border border-white/10 shadow-2xl rounded-3xl p-10">
@csrf
<!-- Header -->
<div class="text-center mb-8">
<h3 class="text-3xl font-extrabold tracking-tight text-white">
Code Shotcut
</h3>
<p class="text-indigo-200 mt-2 text-sm">
Employment Agreement Confirmation
</p>
</div>
<p class="text-center text-gray-300 mb-8 text-sm leading-relaxed">
Please enter your details and sign below to accept the employment terms.
</p>
<!-- Success -->
@if (session('success'))
<div class="mb-4 bg-green-500/10 border border-green-400/30 text-green-300 p-4 rounded-xl">
{{ session('success') }}
</div>
@endif
<!-- Errors -->
@if ($errors->any())
<div class="mb-4 bg-red-500/10 border border-red-400/30 text-red-300 p-4 rounded-xl">
<ul class="list-disc list-inside space-y-1">
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<!-- Inputs -->
<div class="space-y-5">
<!-- Name -->
<div>
<label class="text-sm font-medium text-gray-200">Full Name</label>
<input type="text" name="name" required
class="mt-1 w-full px-4 py-3 rounded-xl bg-white/5 border border-white/10 text-white placeholder-gray-400
focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent"
placeholder="Enter your full name">
</div>
<!-- Email -->
<div>
<label class="text-sm font-medium text-gray-200">Email Address</label>
<input type="email" name="email" required
class="mt-1 w-full px-4 py-3 rounded-xl bg-white/5 border border-white/10 text-white placeholder-gray-400
focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent"
placeholder="Enter your email">
</div>
<!-- Password -->
<div>
<label class="text-sm font-medium text-gray-200">Password</label>
<input type="password" name="password" required
class="mt-1 w-full px-4 py-3 rounded-xl bg-white/5 border border-white/10 text-white placeholder-gray-400
focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent"
placeholder="Create a password">
</div>
<!-- Signature -->
<div>
<label class="text-sm font-medium text-gray-200">Digital Signature</label>
<p class="text-gray-400 text-xs mb-2">
Sign below using your mouse or touch device.
</p>
<div class="bg-white/100 border border-white/10 rounded-2xl p-4">
<x-creagia-signature-pad name="sign" />
</div>
</div>
</div>
</form>
<script src="{{ asset('vendor/sign-pad/sign-pad.min.js') }}"></script>
</body>
</html>
Next, create another view named show.blade.php inside the resources/views directory. This file will be used to display the user’s agreement details, including their name, email address, and signature image (if it exists).
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Code Shotcut - Laravel 13 SignPad Example</title>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="min-h-screen bg-gradient-to-br from-gray-950 via-gray-900 to-gray-800 flex items-center justify-center p-6 text-gray-100">
<!-- Glass Card -->
<div class="w-full max-w-md backdrop-blur-xl bg-white/10 border border-white/10 shadow-2xl rounded-3xl p-8">
<!-- Heading -->
<h3 class="text-2xl font-bold text-center text-white">
Code Shotcut - User Agreement
</h3>
<!-- Description -->
<p class="text-center text-gray-300 mt-2 mb-6 text-sm">
Below are the details you submitted along with your digital signature.
</p>
<!-- User Details -->
<div class="space-y-3 mb-6 text-sm">
<p class="text-gray-200">
<span class="text-gray-400">Name:</span>
<span class="font-medium text-white">{{ $user->name }}</span>
</p>
<p class="text-gray-200">
<span class="text-gray-400">Email:</span>
<span class="font-medium text-white">{{ $user->email }}</span>
</p>
</div>
<!-- Signature Section -->
<div>
<h4 class="text-sm font-semibold text-gray-200 mb-2">
Digital Signature
</h4>
@if ($user->signature)
<div class="bg-white/100 border border-white/10 rounded-2xl p-3">
<img
src="{{ asset('storage/' . $user->signature->filename) }}"
alt="User Signature"
class="w-full h-auto rounded-lg"
>
</div>
@else
<div class="bg-white/100 border border-white/10 rounded-2xl p-4 text-gray-400 text-sm">
No signature available.
</div>
@endif
</div>
</div>
</body>
</html>
These Blade templates handle the frontend functionality for collecting user information and digital signatures, as well as displaying the stored agreement data in a structured format.
Step # 10 : Test the Signature Pad Functionality.
Start the Laravel development server using the following command.
php artisan serve
Once the server is running, open your browser and visit: http://127.0.0.1:8000. You should now see the employment agreement form. Enter the required details, draw your signature in the signature pad, and submit the form to save the data.
After submitting the form, you can review the stored record by visiting: http://127.0.0.1:8000/show/{id}. Replace {id} with the actual user ID to display the submitted details along with the saved signature.
This confirms that the signature capture, storage, and retrieval process is working correctly, completing the full workflow from form submission to data display.
Conclusion
By following this guide, you’ve successfully integrated a digital signature feature into your Laravel 13 application. Users are now able to submit their details along with a secure digital signature, which is safely stored and retrieved within the system. With the help of the laravel-sign-pad package, the entire signature workflow becomes simple, reliable, and easy to manage. This setup provides a solid foundation for handling user agreements and can be further customized to fit your specific project requirements.
For more information and advanced usage, you can refer to the official creagia/laravel-sign-pad documentation: https://github.com/creagia/laravel-sign-pad.
Share this with friends!
To engage in commentary, kindly proceed by logging in or registering
Subscribe to Our Newsletter
Stay ahead of the curve! Join our newsletter to see what everyone’s talking about.
0 Comments