Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Nova Button Laravel Package

sietse85/nova-button

Add customizable action buttons to Laravel Nova resources with sietse85/nova-button. Trigger links, modal forms, or custom logic directly from resource pages, dashboards, and toolbars using simple, flexible configuration.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit

  • This is a view-layer package, not a platform commitment. It ships a single Nova field class that renders a configured button, plus a compiled Vue component in dist/. No migrations, no published config, no service provider registration beyond Composer auto-discovery. That means it touches no data model, no queue topology, and no service boundary — the integration surface is confined to Nova resource fields() methods.
  • Fit is conditional on one thing: you already run Laravel Nova 4+. If Nova is not in the stack, this package is irrelevant, and if Nova is in the stack, this package is competing only against "write a custom Nova Tool/Card/Vue component," which is a materially more expensive answer for the same outcome.
  • The value proposition is repetition-driven. A single button does not justify a dependency; the fifth "approve / resend / sync / open-in-vendor" affordance across four resources does. Treat adoption as a standing build-vs-buy decision: single-record action buttons are bought, not built.
  • The package's natural boundary is narrow and should be written down: single-record, click-to-run, one-step affordances. Bulk/multi-record and queued operations belong to Nova Actions; anything with a form, wizard, or branching logic belongs to a Nova Tool. Drift across that line is where the authorization and idempotency debt accumulates.

Integration feasibility

  • Mechanically trivial: composer require sietse85/nova-button, pin an explicit tag, and a Nova-fluent developer has a rendered button in well under a day. There is no infrastructure work, no capacity negotiation with front-end, and no design cycle.
  • The real cost is not the package. It is the authorization, idempotency, and audit trail behind the button — a backend deliverable that the package makes visible but does not provide. Budget that separately or the "one-day integration" estimate is fiction.
  • Highest-leverage first action is not a button, it is a thin internal wrapper class (App\Nova\Fields\ActionButton extends Sietse85\NovaButton\Button) that re-exposes only the fluent API you actually use. This converts exit cost from "grep every resource" to "rewrite one file" and is the single decision that makes the vendor risk acceptable.

Technical risk

  • Vendor concentration. 37 stars, single maintainer, last release Feb 2025, MIT. The 0-dependent count is structurally misleading — Nova is commercial and not distributed via Packagist, so dependent counts under-report adoption for every Nova add-on. Read this as "small but not abandoned," not "unproven."
  • Forward-compatibility is asserted, not contracted. "Nova 4+" is a floor, not a tested guarantee, and Nova's internal Vue component API is not a public stability contract. Pin the package and Nova together and upgrade them in the same commit as a deliberate pair.
  • Supply chain. dist/ is prebuilt JS running inside your highest-privilege authenticated UI. Either rebuild from source in CI and diff, or have someone read it. This is a security review item, not an ops convenience, and it is the step that is routinely skipped.
  • Failure modes are silent. The characteristic breakage is a blank table cell or a browser console error — never a 500. Server-side monitoring will not catch it, which means the risk is "operators quietly lose a workflow for two weeks" rather than "alert fires."
  • Security is entirely your responsibility. canSee, confirm(), and disabled states are all client-side UX hygiene. Every backing route and Action must independently enforce Nova's guard, CSRF, and your policies. A determined user can POST the URL directly.

Key questions for the adopting team

  1. Who is the named owner of this dependency? Unassigned OSS inside an admin panel becomes orphaned infrastructure within a quarter.
  2. What is the button → endpoint mapping, in one reviewable place, so on-call can trace a reported failure to a route?
  3. Do we have a documented decision rule (button vs. Action vs. Tool) that a reviewer can enforce in PR, or does it live in someone's head?
  4. Is our Nova version pinned, and is "upgrade Nova" a checklist item that includes clicking a button in staging with the console open?
  5. For each mutating button, what is the server-side idempotency guard (status transition check, firstOrCreate on a job key, lock)?
  6. Can we reproduce dist/ from source, or do we accept and vendor a reviewed build?

Integration Approach

Stack fit

  • Laravel + Nova 4+ + Composer. No new runtime dependency beyond the package itself, no new service, no new datastore. It coexists with existing Nova resources as a field, which means it inherits Nova's auth, middleware, and layout for free.
  • It is additive: nothing existing is modified to adopt it. That makes the change reversible at the same granularity it was introduced — per-field, per-resource.
  • Where the stack already has a mutation convention (Nova Actions with policies and audit), URL buttons are the low-risk default and Action buttons are the correct default for anything that mutates state. Ad-hoc POST /admin/{resource}/{id}/do-thing controller endpoints per button are the anti-pattern to prohibit explicitly in the team conventions doc.

Migration path

  • There is no migration in the data sense — no schema, no backfill, no dual-write. "Migration" here is inventory: enumerate the existing ad-hoc admin affordances (manual runbooks, Slack-driven ops requests, links bookmarked in a wiki) that this replaces, and convert them one at a time.
  • Exit path is equally cheap and should be documented before adoption: internal wrapper class → single-file rewrite → either fork under MIT or reimplement. Capping downside this way is what makes the vendor bet sizeable rather than scary.

Compatibility

  • Pin the package tag and the Nova major together. Treat the pair as a composite dependency in the upgrade runbook, not two independent composer update outcomes.
  • Verify fluent method names against vendor/sietse85/nova-button/src/ at the pinned tag, not against the README or memory. The README documents a snapshot, not a contract; the source is authoritative.
  • Verify the rendered button's keyboard focus and screen-reader labeling during the spike. If the shipped component misses it, fix it once in the internal wrapper — that is what the wrapper is for.

Sequencing

  1. Spike, read-only. One non-destructive button on a detail view ("Open in Stripe", "View invoice PDF"). Proves rendering, URL generation, and the click path with zero blast radius.
  2. Wrapper class. Land ActionButton before the second usage so no call site ever references the vendor class.
  3. Conventions doc. Write the button/Action/Tool boundary and the "no ad-hoc mutation routes" rule while context is fresh.
  4. First mutating button, wired to a Nova Action — not a bespoke endpoint — with a consequence-statement confirmation ("This overwrites local records"), a canSee policy gate, and server-side idempotency.
  5. Catalogue trait. Once past ~5 buttons, merge them through a single operatorButtons() method so there is one file to review at Nova-upgrade time and one file to hand a security reviewer.
  6. Scale-out. Remaining affordances convert opportunistically as backend endpoints land — which is the point: the gating dependency becomes backend readiness, not front-end sprint capacity.

Operational Impact

Maintenance

  • One file (the wrapper), one trait (the catalogue), one pinned version pair. Total ongoing load is a per-Nova-upgrade review, not continuous maintenance. Assign a named engineer anyway; unowned is the actual failure mode.
  • Upgrades are paired and deliberate: Nova bump + package bump in one commit, followed by a staging smoke of one index page, one detail page, one button click, and a browser console check. That checklist is the entirety of the maintenance ceremony and should live in the runbook.
  • Keep a light vendor watch. If the maintainer disappears, MIT guarantees you can fork; the wrapper guarantees the fork is one file. Neither requires action today, but both require knowing who would act.

Support

  • No vendor SLA. Single maintainer, community OSS, no commercial backing. Internal support is you. That is acceptable at this surface size and unacceptable if the button fleet quietly becomes load-bearing for revenue-adjacent ops workflows without anyone noticing — which is why the catalogue matters.
  • Ops teams iterate on button copy (labels, confirmation wording, visibility) constantly. Because it lives in PHP next to the fields, that iteration is a PR, not a design cycle — a genuine velocity gain, but it also means product and ops can change mutation affordances without engineering review unless the PR conventions say otherwise.

Scaling

  • Index placement is the scaling trap. Buttons render per row: 50 rows = 50 interactive elements, plus DOM weight, plus visual noise. Reserve index placement for a single high-frequency read-only affordance and keep mutating buttons onlyOnDetail().
  • canSee closures that dereference relationships will produce N+1s on index views at scale. Either eager-load in indexQuery or restrict to detail.
  • Anything that is not instant must be queued. A synchronous 30-second ERP sync behind a button will time out, and an impatient operator will click it three more times. Route through a queued Action or job, surface queued/running/complete state, and make the confirmation copy say "runs in the background" if the UI cannot show progress.

Failure modes

Failure Signal Mitigation
Nova upgrade breaks the component Blank cell / console error, no 500 Post-upgrade staging click-through checklist
Backing route renamed Silent 403/404 invisible to operator Button→endpoint mapping doc; server-side click logging
Double-click on non-idempotent action Duplicate side effects Server-side guard: status check, job key, lock
Policy drift Button shown/hidden incorrectly Field test asserting canSee returns expected value per model/user; route test for 401/403
Unreviewed dist/ asset Supply-chain exposure Rebuild from source in CI and diff, or vendor a reviewed build
  • The unifying property of every row is silence. Nothing here pages anyone. Compensate with explicit tests and a documented manual smoke step, not with monitoring you assume will catch it.

Ramp-up

  • Developer ramp: under a day to first rendered button; the fluent surface (label, icon, classes, confirmation, URL vs. action, canSee, onlyOnDetail) is small enough to learn from source in a sitting.
  • Realistic delivery ramp for a production button: 1–2 days once you include the policy gate, the idempotency guard, and a test. Plan the epic around the backend contract, not the field config.
  • Ops ramp: near zero — it looks like a button. That is simultaneously the benefit and the risk: the affordance is so cheap to add that the discipline (queued long-ops, detail-only mutation, consequence-statement confirmations, no ad-hoc endpoints) has to be enforced socially and in review, because nothing in the tooling will enforce it.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings