How we built a secure, scalable, and legally binding document signing system with Laravel, Vue, queues, cryptography, and modern web architecture.
On the surface, electronic signatures seem trivial: capture some squiggles on a canvas, slap them onto a PDF, done. But when you dig deeper, you discover a labyrinth of legal requirements, cryptographic integrity checks, identity verification flows, and distributed systems challenges.
Modern e-signature platforms solve problems that aren't immediately obvious: How do you prove someone actually consented to sign? How do you detect tampering after the fact? How do you scale PDF stamping when hundreds of documents need processing simultaneously?
The platform is split into four layers: a Vue 3 SPA for document preparation, a versioned Laravel API for business logic and security, Redis-backed queues for async processing, and cloud storage abstraction for document persistence.
Handles drag-and-drop field placement, coordinate conversion (px ↔ pt), multi-page navigation, and touch support.
/api/v2 enforces authentication, decrypts payloads, validates data, and dispatches queue jobs.
StampPdfJob runs on the documents queue, processing PDFs asynchronously without blocking API responses.
Receives the field map blueprint and stamps signatures, text, and initials onto the final PDF at exact coordinates.
User uploads PDF & places fields
-> Vue 3 produces coordinate blueprint
-> Encrypted payload sent to Laravel API
-> API decrypts, validates, persists template
-> Document sent to recipient via email
-> Recipient verifies identity (email code)
-> Signature collected and submitted
-> StampPdfJob dispatched to Redis queue
-> PDFBox stamps fields at exact positions
-> SHA-256 hash generated & stored
-> Audit trail entry created
-> Signed PDF stored in cloud
Legal compliance is not an afterthought — it's baked directly into every layer of the system. Each signing event triggers a chain of verifiable, timestamped actions.
The key enforcement point is identity verification — no signature is accepted without a time-limited, rate-limited email code that proves the recipient actually received the document.
| Requirement | Implementation |
|---|---|
| Consent | Explicit opt-in with withdrawal support, timestamped |
| Identity Verification | Time-limited email codes, rate-limited per recipient |
| Tamper Detection | SHA-256 hash stored post-signing, re-verified on download |
| Audit Trail | Immutable log: sent, viewed, signed, hashed, IP, user agent |
| Document Integrity | AES-256-CBC encrypted payload in transit + at rest |
| Access Control | UUID-based links, OAuth auth, rate-limited endpoints |
| Record Retention | Cloud storage abstraction, provider-agnostic persistence |
PDFs use points, browsers use pixels. The editor converts continuously so on-screen placement maps exactly to the final stamped position. Without this, elements appear misaligned in the finished PDF.
1const deltaX = event.clientX - startX;
2const deltaY = event.clientY - startY;
3
4// Convert current pt position to px, apply delta, convert back
5const currentLeftPx = ptToPx(parseFloat(element.style.left));
6const currentTopPx = ptToPx(parseFloat(element.style.top));
7
8element.style.left = `${pxToPt(currentLeftPx + deltaX)}pt`;
9element.style.top = `${pxToPt(currentTopPx + deltaY)}pt`;
When a user clicks an element, global mouse listeners are attached so dragging remains smooth even if the cursor moves quickly off the element. Dashed guide lines appear in real time for alignment.
1const handleMouseDown = (event) => {
2 isDragging.value = true;
3 startX = event.clientX;
4 startY = event.clientY;
5
6 DashlineSystem.showDashlines(element);
7 document.addEventListener('mousemove', handleMouseMove);
8 document.addEventListener('mouseup', handleMouseUp);
9};
Once placement is complete, the frontend encrypts the field blueprint with AES-256-CBC before it ever leaves the client. The backend decrypts it only after validating the format — tampered payloads are rejected immediately.
1$decrypted = openssl_decrypt(
2 $rawCiphertext,
3 'AES-256-CBC',
4 $key,
5 OPENSSL_RAW_DATA,
6 $iv
7);
PDF stamping is computationally expensive. Rather than blocking the API response, the backend dispatches a job to a Redis-backed queue. Users get an immediate response while processing happens in the background.
1StampPdfJob::dispatch($uuid, $request->all())
2 ->onQueue('documents');
After stamping, the backend generates a SHA-256 fingerprint of the final PDF. This hash is stored in the audit trail. Any future download that produces a different hash flags the document as potentially compromised.
1$hash = hash('sha256', $pdfContent);
2
3// Stored in audit trail for future verification
4$document->update([
5 'integrity_hash' => $hash,
6 'signed_at' => now(),
7]);
Every significant action — sent, viewed, verified, signed, hash generated — is written to an immutable activity log with IP, user agent, and timestamp metadata suitable for legal proceedings.
1$user->update([
2 'esign_consent' => false,
3 'esign_consent_withdrawn_at' => now(),
4]);
5
6// Activity log entry written for every state change
7ActivityLog::record('consent_withdrawn', $user, $request);
This isn't a weekend hackathon — it's a production-ready, ESIGN-compliant platform designed for real-world document workflows. Every decision stems from production requirements:
The Templator+ platform bridges intuitive document preparation with rigorous security and legal compliance. The frontend makes signing feel effortless — the backend makes it trustworthy.
We've covered Vue 3 composables, coordinate conversion, Laravel queues, SHA-256 hashing, ESIGN compliance, and OAuth authentication. The real takeaway: security and compliance aren't features you add later — they're the foundation you build on from day one.