savannabits/filament-signature-pad
Filament Signature Pad adds a canvas-based signature field to Filament forms, letting users draw with mouse or touch and save signatures as images. Easy to install and configure, it fits smoothly into admin panels for approvals, contracts, and sign-off workflows.
Architecture fit. This is a presentation-layer plugin: a single Filament form field that wraps a client-side canvas (Alpine component around a signature_pad-style JS library) and persists the result as a base64-encoded image payload on the form state. It sits at the leaf of the dependency graph — nothing in our codebase would depend on it, and it depends only on Filament/Livewire. That is the ideal shape for an optional capability: near-zero architectural coupling, near-zero removal cost. It contributes no domain logic, no models, no migrations, and no service provider surface beyond field registration, so it does not constrain how we model signatures in our own domain — which is where the real design decisions live.
Integration feasibility. Mechanically trivial: composer require, one field call in a form schema, one column on the model. Realistically a half-day spike. The non-trivial work is the persistence decision, which the package does not make for us: the field hands back a base64 data URL, and where that lands (a longText column vs. a disk-backed file with a path/hash in the DB) is an architecture call with long-tail consequences for exports, backups, replication, and storage cost. Treat the package as a UI component and own the storage layer ourselves.
Technical risk. Four risks, in descending order of importance to a TPM:
Key questions (to close before committing):
composer.json, and is the field registered via the v3 plugin/schema API? Is there an open branch or issue for Filament v4?saveUploadedFileUsing-style or dehydrateStateUsing path), or is base64-on-the-model the only supported output?Repeater, Wizard, and modal actions? Any known Livewire payload issues at scale?Stack fit. Native to the TALL stack: Laravel 10/11, PHP 8.1+, Livewire 3, Alpine, Tailwind, Filament 3.x. No build-step changes, no new frontend toolchain, no separate asset pipeline beyond Filament's standard asset publishing. It will not disturb our existing panel configuration.
Migration path. Assume the package ships no migrations and we own the schema entirely. Recommended target — do not default to a base64 column:
signatures table (or polymorphic signatures relation) holding: path on a private disk, mime, bytes, sha256, signer_id, signed_at, ip, user_agent, document_hash, plus a nullable signable morph for reuse across workflows.If the package cannot be made to do the disk handoff cleanly, wrap it: a thin internal SignatureField that composes the vendor field and normalizes output. That wrapper is also our upgrade firewall.
Compatibility. Pin the Filament minor version and add this package to the dependency-review checklist at every Filament major bump. Verify PHP/Laravel constraints in composer.json against our runtime before the spike, and confirm the field renders under Livewire 3's component model rather than a legacy Livewire 2 pattern.
Sequencing.
signatures table + disk handoff + private route. This is the real deliverable; the field is incidental.Maintenance. Small runtime surface (one PHP field class + a JS asset), so ongoing engineering cost is low — but vendor risk is elevated and concentrated in one maintainer. Mitigations: pin the version, keep the wrapper, keep a fork-ready posture, and schedule a compatibility check against every Filament major and every Laravel minor. Budget a recurring half-day per upgrade cycle, not a one-time integration.
Support. Upstream support is effectively "GitHub issues, best effort, one small agency." Do not build a support plan that depends on upstream responsiveness. Internal ownership is the assumption: we diagnose, we patch, we fork if needed. Route any production defect through our own backlog, with upstream notification as a courtesy rather than a dependency.
Scaling. Compute impact is nil — capture is client-side, persistence is one write per submission. The scaling axis is storage and evidence retention, not throughput. Rough sizing: at ~30 KB of trimmed PNG per signature, 100k signatures ≈ 3 GB; add the audit metadata and it's still modest, but it grows monotonically and is never deleted without a retention policy. Plan for: trimming/downscaling before write, rejecting blank canvases so we don't accumulate empty artifacts, and a defined retention/legal-hold policy. If signatures are stored in-DB instead, the same volume lands in your primary database and every backup and replica — that's the failure mode to avoid.
Failure modes to instrument and test.
post_max_size, nginx client_max_body_size, or Livewire's request payload limits; presents as a generic 413/419/500 with no user-facing explanation.Ramp-up. A mid-level Laravel/Filament developer is productive in half a day; the wrapper and storage layer add maybe one more. The real ramp-up is QA and compliance, not engineering: one day for the device/browser matrix, and a separate review with the compliance or legal owner to determine whether the captured artifact plus our metadata satisfies the standard for each workflow we intend to use it in. Budget that conversation early — it determines scope far more than any technical detail of the package.
How can I help you explore Laravel packages today?