spatie/ignition-contracts
Contracts for spatie/ignition that define interfaces for building custom error pages. Provides shared abstractions so solutions can integrate with Ignition’s error reporting and rendering workflow.
Architecture fit
spatie/ignition-contracts is an interface-only package — a handful of PHP interfaces (Solution, RunnableSolution, HasSolutionsForThrowable) plus a BaseSolution abstract class and repository interfaces (SolutionRepository, SolutionProviderRepository). It has no service provider, no config, no runtime logic, no storage, and no dependencies. Architecturally it is a contract boundary, not a component: it belongs at the edge of the dependency graph, pulled in transitively by Ignition, and should only become a direct dependency when we deliberately build custom solution providers.
Integration feasibility
Mechanically trivial: composer require is instantaneous, there is no bootstrapping, and it runs on any PHP 7.1+/8.x runtime Ignition supports. The TPM question is why we would add it. Two legitimate scenarios: (1) authoring custom exception classes or solution providers so domain-specific failures render as actionable fixes in local/staging error pages, and (2) publishing a package that contributes solutions for other Laravel teams. Outside those, it adds no capability we don't already get from spatie/ignition/facade/ignition.
Technical risk
The dominant risk is lifecycle, not code. The contracts have been folded into Ignition under the Spatie\Ignition\Contracts / NunoMaduro\Ignition\Contracts namespaces, so adopting the standalone package means committing use statements to a surface with a known expiry date. Secondary risks: duplicate contract definitions in one process causing instanceof/type-hint mismatches; silent drift in the low-urgency part of the tree; and the reported zero dependents, which conflicts with expected usage in Laravel 8-era facade/ignition trees and warrants verification before any SBOM/inventory decision.
Key questions
Spatie\Ignition\Contracts directly and skip this package.^7.1|^8.0)? PHP 8.3+/8.4 hardening will not come from here.Stack fit
Fits Laravel/PHP applications only as a local-development and debugging affordance — zero bearing on production request handling, queue workers, or API contracts. Teams on Laravel 9+ should treat spatie/ignition as the integration point and this package as legacy. Teams on Laravel 8 or earlier already have it via facade/ignition and should not version-pin it independently.
Migration path
Treat this as a containment item, not an adoption item. Target state: no direct dependency in our composer.json; any custom solution classes authored against Spatie\Ignition\Contracts\* so they survive the transition. If we already have code typed against Spatie\IgnitionContracts\*, migration is a mechanical namespace rewrite plus a constraint bump, gated behind the Ignition major upgrade — a one-PR change with no data migration and rollback limited to reverting the commit.
Compatibility
Constraint surface is narrow and stable (^7.1|^8.0). Because the package is interfaces plus one abstract class, binary compatibility is essentially a non-issue; the only breaking change that matters is the namespace move. Watch for ProvidesSolution vs HasSolutionsForThrowable naming differences across Ignition releases — a class can satisfy one and not the other, producing a silently non-rendering solution rather than an error.
Sequencing
composer.lock and at what version.spatie/ignition contracts first — this usually eliminates the need for the standalone package.^1.0, and flag for removal at the next Ignition upgrade.Maintenance Near-zero in the happy path — interface-only packages cannot fail at runtime in interesting ways. The cost is governance: deprecation tracking, an owner on the framework side who knows the package exists, and a standing rule that it never gets promoted to a direct dependency without review. Realistically a 15-minute-per-quarter line item inside dependency review, not a workstream. If we do emit solutions, add content maintenance on top — keeping commands and config keys accurate as they drift.
Support Community-supported, effectively unmaintained upstream: no vendor SLA, no security response process, no expectation of PHP-version updates. Mitigating factor is that an interface package has almost no attack surface — CVE exposure is bounded by its dependency-free nature. Do not build any workflow that depends on this package receiving releases.
Scaling
Irrelevant to runtime scaling: negligible autoload overhead, no I/O, no measurable memory footprint. The scaling concern is organizational — every direct dependency multiplies dependency-review surface across teams and repos, and this one adds review cost without adding capability. The functional scaling lever is content: one well-authored RunnableSolution for a top failure mode can deflect support tickets at scale, but only if the fix stays accurate.
Failure modes
Spatie\Ignition\Contracts\Solution while our code implements the legacy interface. The error page simply loses its "solution" block. Detect with a smoke test asserting a known throwable renders a solution.instanceof results or type errors in provider repositories.RunnableSolution is used for non-idempotent or destructive commands, the error page becomes a security/operational boundary. Gate to local/dev or require explicit confirmation.Ramp-up Low. A developer familiar with Laravel and Composer can understand the contracts in under an hour; authoring a first solution provider is a half-day including wiring and a test. The steeper learning curve is judgment — deciding which failures deserve solutions, keeping them accurate, and knowing when to stop. Recommend designating one owner for error-UX/DX content and treating the package as a read-only contract surface with no ongoing engineering investment unless a measurable ticket-deflection goal justifies it.
How can I help you explore Laravel packages today?