PHPackages                             dirop1/frankendash - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. dirop1/frankendash

ActiveLibrary

dirop1/frankendash
==================

A secure, dependency-free Laravel dashboard for FrankenPHP metrics, logs, and Horizon.

00PHPCI passing

Since Jul 30Pushed todayCompare

[ Source](https://github.com/dirop1/frankendash)[ Packagist](https://packagist.org/packages/dirop1/frankendash)[ RSS](/packages/dirop1-frankendash/feed)WikiDiscussions main Synced today

READMEChangelogDependenciesVersions (1)Used By (0)

Frankendash
===========

[](#frankendash)

A small, secure Laravel dashboard for applications running on FrankenPHP. Frankendash reads curated Prometheus metrics from Caddy's **fixed loopback endpoint**, displays stable frankenbase runtime/watchdog status, tails bounded Laravel log files, optionally records metric history, and reports or controls Laravel Horizon when available.

- PHP 8.2+
- Laravel 12 or 13
- No Node, Vite, frontend framework, or required database table
- Disabled and authorization-denied by default

Install
-------

[](#install)

```
composer require dirop1/frankendash
php artisan frankendash:install
```

Laravel package discovery registers the service provider. Define both abilities in an application service provider before enabling the package:

```
use Illuminate\Support\Facades\Gate;

Gate::define('viewFrankendash', fn ($user) => $user->is_admin);
Gate::define('manageFrankendash', fn ($user) => $user->is_admin && $user->can_manage_infrastructure);
```

Then set the strict runtime flag:

```
FRANKENDASH_ENABLED=true
```

Only the literal lowercase value `true` enables Frankendash. A missing or malformed runtime value fails closed. Missing Gates always deny access. The default URL is `/frankendash`.

Frankendash routes are registered even while disabled so Laravel's route cache remains valid. The first package middleware resolves the enabled state for every request; disabled routes return 404. If deployment builds cached configuration before runtime environment injection, the runtime `FRANKENDASH_ENABLED=true` value overrides the cached setting.

Configuration
-------------

[](#configuration)

Publish `config/frankendash.php` with the install command. It controls:

- dashboard path, read/manage Gate names, and additional route middleware;
- short metrics timeout, response/sample bounds, and cache duration;
- relative directories beneath `storage/logs`, allowed extensions, and tail size;
- optional history collection interval and retention;
- opt-in Horizon controls.

The Caddy URL remains `http://127.0.0.1:2019/metrics`. It cannot be redirected to user input or another host. Frankendash uses a direct bounded loopback socket request, follows no redirects, and uses no HTTP proxy. It never exposes Caddy's admin endpoint.

Likewise, frankenbase runtime paths are fixed and are not configuration options: `/etc/frankenbase/version` and `/run/frankenbase/watchdog.json`. Reads are size-bounded and fail closed for symlinks, non-regular files, malformed values, invalid schema-v1 types/states/timestamps, or unsupported schemas. A missing file is presented as a legacy or non-frankenbase environment instead of failing the dashboard.

The `web` middleware is always retained for session authentication and CSRF protection. Configured middleware is additional.

Optional metric history
-----------------------

[](#optional-metric-history)

Live metrics need no database. To enable persisted charts:

```
php artisan vendor:publish --tag=frankendash-migrations
php artisan migrate
```

Then set:

```
FRANKENDASH_HISTORY_ENABLED=true
```

The migration is publish-only and is never loaded automatically. When Frankendash and history are both enabled, the package schedules `frankendash:collect` at the configured interval and `frankendash:prune` daily. The commands may also be run directly. Only curated aggregates are stored.

Request rates are derived when snapshots are read, so no migration or stored JSON rewrite is required. The first point, a non-positive time interval, a missing counter, or a counter decrease/reset produces an unavailable rate rather than a negative value.

The curated snapshot includes FrankenPHP worker/thread totals, ready/busy workers, separate regular and worker queue depths, worker request/crash/restart/request-time counters, Caddy in-flight requests, and process start time when those families are present. Worker utilization and process uptime are derived only from valid denominators/timestamps. Worker queue depth remains summed across labeled worker samples.

After changing cached environment/configuration, rebuild the application's configuration cache and restart long-running FrankenPHP workers.

Laravel logs
------------

[](#laravel-logs)

The viewer only lists configured regular files beneath the application's canonical `storage/logs` directory. Paths are relative, file extensions are allowlisted, reads are tail-bounded, and traversal or symlink escapes are rejected. Content is escaped by Blade.

Caddy, Horizon, scheduler, Supervisor, and container stdout/stderr are **not** available through this viewer. Use your platform's logging backend for those streams.

Horizon
-------

[](#horizon)

Horizon is optional and is never required by Composer. The page distinguishes installation, strict runtime enablement (`HORIZON_ENABLED=true`), and responsive master supervisors.

Controls are off by default. Set `FRANKENDASH_HORIZON_CONTROLS=true` and define the manage Gate to permit pause, continue, or graceful terminate actions. Every action is POST-only, CSRF-protected, throttled, requires typed confirmation, uses a fixed supported Horizon Artisan command, and writes an audit log. Frankendash never accesses Supervisor or executes user-controlled commands.

Security
--------

[](#security)

Every dashboard, JSON, asset, log, Horizon status, and Horizon action route passes enabled and read-Gate middleware. Actions additionally pass the manage Gate. Sensitive responses use `no-store`, CSP, frame denial, and MIME-sniffing protection.

Please report vulnerabilities according to [SECURITY.md](SECURITY.md). Do not expose the Caddy admin listener beyond loopback.

Development
-----------

[](#development)

After intentionally installing development dependencies:

```
composer validate --strict
vendor/bin/phpunit
```

The test suite covers default-denied access, strict runtime resolution, Gate behavior, method safety, curated Prometheus parsing/cardinality, and bounded/traversal-safe log reads. Network and full Laravel/Horizon integration tests require a prepared application environment; package installation does not run them automatically.

License
-------

[](#license)

MIT. See [LICENSE](LICENSE).

###  Health Score

20

—

LowBetter than 12% of packages

Maintenance65

Regular maintenance activity

Popularity0

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity11

Early-stage or recently created project

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://www.gravatar.com/avatar/75e4818f80b427e3a40fad9961b3c99e27725c623267ebee632f953917418ece?d=identicon)[dirop1](/maintainers/dirop1)

### Embed Badge

![Health badge](/badges/dirop1-frankendash/health.svg)

```
[![Health](https://phpackages.com/badges/dirop1-frankendash/health.svg)](https://phpackages.com/packages/dirop1-frankendash)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
