ynacorp/nova-swatches
A Laravel Nova field that lets you display and select colors as visual swatches, making color attributes easier to manage in Nova resources with a clean, compact admin UI.
Architecture fit. ynacorp/nova-swatches occupies the sanctioned Nova extension seam: a custom Field subclass on the PHP side plus a compiled Vue component registered through Nova's asset pipeline. There are no migrations, no config file, and no service provider to hand-register — it is an additive presentation-layer dependency that stores a plain string column. That is the best possible architectural shape for a third-party admin package: nothing to fight, nothing to uninstall beyond a composer remove and a column drop. If the product already runs Laravel Nova, fit is high; if it does not, the package is irrelevant.
Integration feasibility. Install is three commands (composer require, nova:publish, view:clear) and a single make() call on a resource. Realistic engineering effort is hours, not days — but only after roughly the same amount of time reading vendor source. With 22 stars and zero dependents, the README is the only documentation and may lag the code. The binding API surface is three things: the PSR-4 namespace in composer.json, the fluent setters in src/, and the Vue props in resources/js/ (each withMeta() key maps 1:1 to a PHP setter). Feasible; low effort; requires a licensed Nova sandbox to validate.
Technical risk. Risks are narrow but each is real, and they cluster around packaging rather than function:
ynacorp/nova-swatches from triolla-io/nova-swatches. That mismatch is a governance question, not a typo. Until someone confirms who controls the Packagist namespace, this should not enter a production composer.lock.^4.0 and we are on 5, we are not adopting a field, we are inheriting a front-end rebuild. If dist/ is a shipped compiled artifact with no build surface, we cannot even do that rebuild cheaply.Rule::in(Palette::keys()) (plus a hex regex if arbitrary input is allowed), any user with the field open can POST an arbitrary string. This is the highest-value line of code in the entire integration and it does not come with the package.nova:publish belongs in the deploy script. A blank field in staging that works locally is almost always stale published assets.dependsOn re-renders are all common failure modes for custom Vue fields that cache props on mount. Each must be isolated by disabling the field on a single resource.Key questions (answers required before code is written):
ynacorp Packagist namespace, and is an exact tag pinnable (1.0.0, not ^1.0)?laravel/nova constraint, and does it cover our current Nova major?dist/ a reproducible build, and does the front end wrap a third-party JS color library (supply-chain and rebuild implications)?nullable, validation rules, and dependsOn contexts?#RGB, #RRGGBB, #RRGGBBAA, case, and does empty mean null or ''?Stack fit. Laravel + Nova only. No relevance outside that surface. The integration is a form field over an existing text column, so it composes with the data model rather than altering it.
Migration path. For a new nullable column (string('accent_color', 9)->nullable()), it is a pure drop-in — the 9-char width is the cheap hedge if alpha ever appears. The actual migration work is not the package: it is data, where existing free-hex values must be mapped onto the constrained palette (or nulled with a fallback). Decide up front whether the value is normalized via an Attribute cast or a saving model event; downstream exports, migrations, and CSS interpolation all depend on one consistent format.
Compatibility. Verify the laravel/nova constraint against our Nova major, check the PHP version constraint, and confirm which asset-registration mechanism the package assumes. If the constraint does not cover our version, the decision changes from "adopt" to "reimplement" — do not plan a Vue 4→5 port of a package nobody maintains.
Sequencing.
dist/ audit, third-party JS audit. No code until this passes.App\Support\Palette constant (the design system, reusable by validation, seeders, factories, API resources) and App\Nova\Fields\Swatch as a one-file adapter so no resource ever imports the vendor namespace.nullable, Rule::in(Palette::keys()).Maintenance. There is effectively no upstream maintenance; the burden transfers to whoever adopts it. Budget a few hours per Nova major upgrade, forever, and write that expectation into the adapter's docblock so it is not rediscovered in eighteen months. Assign a named owner and a calendar reminder tied to Nova release notes — or do not adopt.
Support. No vendor. Escalation is internal, and the documentation is the README plus the source. Any incident is ours to diagnose.
Scaling. Runtime cost is negligible — it is a form field with no queries, no queues, and no service dependencies. The cost scales with the number of Nova resources using it (asset publishing surface) and with upgrade frequency, not with traffic or user count.
Failure modes to watch:
dependsOn prop caching.Ramp-up. Near zero for developers fluent in Nova fields; a few hours of source reading for the first one. Admin users need no training — the UI is self-evident — but a manual hex fallback should exist for edge cases, and keyboard/contrast checks belong in the QA checklist rather than in tribal knowledge.
Decision framing. Treat this as source code we adopt, not a product we depend on. It is reversible and low blast radius (a plain string column), so the honest comparison is two days once to build it ourselves versus an indefinite dependency that breaks on every Nova major. Pilot it on one low-risk resource behind a flag, pin and fork into our namespace, wrap it behind the adapter, constrain the palette server-side, and then decide between keeping the fork and reimplementing internally. If color management is core to the product rather than an admin convenience, skip this and build a supported internal field.
How can I help you explore Laravel packages today?