shivanshrajpoot/nova-create-or-add
A Laravel Nova field that lets you create a new related resource or attach an existing one directly from a relationship form, streamlining inline workflows without leaving the parent resource.
Confirm the package resolves against your Nova major before writing any code. This is a third-party Nova field, so it compiles against Nova's internal Vue component API. Two reads gate everything else:
composer.json — check the laravel/nova and laravel/framework constraints. A missing or * constraint means compatibility was never reasoned about; treat that as a signal to read the source rather than trust the tag.shivanshrajpoot/nova-create-or-add, but the source lives at Abhi0725/nova-create-or-add. Confirm which is canonical. If they diverge, treat the GitHub repo as the reference and do not assume the Packagist tag matches it.Install into staging, not production.
composer require shivanshrajpoot/nova-create-or-add
php artisan vendor:publish --tag=nova-create-or-add-assets
The publish tag varies — open the service provider in src/ and read publishes() rather than guessing. After publishing, hard-refresh and confirm the field renders at all before you configure anything.
Read these four things, in this order:
src/ — the field class. Does it extend BelongsTo or a bare Field? That single fact determines whether you inherit Nova's search, nullable, rules, and default behavior for free, or have to reimplement each.routes/ and any controllers — the most important read. Inline creation puts a write path inside a form widget. You need to know whether the create posts to Nova's standard resource store endpoint (policies and middleware apply automatically) or a bespoke controller (they may not).resources/js/ — skim the Vue component for the search debounce, the create submit handler, and how the new record is merged back into the select.composer.json — asset registration and version constraints.First use case: a sparse BelongsTo. Don't start with the busiest relation in the app. Pick a target table that is frequently empty — vendors, contacts, authors, categories — on a resource where the operator creating the parent regularly discovers the child doesn't exist. Register the field exactly where the stock BelongsTo sits, keeping the same foreign key column so nothing downstream (indexes, filters, with(), serialization) changes:
use Shivanshrajpoot\NovaCreateOrAdd\CreateOrAdd; // verify namespace in src/ first
public function fields(Request $request)
{
return [
CreateOrAdd::make('Vendor', 'vendor_id')
->rules('required'),
];
}
Rule out native Nova first — it's free and supported. Two hours of work: does BelongsTo::searchable() plus Nova's built-in create-relation affordance already cover the case? If yes, close the ticket. This package's value proposition is the narrow case where native Nova leaves you with a save-parent → navigate → create-child → return cycle, and that case narrows with every Nova release.
Drop-in swap, one relation at a time. The cheapest integration is a field-for-field replacement with no schema change and no data migration — the field writes through the Eloquent relationship you already own. That also means rollback is a one-line revert to BelongsTo. Say that out loud to anyone nervous about the dependency.
Treat the field as a UI affordance, not an authorization boundary. The pattern that matters: create-then-attach must hit Nova's standard resource store route so the related model's create policy, validation rules, and model events run through paths the rest of the app already trusts. If the source shows a custom controller, patch a policy check into your fork before the field goes anywhere near operators. Never rely on the field's own validation as the only gate.
Scope to single-select. BelongsTo and MorphTo are the natural fit. For BelongsToMany attach semantics, nested creation, or multi-record creation, this is the wrong tool — route those to a Nova action or a custom tool rather than bolting them onto the field.
Vendor and pin on day one, even if the spike is clean. Nine stars, zero dependents, one maintainer. Adopting it converts an external dependency into a pin on your Nova major version — every Nova upgrade now carries a third-party bundle that fails silently when the component API shifts. Mitigate with a packages/ path repository or a private VCS fork, add Dependabot for laravel/nova and laravel/framework, and put the coupling on the upgrade checklist. Cost: about an hour.
Smoke test six paths in CI, against the exact Nova version in production:
createShip behind a flag, one resource at a time, and keep an inventory. Enumerate every Nova relation where the target table is sparse — tags, authors, categories, vendors, contacts. A short list argues for a local patch; a long list argues for a single quick-create convention across resources, which is a different and larger piece of roadmap work. Tracking the list now saves you from re-litigating it at the next Nova upgrade.
Plan for the fallback. A minimal in-house field is 1–2 dev-days. Build-vs-fork should be decided on evidence from the source read and the spike, not on the README. Because replacement cost is low, the decision stays reversible at every step — tell stakeholders, so nobody treats it as a one-way door.
Version mismatch fails silently, not loudly. Composer resolution failing is the good outcome. The expensive outcome is a permissive constraint resolving cleanly and then rendering a blank or inert field at runtime, with no exception and no log line. Test three axes independently because they fail differently: Composer resolution (fast, loud), asset publish and build (medium, sometimes loud), runtime behavior (slow, silent).
Authorization is the highest-severity risk. Small Nova fields routinely post to custom search and create endpoints that skip the policy layer entirely. Read routes and controllers before you read the README. Confirm the create policy on the related model is evaluated, and confirm at which layer.
Orphaned records from a non-transactional create-then-attach. Create and attach are two operations. If attach fails after create succeeds, you accumulate orphaned rows quietly in whatever table the operator was trying to reference. Check the source; if it isn't wrapped in DB::transaction(), wrap it in your fork.
Double-submit produces duplicates. Slow connection plus no idempotency guard equals two rows and two confused operators. Add a submit lock in the Vue component or a server-side uniqueness guard — ideally both.
Search scoping leaks across tenants. If the app is multi-tenant, verify the search endpoint is tenant-scoped, paginated, and debounced. An unscoped search endpoint on a high-cardinality table is simultaneously a performance problem and a data-exposure problem.
Validation errors can destroy the parent form's state. The classic failure mode for widgets of this class: an inline create error resets the parent form and the operator loses typed work. They stop trusting the form after that. Exercise this explicitly in the spike, not as an afterthought.
Assets are pre-compiled and go stale. Republish after any Nova upgrade and confirm the published asset hash actually changed. A stale bundle is the classic silent failure — the field simply stops responding, with nothing in the logs.
Nullable and required ordering. If the field wraps BelongsTo, chain ->nullable(), ->rules(), ->default(), and ->help() exactly as you would on the native field — but check the Vue source to confirm the component honors nullable. Inheriting the PHP API does not guarantee the front end respects it.
Debugging checklist, in order:
laravel.log.storage/logs/laravel.log — policy denials and validation exceptions land here only if the request actually reaches the app. An empty log alongside a broken field points at the asset or component layer.Extension points are limited by design. This is a leaf package, not infrastructure — it registers a field, publishes assets, and reads/writes through relationships you already own. The realistic surface is: fork the Vue component, subclass the field class in your app's Nova namespace, or gate the endpoint in the controller. Do not expect a plugin API.
Bus factor of one. Nine stars, zero dependents, no community review of the surface. Plan for the maintainer disappearing and price the fork accordingly — that is the whole reason to vendor rather than require directly.
How can I help you explore Laravel packages today?