outl1ne/nova-simple-repeatable
A lightweight repeatable field for Laravel Nova. Define a set of fields once, then let users add, remove, and reorder rows stored as JSON, ideal for simple structured lists without extra database tables or relationships. Quick to configure and easy to use.
What this package actually is. outl1ne/nova-simple-repeatable is a Laravel Nova field component, not a standalone library or service. It renders a repeatable group of Nova sub-fields inside an existing resource form and persists each row-group as a single JSON value on one Eloquent column. There is no shipped migration, no queue, no external service — the application owns the schema and the shape contract. As a TPM, the first thing to internalize is that you are adopting a form-building primitive, not a data platform.
Architecture fit. Two independent gates must both pass before this consumes any delivery capacity:
If either gate fails, the correct TPM action is to close the evaluation rather than to scope around it.
Leverage for a TPM. The value proposition is workstream collapse. A repeatable editorial block normally implies a migration, a child model, a policy, a Nova related-resource, and a form build. Here it becomes a composer require, a nullable json column, a cast, and a fluent field definition (fields(), min(), max(), addButtonText(), and stacked() as of 3.0.1). That converts a recurring "build vs. buy" debate for a narrow, well-understood pattern into a default "buy," and it lets you greenlight content-editing features that would otherwise compete with schema work on the roadmap. It also lets you name the deferral — normalized modeling postponed until reporting, per-row permissions, or workflow needs materialize — with an explicit trigger for revisiting.
Technical risk.
composer.json constraints against your pinned Nova/PHP/Laravel matrix rather than trusting the README or the release date.Key questions to answer before committing.
Stack fit. Laravel + Nova only. Confirming the Nova license, version, and upgrade policy is the first blocking step; every downstream decision depends on it. If that confirmation is ambiguous, treat the whole evaluation as a Nova adoption decision and re-scope.
Migration path. Adoption is largely additive because the package is storage-agnostic. Stand up a nullable json (or text) column, backfill from any legacy source with an idempotent, re-runnable artisan command, and keep the transformation replayable so a bad backfill can be replayed rather than hand-repaired. Replacing an existing normalized child table with a JSON blob is effectively a one-way door — only take it with a stated reason (genuinely variable shape per record, heavy form complexity, no query requirements) and with the reverse migration sketched first.
The ownership pattern that matters most. Wrap the shape in a single PHP class — a custom Eloquent cast or DTO — so Nova field definitions, API resources, exports, seeders, and imports all read and write through one place. That class is simultaneously the validation contract for non-Nova writers and the migration seam when the shape evolves. Without it, multiple teams will encode incompatible shapes into the same column and you will discover it in production. This is the single highest-leverage TPM decision in the whole adoption.
Compatibility. Pin the package in composer.json alongside the Nova major and treat the two as a single upgradable unit. Upgrade Nova and this field in the same change, in staging, with a smoke test that exercises the maximum expected row count and every sub-field type actually in use. Do not let the field float on a ^ constraint across a Nova major boundary.
Sequencing.
Promote to a team convention only if the pattern recurs and the package survives your upgrade cycle. Otherwise leave it as a deliberate one-off and capture the exit path before usage spreads.
Maintenance. The code surface is small, but two recurring obligations must be explicitly budgeted: the Nova license renewal and the package upgrade. Assign one named owner for both. MIT licensing means a stale package is an inconvenience rather than a blocker — a mid-level Laravel/Vue engineer can vendor and patch it — but that fork becomes your maintenance burden and should be a planned contingency, not a surprise discovered mid-quarter. Track the package's release cadence as a leading indicator; a long silence plus an imminent Nova major is the trigger to exercise the fork plan.
Support. No SLA. Support is GitHub issues with a single maintainer, and Nova's own support explicitly excludes third-party fields. The escalation ladder runs maintainer → fork → alternative field package → first-party custom field, and none of those are fast. Set stakeholder expectations at adoption time rather than at the first incident.
Scaling. Scales fine along the records axis — it is just a column. It scales poorly along the rows-per-record axis, because every row is rendered client-side. Set and document a hard cap on rows and sub-fields, and treat Nova form render time and request payload size as the practical ceilings. If downstream consumers need to filter or aggregate on nested values, plan to denormalize into indexed columns or a search index rather than querying the blob in a hot path. Also scope-control the schema itself: keep sub-fields small and shallow, and refuse requests that push complex domain relationships or conditional logic into the blob.
Failure modes to instrument.
Ramp-up. Low technical ramp-up, moderate convention ramp-up. A Laravel developer can add the field in under an hour; the work is teaching the team when not to use it. Plan a short internal write-up plus one worked example resource as the reference implementation, and make the DTO the pattern everyone copies. Budget the pilot as a genuine learning exercise — its output is not just the shipped feature but the cap, the convention, and the measured build-time saving that justify (or refute) wider adoption.
How can I help you explore Laravel packages today?