Download the PHP package freshwaveonline/janitor without Composer

On this page you can find all versions of the php package freshwaveonline/janitor. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package janitor

Janitor

Informative, white-label error pages for Laravel.

tests static analysis latest version

Laravel's default error pages show a status code and one line of text. That is enough for a developer and almost useless for the person who hit the error.

This package replaces them with pages that actually explain the situation: what happened, why, what to do next, a button that does it, and — when something went wrong on your side — a short code the visitor can quote so you can find that exact error in your logs.

Why

Installation

Requirements: PHP 8.2+ and Laravel 12 or 13.

Laravel 13 requires PHP 8.3+, so PHP 8.2 pairs with Laravel 12 only. Laravel 11 is not supported.

To pin the major explicitly:

The package registers itself through Laravel's auto-discovery and starts rendering immediately.

Installing from a private fork or a mirror If you run this from a repository of your own rather than from Packagist, point Composer at it directly. In the **consuming application's** `composer.json`: Composer needs credentials for the private repository. Either a GitHub token with `repo` scope: or SSH, by using `[email protected]:freshwaveonline/janitor.git` as the `url` and relying on your existing SSH key. On a deploy server, use a machine user or a deploy key rather than a personal token. To track the branch rather than a release, require it directly — `dev-main` is aliased to `2.0.x-dev`:

For local development

To work on the package and the application side by side, use a path repository. Composer symlinks the directory, so edits are picked up without reinstalling:

Releasing a version

Composer resolves versions from git tags, so cutting a release is a tag:

That runs the release workflow, which validates composer.json with composer validate --strict, runs the suite against both supported Laravel majors, and publishes a GitHub release with generated notes only if all of that passes. The Packagist GitHub App picks the tag up from there, and the update changelog workflow writes the release notes back into CHANGELOG.md.

Configuring

To tune the package, publish the config:

or publish assets individually:

Quick start

Four environment variables cover most projects:

Then look at every page without breaking anything:

The preview lists all eighteen states and accepts ?theme=dark, ?details=1, ?retry=120, ?modal=1 and ?position=top-right.

What you get

Message numbers

The number is derived from a normalised app/Http/Controllers/OrderController.php:88 fingerprint — never from the message, the timestamp or the user. That means:

OriginStrategy::Application is the default and usually the right one: a QueryException thrown deep inside Illuminate still fingerprints to the line in your code that caused it.

Set JANITOR_SALT in production. Without it, someone who can trigger errors could confirm a guessed file path by comparing hashes. Keep the salt stable — changing it changes every number you have ever quoted.

Request IDs

Read from X-Request-Id, X-Correlation-Id, X-Amzn-Trace-Id, X-Cloud-Trace-Context, CF-Ray or W3C traceparent — AWS, Google Cloud and traceparent formats are unwrapped to the bare trace id. When nothing upstream supplied one, the package generates it at the start of the request, so the id on the page matches the id in every log line for that request.

Header values are length-capped and character-validated before they reach the page; anything unusual is replaced by a generated id rather than echoed back.

Retry-After

For 429s, maintenance mode and any exception carrying a Retry-After or X-RateLimit-Reset header, the page shows when to come back:

When to try again — You can try again at 14:32. (04:12)

The countdown ticks live and the retry button is disabled until it reaches zero. Waits longer than retry_after.max_seconds (a day by default) show no countdown at all, because "try again in three days" is not something a visitor can act on.

Call-to-action buttons

Configured per status code, from built-ins (home, back, reload, retry, login, support, status_page) or inline definitions:

An action that cannot resolve removes itself: no support address configured means no support button, no login route means no sign-in button. Exactly one button always carries the primary emphasis.

The 500 page

On a 500 the page can show the exception, formatted and copyable:

Auto shows it when app.debug is on or when the current environment is in the list. That is the useful case: on staging (debug=false, env=staging) testers get a full stack trace and a Copy report button that puts the message number, request id, URL, exception and trace on the clipboard in one click — while production shows nothing.

replace_debug_page is off by default, so locally you keep Ignition. Turn it on to design against these pages.

The copied report contains only what is deliberately put in it — never request bodies, headers, session data or environment variables.

Livewire

An error during a Livewire round-trip normally drops Livewire's iframe overlay over your page. Instead:

Modal renders the same information as a pop-up and leaves the page — and whatever the user had typed — completely intact. ModalPosition has nine values: TopLeft, TopCenter, TopRight, MiddleLeft, Center, MiddleRight, BottomLeft, BottomCenter, BottomRight. Center gets a backdrop; the rest behave as toasts.

The handler is injected automatically when Livewire is installed. To place it yourself, set inject_assets to false and add @janitorScripts to your layout.

Filament

If Filament is installed, an error inside a panel inherits the panel's brand name, logo, primary colour, home URL and login URL:

Everything you set explicitly in this package's config wins over Filament. Every call into Filament is guarded, so a Filament upgrade that renames a method turns into "no branding inherited", never into a 500 on your error page.

Colours, light and dark

You configure one colour. The package derives the hover state, the active state, the soft background, the border, the focus ring and the readable text colour on top of it, for both schemes:

light and dark exist for brand colours that work on white and vanish on near-black. When they are empty, primary is used for both.

With auto_contrast on, a primary colour that fails WCAG contrast against its own surface is nudged lighter or darker until it passes — a pale yellow brand colour still produces a readable button instead of an invisible one.

Everything else is neutral grey. That is deliberate: the pages stay white-label until you give them a colour.

Translations

English and Dutch ship with the package. Copy resolution falls back from the status code to the family to the default, so you only translate what differs:

Each status has title, message, reason, explanation and suggestions, with :status, :brand, :message_number and :support_email placeholders.

API responses

Requests that expect JSON get the same information in a machine-readable shape:

Customising the views

Every blade file lands in resources/views/vendor/janitor/. Laravel's namespaced view finder checks that directory first, so a published file wins immediately — no config, no registration. Delete a file to fall back to the packaged version.

There are three levels of override, and you pick the smallest one that does the job:

One partial. Change the meta chips and keep everything else:

The whole page. Replace error.blade.php and lay the page out yourself:

One status code. Add errors/{code}.blade.php under the published directory and only that status gets the bespoke page:

Every view receives the same $error object (FreshwaveOnline\Janitor\Data\ErrorContext):

Property What it holds
$error->statusCode 404
$error->title / ->message translated headline and lead
$error->reason / ->explanation the "what happened" block
$error->suggestions list<string>
$error->actions() list<ErrorAction> — label, url, icon, style, behaviour
$error->messageNumber / ->requestId the quotable codes
$error->retryAt / ->retryInSeconds() the retry moment
$error->details ExceptionDetails or null
$error->branding Branding — name, logo, homeUrl, supportEmail, …
$error->palette resolved colour tokens for both schemes
$error->copyReport() the plain-text support report

The error inside your own layout

The card is then rendered into your layout's content section instead of as a standalone document.

Extending

Every moving part is bound by contract, so you replace one piece from your own AppServiceProvider and the rest of the package keeps working around it.

Contract Default Replace it when
MessageNumberGenerator MessageNumber you already have an incident-code scheme
RequestIdResolver RequestId your APM assigns the id
RetryAfterResolver RetryAfter the moment comes from a deploy window or queue depth
BrandingResolver ConfigBranding branding is per tenant, not per app
ActionResolver ActionFactory the buttons depend on runtime state
ErrorContextBuilder ErrorContextFactory the copy lives in a CMS, not in lang files
ErrorRenderer ErrorPageRenderer you want different take-over rules

The multi-tenant case, which is the one that comes up most:

The concrete classes stay bound under their own names, so you can decorate the default instead of replacing it wholesale:

ErrorContextFactory and ErrorPageRenderer are non-final with protected methods throughout, so subclassing one method is often enough:

Custom icons

Icons are SVG path data, so they are registered rather than configured:

Registering an existing name replaces that bundled Heroicon everywhere. Any registered name can then be used from the actions config.

Keeping Laravel's behaviour

resources/views/errors/404.blade.php in your application wins — the package steps aside for any error view you wrote yourself. Turn that off with views.prefer_application_views.

To disable the package for specific codes or exceptions:

Validation and authentication exceptions are excluded by default because Laravel redirects for them — hijacking those would break every form and every login redirect in your application. The one exception: when your app has no login route, handle_missing_login_route renders a proper 401 page instead of letting Laravel throw a RouteNotFoundException and turn it into a 500.

Abort messages

That message is shown to the visitor, because you wrote it. Framework-generated messages are not: 404 and every 5xx are excluded by default, so a ModelNotFoundException cannot leak your model class names onto the page.

Testing

PHPStan runs at level: max with no baseline, and the package's own config directory is analysed alongside src. Larastan and phpstan/phpstan-deprecation-rules are registered by phpstan/extension-installer, so they must not also be listed under includes: in phpstan.neon.dist — PHPStan aborts with "These files are included multiple times" before analysing anything.

Contributing

Pull requests are welcome. Please run composer check before opening one — it runs the same four things CI does: composer validate --strict, Pint, PHPStan and Pest.

CI runs the suite against every supported pairing, on both the lowest and the highest resolvable dependencies:

PHP Laravel 12 Laravel 13
8.2 ✅ —
8.3 ✅ ✅
8.4 ✅ ✅
8.5 — ✅

CI never rewrites your code. If Pint reports a violation, the check fails and asks you to run composer format locally.

Security

If you discover a security issue, email [email protected] rather than opening a public issue.

Credits

License

The MIT License (MIT). See LICENSE.md.


All versions of janitor with dependencies

PHP Build Version
Package Version
Requires php Version ^8.2
illuminate/console Version ^12.0|^13.0
illuminate/contracts Version ^12.0|^13.0
illuminate/http Version ^12.0|^13.0
illuminate/support Version ^12.0|^13.0
illuminate/view Version ^12.0|^13.0
nesbot/carbon Version ^3.8.4
symfony/http-kernel Version ^7.2|^8.0
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package freshwaveonline/janitor contains the following files

Loading the files please wait ...