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

Laravel Ward Laravel Package

kabbouchi/laravel-ward

Ward is a lightweight Laravel package from Kabbouchi that puts a simple guard in front of your application, making it easy to restrict access, protect staging sites, and gate features with minimal configuration and sensible defaults.

Deep Wiki
Context7

Getting Started

Laravel Ward is a lightweight, self-hosted log dashboard: it reads the files in storage/logs, parses Monolog entries into timestamp / environment / level / message / context / stack trace, and serves them through a browsable web UI with filtering, search, and log clearing.

Minimal setup:

composer require kabbouchi/laravel-ward
php artisan vendor:publish --provider="Kabbouchi\Ward\WardServiceProvider"

The service provider is auto-discovered; the publish step gives you config/ward.php. Check the actual publish tag in the package README (--tag=ward-config is the typical convention) if the provider publish above lists multiple groups.

Then:

php artisan route:list | grep -i ward   # confirm the registered route/prefix

and open the dashboard at the configured path (usually /ward). If the page is blank rather than a 404, the route is working and the frontend assets are the problem — see Gotchas.

Where to look first

  1. config/ward.php — path/prefix, enabled flag, middleware stack, and any authorization callback. This is the only file you should need to touch for a normal install.
  2. storage/logs/ — the dashboard is a view over these files. Confirm laravel.log (or your daily files) exists and is readable by the PHP process.
  3. php artisan route:list — verifies registration and shows which middleware protects the dashboard.

First use case

Reproduce a failure locally, open /ward, filter level to ERROR, and click the entry. This is the package's core value: you get the full stack trace, the request context, and the surrounding entries without tail -f in a second terminal or SSH access to a staging box. Compared with Telescope, Ward is retrospective — it works on logs that survived a crash, a queue worker, or a container restart, which is exactly when Telescope's pruned database rows are least useful.

Implementation Patterns

Gate the dashboard by environment and middleware. The default middleware is usually just web, which is fine locally and wrong everywhere else. The cheapest safe pattern:

// config/ward.php
'enabled' => env('WARD_ENABLED', app()->environment('local')),
'middleware' => ['web', 'auth'],

For staging, add a gate in AuthServiceProvider and reference it from a small middleware, or use an IP allowlist at the proxy. Never rely on an unguessable path as the only control.

Route the dashboard next to your existing debugging tools. A practical split in day-to-day work: Telescope for "what did this request do," Ward for "what did this process write and when." Ward remains useful for queue workers, scheduled commands, and php artisan runs that never produce an HTTP request Telescope can record.

Make your logs searchable, because Ward's search is substring-based. The dashboard is only as good as your log lines. Add correlation context where it matters:

Log::withContext([
    'request_id' => $request->header('X-Request-Id'),
    'user_id' => auth()->id(),
    'job' => static::class,
]);

Then searching the request ID or job class in Ward takes you straight to the failure. This is the single highest-leverage integration: it turns a log viewer into a tracing tool.

Daily logs work naturally. Ward scans the log directory, so LOG_CHANNEL=daily gives you a file list you can move between. If you use a single channel, keep an eye on file size (see Gotchas) and truncate deliberately rather than letting it grow to hundreds of megabytes.

Clearing logs as part of a workflow. The clear/delete action is the fastest way to reset noise between reproduction attempts: reproduce → read → clear → reproduce again. For automated tests, do not depend on the dashboard; truncate the file in test setup (file_put_contents(storage_path('logs/laravel.log'), '')) or use a dedicated test log channel so your real logs stay intact.

Custom channels. If you write to a non-default path, confirm Ward's configured log path (or directory scanner) points at it. Channels writing outside storage/logs will silently be invisible otherwise. Laravel's LOG_STACK in 9+ can fan out to multiple channels; Ward shows the resulting files individually, so make sure you are reading the channel that actually receives the entry.

Deployment checklist. Publish config and any public assets during deploy, run php artisan config:cache after publishing, and run php artisan route:cache only after confirming the package's routes are cacheable. In Docker, mount storage/logs as a volume — otherwise the container restart that motivated you to check the logs also deletes them.

Extension points. The practical customization surface is: the config path/prefix, the middleware stack, any authorization hook the config exposes, and published views for branding or removing destructive buttons. If you need a different parser (JSON logs, custom LineFormatter), that is where you will hit the package's limits — plan to fork rather than fight it.

Gotchas and Tips

  • Lock it down before you ship it. A log dashboard exposes stack traces, file paths, SQL, and often secrets in context. Defaults are developer-friendly, not production-safe. Set enabled off in production unless it sits behind real authentication.
  • Permissions are the most common "it shows nothing" cause. php-fpm/www-data writes the log; your browser session reads it through PHP, so the PHP user needs read permission on the file and read/execute on the directory. Conversely, if the web user can write, the clear button works — verify that deliberately rather than discovering it by accident.
  • Large files degrade badly. Parsers that read the whole file into memory will time out or exhaust memory on a multi-hundred-megabyte log. Keep files rotated (LOG_DAILY_DAYS), truncate with : > storage/logs/laravel.log, and treat the dashboard as a tool for recent entries, not archival search.
  • Custom Monolog formatters break parsing. Ward expects conventional single-line Monolog output. JsonFormatter or a LineFormatter with a different format string will produce entries the parser cannot split into level/message/context. If you need structured logs, run a separate channel for the dashboard.
  • Multi-line stack traces are the fragile part. Entries without a trailing newline, or interleaved output from concurrent workers, can merge two entries into one. Correlation IDs in context are the workaround when entries get glued together.
  • Blank page ≠ broken route. If route:list shows the route but the browser renders nothing, the frontend assets were not published or the build manifest is missing. Publish assets as part of deploy; do not assume a dev server is running in production.
  • Stale config after install. config:cache and route:cache can make a newly published ward.php appear ignored. Clear caches (php artisan optimize:clear) before debugging the package itself.
  • Last release is February 2023, so verify framework compatibility before committing. Check the illuminate/* constraint in composer.json; on Laravel 11/12 the resolver may refuse to install. Options: --with-all-dependencies, a constraint override in your root composer.json, or a small fork. Given the package's scope — a route, a parser, and a UI over files — forking is realistic if it becomes load-bearing.
  • Timezone mismatches cause confusing date filters. Monolog timestamps follow the app timezone; your browser may not. If "today" shows yesterday's errors, compare config('app.timezone') against the timestamps in the raw file.
  • Clearing is destructive and irreversible. There is no undo and no audit trail. On shared staging, either disable the clear action (published views or a route-level guard) or make sure a colleague is not mid-investigation.
  • Ephemeral containers. In Kubernetes or ECS, logs vanish on restart. Ward will faithfully show you an empty directory. Ship logs to a volume or a log aggregator; Ward is a convenience layer, not a retention strategy.
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.
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
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin