Open-source project
spatie/ignition avatar
spatie/ignition

Ignition: a readable error page for PHP applications, with fixes attached

A beautiful error page for PHP apps

519 stars63 forksPHPMIT

At a glance

What is it?
Ignition replaces the PHP fatal error screen with a page that shows the stack trace, the request, the environment and, where it can, a suggested solution to the problem. It is a Spatie package with framework wrappers for Laravel, Symfony and Drupal, and a React front end compiled with Tailwind.
Who is it for?
Adopt Ignition if you are building a PHP application and the default error output is slowing you down, since the solution mechanism and the readable stack trace are the payoff. Do not enable it in production, because the README is explicit that the page can display sensitive information, so pass a falsy value to shouldDisplayException.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 77 days ago.
What is it written in?
Mainly PHP, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What Ignition does, and how little it takes to install

Ignition is a beautiful and customizable error page for PHP applications, and the whole package is registered in one line.

php
use Spatie\Ignition\Ignition;

include 'vendor/autoload.php';

Ignition::make()->register();

Then you throw an exception during a web request and the browser shows the Ignition page instead of PHP's default output. There is also a dark mode, and a screenshot of each in the README.

The value proposition is worth stating precisely, because PHP's built-in error output is genuinely poor for development. The default output is a wall of plain text with no structure, no syntax highlighting, no way to see the request that caused it, and no way to know what to do next. Ignition turns that into a page you can read at a glance, which for a full stack developer is the difference between a two minute fix and a twenty minute one.

The package is MIT licensed, the primary language is PHP, the default branch is main, and the last push was on 2026-08-07. The recent releases are 1.16.0 on 2026-03-17, 1.15.1 on 2025-02-21 and 1.15.0 on 2024-06-12, so the 1.x line is stable and still receiving fixes.

The homepage is flareapp.io/ignition, and there is a video on YouTube that demos all of the features, with a note that the design decisions behind them are written up in a separate blog post.

It is worth knowing that Ignition is a Spatie package and that Spatie is a commercial open source shop. The README asks for support, either through buying one of their paid products or by sending a postcard from your hometown, which is a slightly unusual but now fairly well known funding model for a package that many developers will use for free in a hobby project.

Framework wrappers, and why they are separate packages

Ignition is a framework-agnostic PHP package, and the README lists a set of wrappers for the frameworks where you should not install it directly.

For Laravel apps, head over to laravel-ignition. For Symfony apps, go to symfony-ignition-bundle. For Drupal 10 and later websites, use the Ignition module from Drupal.org. For OpenMage websites, use the Ignition module from empiricompany. For all other PHP projects, install the package via Composer.

bash
composer require spatie/ignition

The reason for the split is that each framework has its own way of registering an error handler, its own configuration conventions and its own release cycle. Laravel ships its own error page, so installing Ignition there means replacing that behaviour, and the wrapper package knows how to do it without you having to wire it yourself. The same applies to Symfony's exception handling and Drupal's module system.

The Drupal and OpenMage cases are worth a second look, because they show the range of the ecosystem. A Drupal module is a different packaging model from a Composer library, and OpenMage is a Magento fork, so getting Ignition to work there required somebody to write the glue.

If you are on a plain PHP application, the composer require is the whole installation. The registration line then goes in the bootstrap part of your application, which the README says is typically where you would add it.

The package structure is visible in the top level listing. There is a src/ directory for the PHP code, a resources/ directory holding the front end assets, a tests/ directory, a docs/ directory, and the usual project files: composer.json, phpunit.xml.dist, phpstan.neon.dist with a phpstan-baseline.neon, a .php_cs.php for code style, and a CHANGELOG.md and LICENSE.md.

The PHP tooling is a serious setup. PHPUnit for tests, PHPStan for static analysis with a committed baseline, and a code style fixer, all of which is what you would expect from a package whose job is to display a stack trace well, since it is going to be the first thing a developer sees when something breaks.

Configuration, and the one setting you must not skip

There are four configuration options, and three of them are about presentation while the fourth is about safety.

The first is the application path. When setting the application path, Ignition will trim the given value from all paths, which makes the error page look more clean. The code is:

php
\Spatie\Ignition\Ignition::make()
    ->applicationPath($basePathOfYourApplication)
    ->register();

That is a small thing with a disproportionate effect. Every path in a stack trace is an absolute path into your source tree, so an error page shows the same long prefix on every line. Trimming it makes the trace readable, and it also happens to remove your deployment directory layout from the page.

The second is the theme. By default Ignition uses a white based theme, and if that is too bright you can use dark mode:

php
\Spatie\Ignition\Ignition::make()
    ->setTheme('dark')
    ->register();

The third is the one that matters. You do not want to render the Ignition error page in a production environment, as it potentially can display sensitive information. To avoid rendering it, you call shouldDisplayException and pass it a falsy value:

php
\Spatie\Ignition\Ignition::make()
    ->shouldDisplayException($inLocalEnvironment)
    ->register();

The variable name in the example is the point. The condition is a flag about whether you are in a local environment, and it is passed in from your configuration rather than hard-coded, which is the difference between a flag that actually flips between environments and one that someone set once and forgot.

What the page can display is the reason the warning exists. It shows the stack trace, the source of the failing line, the request that triggered it, the application environment and its variables. Those variables are the sensitive part, because an application environment routinely holds database credentials, API keys and mail server passwords. A stack trace page with your environment dumped on it is a credential disclosure waiting for the wrong person to trigger an error.

The fourth option is less about the page and more about the response, and it is described next.

Solutions: the mechanism that makes the page more than a stack trace

The feature that separates Ignition from a prettier exception page is solutions. In addition to displaying an exception, Ignition can display a solution as well, and out of the box it will display solutions for common errors such as bad method calls or using undefined properties.

There are three ways to add one, and they form a hierarchy.

The most specific is attaching a solution to an exception. To do that, the exception implements the Spatie\Ignition\Contracts\ProvidesSolution interface, which requires one method returning the Solution the users will see when the exception gets thrown:

php
use Spatie\Ignition\Contracts\Solution;
use Spatie\Ignition\Contracts\ProvidesSolution;

class CustomException extends Exception implements ProvidesSolution
{
    public function getSolution(): Solution
    {
        return new CustomSolution();
    }
}

And the solution itself is a plain object with three methods:

php
use Spatie\Ignition\Contracts\Solution;

class CustomSolution implements Solution
{
    public function getSolutionTitle(): string
    {
        return 'The solution title goes here';
    }

    public function getSolutionDescription(): string
    {
        return 'This is a longer description of the solution that you want to show.';
    }

    public function getDocumentationLinks(): array
    {
        return [
            'Your documentation' => 'https://your-project.com/relevant-docs-page',
        ];
    }
}

A title, a longer description and a set of documentation links. The links are the detail that makes it useful, because a solution that says what to do but sends you to a search engine is half a solution.

The middle way is a solution provider, which is the general case. Where exceptions that return a solution provide the solution directly to Ignition, a solution provider allows you to figure out if an exception can be solved. The example given is a custom Stack Overflow solution provider that will look up if a solution can be found for a given throwable. Solution providers can be added by third party packages or within your own application, and a provider is any class implementing the HasSolutionsForThrowable interface:

php
interface HasSolutionsForThrowable
{
    public function canSolve(Throwable $throwable): bool;

    /** @return \Spatie\Ignition\Contracts\Solution[] */
    public function getSolutions(Throwable $throwable): array;
}

The two-step protocol is what makes this composable. When an error occurs, the class receives the Throwable in canSolve, and there you decide whether your provider applies. If you return true, getSolutions is called. So the expensive work, whatever it is, only happens for the throwables you actually handle.

And the registration is a list of class names:

php
\Spatie\Ignition\Ignition::make()
    ->addSolutionProviders([
        YourSolutionProvider::class,
        AnotherSolutionProvider::class,
    ])
    ->register();

The stack overflow provider example makes the value obvious. A provider that recognises a class not found error and looks up the right class name turns a dead end into a two second fix, and because providers are a list of classes, a third party package can add one for a library you use without the core package knowing anything about it.

The AI suggestions, and the front end stack behind the page

The last feature in the README is the one that needs the most care.

Ignition can send your exception to Open AI that will attempt to automatically suggest a solution. In many cases the suggested solution is quite useful, but keep in mind that the solution may not be 100% correct for your context.

The caveat is doing real work there. An exception is a stack trace, and a stack trace is a map of your source code, and sending it to a hosted model means sending a slice of your codebase and your environment to a third party. The README says it in a sentence and a half, which is about the right length for a decision with that shape, but it is a decision the developer has to make deliberately rather than discover later.

The front end is a separate concern and it is worth looking at, because the page you see is built with a modern toolchain rather than being server-rendered templates.

The package.json in the repository is a React and Tailwind project named @flareapp/ignition. The dependencies include @flareapp/ignition-ui at 4.11.0, which is the component library for the error page itself, React and React DOM at 17.0.2, Tailwind CSS at 3.2, the FontAwesome React packages for the icon set, lodash, and react-intersection-observer.

The build is microbundle, with a bundle script that compiles resources/js/index.tsx to resources/compiled/ignition.js as CommonJS, with type generation turned off, and with process.env.NODE_ENV defined as production. There is a bundle-temp variant for development, and a dev script that runs microbundle in watch mode alongside a TypeScript typecheck using concurrently, with the two processes named dev and typescript.

The rest of the front end tooling is a prettier and eslint setup with a postcss config and a tailwind config, a tsconfig for the TypeScript side, and a yarn.lock. The resources/ directory is the compiled asset directory that ships with the PHP package, and the compiled JavaScript is what the server sends to the browser.

The result is that the error page is a small React application that the PHP side serves as a static asset and bootstraps with the exception data. That is why the page can be a rich interface with tabs and interactive elements rather than a table of text, and it is also why the front end and the PHP package version separately, which is a packaging trade you accept in exchange for the interface.

Editorial conclusion

Adopt Ignition if you are building a PHP application and the default error output is slowing you down, since the solution mechanism and the readable stack trace are the payoff. Do not enable it in production, because the README is explicit that the page can display sensitive information, so pass a falsy value to shouldDisplayException. Before you rely on the AI suggestions, read that section, because the README warns the suggestions may not be correct for your context and that sending exceptions to a third party is a decision with privacy implications of its own.

Frequently asked questions

What does the Ignition package do for PHP applications?

It renders exceptions on a styled, customizable error page instead of PHP's default output, and can display a suggested solution alongside the exception. Out of the box it shows solutions for common errors such as bad method calls or using undefined properties.

How do I install Ignition?

For a plain PHP project, run composer require spatie/ignition and register it in your bootstrap with \Spatie\Ignition\Ignition::make()->register(). For Laravel use the laravel-ignition package, for Symfony the symfony-ignition-bundle, and for Drupal 10 or later and OpenMage there are Ignition modules.

How do I stop Ignition from rendering in production?

Call shouldDisplayException with a falsy value, for example ->shouldDisplayException($inLocalEnvironment), because the README warns the page can display sensitive information in a production environment.

What are the two ways to provide a solution to Ignition?

You can make an exception implement the ProvidesSolution interface and return a Solution with a title, description and documentation links, or you can register a solution provider class implementing HasSolutionsForThrowable, whose canSolve method decides whether it applies to a given Throwable before getSolutions is called.

Does Ignition use AI to suggest fixes?

Yes, it can send your exception to Open AI to attempt to suggest a solution, and the README says this is often useful, but warns that the suggestion may not be 100% correct for your context.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. spatie/ignition on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/spatie-ignition.svg)](https://hysenlabs.com/projects/spatie-ignition)

Was this useful?