blendbyte/nova-items-field
A Laravel Nova field for managing repeatable items as JSON. Define item fields in PHP, let editors add, reorder, and remove rows, and store structured array data on your models—ideal for flexible content blocks and simple repeaters.
1. Content modeling: JSON array vs. relational schema. The recurring product question is whether a repeatable list deserves its own table, model, migration, and admin surface. This field lets you answer "not yet" cheaply — the entire list lives in one JSON column, edited through drag/drop. For FAQ pairs, feature bullets, spec rows, nav links, pricing tiers, opening hours, and redirect maps, that defers normalized tables and per-item models until cross-item querying actually becomes a requirement. It converts a schema debate into a reversible, low-cost deferral rather than a one-way door.
2. Build vs. buy for the admin UI. The alternative to adopting this is a bespoke Vue component or hand-rolled Nova field for every repeatable editor you ship. At ~200 lines, MIT-licensed, and free, adoption is a clear "buy" that removes a recurring chunk of admin front-end work from the backlog — and keeps it off, since each new two-field list becomes configuration rather than a ticket.
3. The Nova 5 upgrade decision. As the maintained fork of the abandoned dillingham/nova-items-field, this directly unblocks the "upgrade Nova now vs. stay on an unsupported major" roadmap call. If any admin surface depends on this field, the fork is what lets the upgrade proceed this quarter instead of slipping again. It's a small dependency carrying disproportionate roadmap leverage.
4. Platform currency (PHP 8.4+ / Laravel upgrade train). Release 1.3.5 fixes an implicit-nullable deprecation in the Items constructor on PHP 8.4+. Unglamorous, but exactly the kind of one-line item that becomes a standing exception in the platform team's runtime bump. Roadmap impact: one fewer "we can't move to PHP 8.4 until the admin field is patched" negotiation.
5. Content rules as configuration, not engineering. Per-row validation (dot-notation rules, max, url) and display controls (keyLabel, valueLabel, heading, hide-from-index/detail) let content requirements ship as config changes. The loop from "editors need required URLs on link rows" to shipped behavior compresses from a sprint to minutes.
6. Scope discipline for internal tooling. It supports a deliberate "good enough structured editing" stance: ship the admin surface for v1, measure whether editors actually hit its limits, then invest in a real content model. It keeps "build a proper CMS layer" out of the current cycle without pretending the need will never arrive.
7. A concrete QA and validation story. Per-row error messages in dot notation are the main functional reason to prefer this over a textarea full of raw JSON. That's a measurable reduction in editor error and support load, not just a nicer UI.
Adopt when:
dillingham package remains the compatible option — the two cannot coexist in composer.json, though they store byte-identical JSON, so switching is a namespace sweep with no data migration.^1.3.5 is the minimum. Pin it explicitly. Do not let ^1.0 float across a tag boundary nobody has read — the 1.3.5 changelog header points at 2.0.1 for structural reasons (GitHub picked a non-ancestor tag as the diff base), so it must not be misread as a downgrade.key and value are hard-coded in the Vue component; keyLabel()/valueLabel() are cosmetic. Three or more attributes per row means you will end up stuffing JSON inside value — wrong tool, stop here.Look elsewhere when:
HasMany with per-row identity, diffing, and merge.nova-components/. If that contingency isn't acceptable to the team, don't adopt — and if no admin surface currently depends on it, the Nova 5 argument above evaporates too.For executives — the one-paragraph version: We can give editors a proper drag/drop interface for structured lists — links, FAQs, feature bullets, specs, pricing tiers — without adding database tables, models, or migrations. The list is stored as JSON on the existing record, so the cost is essentially zero and the decision is reversible. It is a free, MIT-licensed, ~200-line package, and critically it is the maintained fork that lets us complete the Nova 5 upgrade instead of deferring it another quarter. The main risk is that it's a small community project with one maintainer; the mitigation is to pin the version and keep the option to vendor it in-house, which is inexpensive at this size.
For engineering — the summary: Adopt blendbyte/nova-items-field ^1.3.5 as the standard field for two-attribute repeatable lists in Nova 5 resources. Composer-only install — no service provider, no config, no migrations. Data shape is an ordered array of {key, value} pairs in a single JSON column with an array cast. Wire Items on forms only and pair it with a computed Text/Badge for index and detail so index queries stay cheap and you control escaping. Put validation in the resource's rules() in dot notation (links.*.key, links.*.value) — ->rules('array') validates only the outer envelope. Keep the top-level rule nullable, since an empty list submits as []. Note the constraints: no per-row IDs (whole-array overwrite, last write wins), no search inside the JSON, hard-coded key/value names, and prebuilt assets in dist/ requiring nova:publish after any Vue change. Pin the version, and treat vendoring into nova-components/ as a known, pre-agreed contingency rather than an emergency.
How can I help you explore Laravel packages today?