whilesmart / eloquent-admin
Shared measurements, user directory and automatic email templates for Laravel applications.
Requires
- php: ^8.2
- laravel/framework: ^11.0|^12.0
- whilesmart/eloquent-engagement: ^1.0
- whilesmart/eloquent-owner-access: ^1.0
- whilesmart/laravel-user-authentication: ^1.0
Requires (Dev)
- fakerphp/faker: ^1.24
- laravel/pint: ^1.22
- orchestra/testbench: ^9.0|^10.0
- whilesmart/eloquent-entitlements: ^2.1
- whilesmart/entitlements-cashier: ^0.4
Suggests
- whilesmart/eloquent-entitlements: Free passes on the discounts page (^2.1)
- whilesmart/entitlements-cashier: Stripe discount codes on the discounts page (^0.4)
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-23 08:52:38 UTC
README
Shared administration APIs for Laravel applications. It provides measurements, a user directory, and a registry-backed automatic email template system while leaving authorization, user fields, and product-specific sections to the host.
Host configuration
return [ 'route_prefix' => 'api/v1/admin', 'route_middleware' => ['api', 'auth:sanctum', 'role:admin'], 'user_model' => App\Models\User::class, 'owner' => ['type' => 'platform', 'id' => 0], 'templates' => [ 'welcome' => [ 'name' => 'Welcome email', 'description' => 'Sent after registration.', 'subject' => 'Welcome, {{first_name}}', 'body' => 'Your account is ready.', ], ], ];
The host binds OwnerAuthorizer to protect the configured admin owner. Product-specific user fields belong in a custom API resource or user provider.
Measurements are registered through whilesmart/eloquent-engagement. Every registered metric provider is returned by the admin metrics endpoint and can be rendered by the companion Nuxt layer.
use App\Engagement\OrdersMetricProvider; return [ 'providers' => [ OrdersMetricProvider::class, ], ];
Each provider implements Whilesmart\Engagement\Contracts\MetricProvider and returns count, sum, ratio, series, or ranking metrics. Adding a provider automatically adds its measurements to the shared admin page.
PostHog
Share a PostHog dashboard publicly (Share, then turn on sharing) and set its
embed address, https://us.posthog.com/embedded/<id>, and the console shows it
on its PostHog page. Anyone holding that address can read the dashboard, so it
is returned only to the configured owner, and only when it is the https address
of a shared dashboard.
return [ 'posthog' => ['dashboard_url' => env('ADMIN_POSTHOG_DASHBOARD_URL')], ];
Optional pages
GET features tells the console which optional pages this host serves, so it
offers only pages that load. Feedback is on once whilesmart/eloquent-feedback
serves its routes under the console's prefix; PostHog is on once a shared
dashboard is set.
Offers
A discount is stored differently in every product, so the console asks a provider rather than a table. Register one and the discounts page lists what it holds and renders a form from the fields it declares.
return [ 'offer_providers' => [ App\Billing\CouponOfferProvider::class, ], ];
use Whilesmart\Admin\Contracts\OfferField; use Whilesmart\Admin\Contracts\OfferProvider; use Whilesmart\Admin\Support\Offer; class CouponOfferProvider implements OfferProvider { public function key(): string { return 'coupons'; } public function label(): string { return 'Coupons'; } public function fields(): array { return [ new OfferField('code', 'Code', required: true), new OfferField('percent_off', 'Percent off', 'number', required: true), new OfferField('expires_at', 'Expires', 'date'), ]; } public function all(): array { /* Offer[] */ } public function create(array $attributes): Offer { /* ... */ } public function revoke(string $id): void { /* ... */ } }
Offer::$value is already formatted, because only the provider knows whether
20 means a percentage, pennies or seats. Revoking stops an offer being redeemed
again and leaves redemptions already made standing.
Registering no provider is a supported state: the endpoint answers with an empty list and the page says so.
Two providers ship with the console, each needing its billing package:
| Provider | Package | What revoking does |
|---|---|---|
Whilesmart\Admin\Offers\StripePromotionCodes |
whilesmart/entitlements-cashier |
Stops the code and takes it off subscriptions already carrying it |
Whilesmart\Admin\Offers\FreePasses |
whilesmart/eloquent-entitlements |
Ends the person's free plan at once |
The page heads its table for discount codes. A provider whose offers are
something else, such as a plan given to a person, names the columns it fills
with a columns() method, and the ones it leaves out are hidden:
public function columns(): array { return ['code' => 'Person', 'value' => 'Plan', 'until' => 'Until']; }