lathanhvien/nova-text-currency
A Laravel Nova field for entering and displaying monetary values as formatted text, making currency input simple in your admin panels. Add it to Nova resources for a lightweight text-based currency field.
What the release actually is: v1.0.0 is the package's first stable cut, and the only documented capability is presentation-layer number formatting inside an input field — thousands separators and a currency symbol. There is no indication of server-side formatting, locale negotiation, validation rules, persistence, or API surface beyond the input widget. The assessment must therefore treat this as a UI/input-masking component, not a money-handling or accounting library. That distinction drives everything below.
Architecture fit: Low-risk, low-coupling. A formatted-input widget sits at the Blade/view or form-component layer and does not need to touch domain models, persistence, or service boundaries. It is compatible with the Laravel shape most teams already run (Blade, Livewire, Filament, Inertia/Vue/React with a Blade shim) without demanding an architectural change. It is not a fit if the intent was to standardise currency representation across the backend — that would be a misread of scope and should be rejected at intake.
Integration feasibility: Straightforward for a single team in a single sprint. The work is: install, publish/register the component, wire it into one or two forms, and reconcile the boundary between the formatted display value and the raw value that gets validated and persisted. The only meaningful engineering decision is where the canonical value lives — the formatted string must never be the thing that reaches the validator or the database.
Technical risk — where this bites:
"1,234.56" fails Laravel's numeric and decimal rules. If the component does not emit a normalised raw value alongside the display value, every consuming form needs bespoke cleaning, and that cleaning will get written slightly differently each time. This is the single highest-probability defect source.number. Any amount crossing a float boundary is a correctness bug waiting for a finance review. Confirm the package is display-only and that the wire format stays integer minor units or a decimal string.1.234,56 and 1,234.56 are the same digits and different amounts. "Thousand separators" with no stated locale strategy means the component's behaviour is undefined for any non-US user, and copy-paste from an international customer is a live parsing hazard.Key questions for the maintainer / vendor:
FormRequest?Intl.NumberFormat driven? Can it be pinned per tenant?type=number fallback, mobile numeric keyboards, and screen readers? (Accessibility and mobile are the usual casualties in masked inputs.)Stack fit: Best fit is Blade + Alpine or Livewire, where the component can own its own state and emit a raw value on change. Acceptable fit for Filament via a custom field wrapper. Weakest fit for Inertia/Vue/React, where you would be wrapping or reimplementing the behaviour rather than consuming it — in that case, evaluate Intl.NumberFormat plus a controlled input directly and expect comparable effort.
Migration path: There is nothing to migrate from if the prior approach was unstyled text inputs, so this is additive. Where an existing form already formats server-side via a Blade helper or accessor, pick one authority and delete the other. Running both is how you get double-formatted output like $1,234,567.00 rendered as $1,234,567.00,00.
Compatibility checks to run before committing:
^10|^11 only, which matters if the estate is mixed.Sequencing (recommended, roughly two to three weeks elapsed with one engineer part-time):
FormRequest rule for currency normalisation. Consumers must never touch the vendor API directly — this is what makes a later swap a one-file change.^1.0 given a single-release track record; pin exact and upgrade deliberately.Explicitly out of scope: using this to format values in exports, emails, PDFs, or API responses. Those are server-side rendering paths and should use a single server-side formatter so that the two cannot diverge.
Maintenance: The package itself is small, so the maintenance load is mostly your wrapper and the shared normalisation rule — budget ongoing ownership there rather than in dependency upgrades. Watch for the package being a low-traffic single-maintainer project, which is the common shape for input-mask packages; the failure mode is abandonment rather than catastrophe. Mitigation is cheap: keep the wrapper thin and the vendor surface to one or two files.
Support: Expect a modest but non-zero support tail, concentrated in three tickets: "it won't accept my paste", "the decimals disappeared", and "the number changed when I saved and reopened". Pre-empt these with a short internal note and a fixture set of adversarial inputs (1,234.56, 1.234,56, -0.005, 1e3, $ 1,234, empty string, 0). Those fixtures should live in the test suite, not a wiki.
Scaling: Negligible infrastructure impact — it is client-side formatting and adds no request, query, or payload weight. The scaling concern is entirely organisational: every additional form that adopts the package by copy-paste multiplies the normalisation surface. Enforce the wrapper component via code review; that, not the package, is what keeps this linear.
Failure modes, ranked by expected damage:
Ramp-up: A day for a Laravel-fluent engineer, most of it spent understanding the raw-value boundary and the Livewire lifecycle rather than the package API. The cost that gets underestimated is reviewer ramp-up: whoever approves PRs touching money fields must understand why the formatted value never reaches the validator. Put that in the wrapper's docblock, not in a document people stop reading.
Recommendation: Proceed to a time-boxed spike and a single-screen pilot. Approve the release for production money-input use only if the spike confirms a clean raw-value boundary and a configurable locale. Otherwise adopt Intl.NumberFormat behind the same wrapper — the wrapper is the durable asset here, and v1.0.0's two-line changelog does not yet justify treating this package as infrastructure.
How can I help you explore Laravel packages today?