marshmallow/nova-charcounted-fields
Laravel Nova form fields with built-in character counters, helping editors track text length and remaining characters while writing. Useful for enforcing limits on inputs and textareas in Nova admin forms.
What it is: A Laravel Nova field package that swaps Nova's native Text and Textarea fields for variants with a client-side character counter. MIT licensed, 4 stars, 0 dependents, archived, last release 2024-12-23. It is a thin presentation-layer extension: a handful of PHP field classes extending Nova's Field base class, plus Vue components and asset registration. No migrations, no service provider beyond field/asset bootstrapping, no database footprint.
Architecture fit: Narrow but clean. It only makes sense inside an existing Laravel + Nova installation — Nova is a paid, closed-source product, so this package couples us to a vendor's internal field API and Vue asset pipeline rather than to Laravel itself. There is no architectural impedance: fields are a first-class Nova extension point, and dropping a field into a Resource is a one-line change. The fit question is not "does it work with our stack" but "is our stack a Nova stack, and does the requirement justify third-party code at all."
Integration feasibility: Technically trivial (composer require, register field, done — measured in hours). Organizationally questionable. The repository is archived, which means no upstream fixes, no Nova-version tracking, and no security response. With 4 stars and 0 dependents there is effectively no community validation: no evidence of production use, no issue history to mine for edge cases, no second implementer to catch breakage.
Primary technical risk — value proposition collapse: Nova has shipped character-count affordances on textarea fields with maxlength in recent majors. If the native field already renders a remaining-characters indicator, this package's entire reason to exist disappears and the correct decision is "delete the dependency, use native." This must be verified against our pinned Nova version before any other work.
Secondary risks:
max: validation and DB column limits must independently enforce the same bound, and they must agree on what "length" means. JS .length counts UTF-16 code units; PHP Str::length counts code points. Emoji, CJK, and combining characters will make the counter and the validator disagree — the counter says "12/50" while the server rejects at 50.aria-live or an associated description, or screen-reader users get nothing from the feature we paid integration cost for.Key questions for the owning team:
Stack fit: Laravel + Nova only. No PHP framework version coupling beyond what Nova requires; no runtime services, queues, or storage. The dependency graph terminates at the package. That isolation is the main argument in its favor — it cannot destabilize anything outside the admin form rendering layer.
Migration path — fork, don't depend. Given archived status, the right integration is code adoption, not a composer dependency:
maxlength to see whether it already does the job. This spike is a kill-switch, and it should be run before any planning commitment.app/Nova/Fields/ (or a private VCS repository if more than one app needs it). Remove the composer constraint so no future composer update can silently change behavior. Retain the MIT license header.max: rules and the DB column; normalize length semantics in one place (recommend PHP Str::length/mb_strlen as the source of truth and pass the limit to the component). Add aria-live to the counter. Add a Nova field test that asserts validation parity at the boundary (limit−1, limit, limit+1) for an ASCII and a multibyte string.Text::make() → CharCountedText::make() in the target resources. Scope to one resource first; measure nothing, because there is nothing to measure — this is a UX affordance.Compatibility: Pin explicitly to the Nova major we run. Do not declare a permissive constraint. Verify PHP version support and confirm the Vue major matches Nova's frontend; if vendoring pre-built assets, prefer the shipped dist over rebuilding unless we must modify the components, in which case the Node toolchain becomes a standing obligation.
Sequencing: Native-capability check → fork/vendor → harden validation parity → single-resource pilot → document → roll out. The first step can cancel everything after it; keep it cheap and first.
Maintenance: Upstream maintenance is zero — permanently. Every future change, including Nova-major compatibility, is ours. This is the dominant cost and it is small but non-zero: budget a half-day to a day per Nova major upgrade to re-verify asset registration and component rendering, indefinitely. That recurring tax is disproportionate to the feature's value, which is why step 1 above matters so much — the cheapest maintenance plan is not owning it.
Support: No vendor, no community, no issue tracker activity to reference. Internal support burden is "whoever forked it." Name an owner in the catalog entry or the fork will rot silently and be rediscovered during an upgrade.
Scaling: Runtime cost is negligible — a JS counter per field instance, no server round-trips. It will not be a throughput or latency concern at any realistic admin-panel scale. The scaling risk is organizational: a hand-rolled fork of an unmaintained field, replicated across multiple Nova apps, becomes inconsistent drift unless it lives in one shared private package. If we adopt, adopt once.
Failure modes and blast radius:
max: rule because "the field already limits it." Prevent with a comment in the field class and a test that fails if the rule is dropped.Ramp-up: Very low. The code is small enough for any Laravel developer to read in an hour and modify in a day; there is no domain knowledge, no undocumented convention, no operational lore. The only knowledge worth transferring is the validation-parity contract and the Nova-upgrade revalidation step — both fit in the catalog entry.
Recommendation posture: The health signals (archived, 4 stars, 0 dependents, quality score 0.14) argue for non-adoption as a dependency. The opportunity signal (27.16) argues there is room for a better-maintained alternative — most plausibly no package at all: verify the native field, and if it falls short, fork this 200-line MIT codebase into our own Nova field catalog and own it outright. Adopting it as a composer dependency is the one option I would reject.
How can I help you explore Laravel packages today?