lara-zeus/rain
Lara Zeus Rain is a Laravel package from the Lara Zeus suite that adds ready-to-use functionality to your apps with minimal configuration. Install it via Composer, publish its assets, and integrate it cleanly into your existing Laravel or Filament project.
First, resolve what the package actually is — before you install it. The evidence you have is contradictory: the repo is lara-zeus/dynamic-dashboard, the marketplace blurb says "widgets for your Filament dashboard / landing page," the bundled description.md describes a generic "lightweight Laravel package," and the only release note is one line: "add support for filament 5." A day-to-day developer needs certainty here, because the API surface of a dashboard compositor and a table/form builder are unrelated. Spend 15 minutes on the repo, not on the marketing copy:
composer show -a lara-zeus/rain # versions + constraints, before touching composer.json
composer require lara-zeus/rain:"^5.0" -W # on a scratch branch only
ls vendor/lara-zeus/rain/src
cat vendor/lara-zeus/rain/composer.json # PHP / Laravel / Filament / Livewire ceilings
cat vendor/lara-zeus/rain/README.md
composer.json is the single highest-value file. It tells you in one shot whether you are on the right Filament major, whether the plugin drags in a Livewire or Tailwind bump alongside it, and whether namespaces changed between 4.x and 5.0.0. The service provider and plugin class are then the entire public surface — a package this size has no hidden API.
Minimal install path (assumes a Filament 5 panel):
composer require lara-zeus/rain:"^5.0" -W
php artisan vendor:publish --tag="rain-config"
php artisan vendor:publish --tag="rain-migrations"
php artisan migrate
php artisan vendor:publish --tag="rain-assets" # only if it ships frontend assets
Register it on one non-production panel and nowhere else:
// app/Providers/Filament/AdminPanelProvider.php
public function panel(Panel $panel): Panel
{
return $panel
->id('admin')
->plugin(RainPlugin::make()); // confirm the class name from src/ first
}
Then hit /admin. If the panel still boots and one DB-backed widget action works, you have exercised registration, routing, authorization, and asset loading in a single smoke test.
Where to look when the docs run out — and they will, this package is small enough that source is the documentation. In order: src/*ServiceProvider.php → src/*Plugin.php → config/rain.php → resources/views/ (publish these; reading the shipped Blade is the fastest way to learn the widget API) → database/migrations/.
First real use case. Do not start with the landing page. Start with the screen you would otherwise hand-build: a role-scoped summary dashboard — three stat cards, one chart, one recent-records list. That exercises widget registration, layout persistence, and per-user configuration in a day. The public/landing-page rendering path is a different problem (caching, SEO, anonymous users) and may not even be what this package solves — keep it out of the spike.
Wrap the plugin in an app-owned registry before it leaks everywhere. Even if you use the package directly, put widget definitions behind a class you control:
final class DashboardWidgets
{
public static function for(User $user): array
{
return collect(config('app.widgets'))
->filter(fn ($w) => Gate::allows('view-widget', $w['key']))
->all();
}
}
This is the seam you swap, fork, or inline behind when the package lags a Filament major. Without it, package class names end up in forty places and an upgrade becomes a refactor.
Decide authoring vs. rendering up front — it changes the data model. For a Filament dashboard, authoring and delivery are the same surface: one panel, one config model. For a landing page, authoring lives in the admin panel but rendering happens on a public route, usually from a JSON layout column. Model the persisted layout as data you own (dashboard_layouts / widget_settings with user_id, panel, payload json), not as whatever schema the package ships — that is the artifact you will need to export when you migrate off. Always ship default and reset actions; users will destroy their layouts within a week.
Scope widgets per panel explicitly, from day one. The most common production bug in dynamic-dashboard plugins is a widget leaking onto a panel it was never meant for:
public function register(Panel $panel): void
{
if ($panel->getId() !== 'admin') {
return;
}
// ...
}
Do this before a client sees an internal revenue chart on a public page, not after.
Local dev loop. Filament plugin work has a specific cache-clearing rhythm worth aliasing:
php artisan filament:assets && php artisan view:clear && php artisan config:clear
Publish views before you need to change them. Editing in vendor/ is a trap — the next composer update silently reverts you.
Seed defaults programmatically, not by clicking through staging. A seeder that creates the default layout per role makes new-environment setup reproducible and gives you a rollback shape when the layout schema changes.
Test the integration you own, not the package. With 16 stars and no visible CI, assume there is no test suite. Add exactly two tests: (1) the panel boots and the dashboard route returns 200 for a permitted user; (2) it returns 403 for an unpermitted one. Those two catch roughly 80% of the breakage you will hit on every Filament bump.
Pin with a tested ceiling, and commit the lock.
"lara-zeus/rain": "^5.0.3"
Not ^5.0, not 5.*. With zero dependents there is no crowd to discover a broken patch release for you.
The version boundary is the whole decision. 5.0.0 exists solely to add Filament 5. If you are on Filament 3 or 4, this is not "a package install" — it is a stacked major upgrade (Filament + Livewire + Tailwind + this plugin) where defect attribution becomes guesswork and rollback is ambiguous. Sequence it: Filament upgrade first, stabilize, then add the plugin. Never in one PR.
"Adds support" ≠ "additive." Expect the 4.x → 5.0.0 diff to have dropped older Filament majors and possibly renamed namespaces, config keys, or the plugin registration class. Diff the published config after upgrading — a stale config/rain.php carrying a removed key is a silent misconfiguration, not an error.
The description mismatch is a real build-vs-buy risk, not a doc nit. If the code turns out to be a table/form builder rather than a dashboard compositor, the math inverts: a table builder overlaps Filament's own table system, and inlining becomes cheaper than tracking its majors. Verify in the source.
Asset pipeline. If the package ships Blade + Tailwind classes that are not in your compiled CSS, widgets render unstyled and look "broken" while nothing throws. Either publish the views and add them to your tailwind.config.js content globs, or run the package's own build. This reliably costs people an afternoon.
Query amplification. Dashboards compound queries: six widgets × an N+1 inside each = a slow, memory-hungry admin page nobody profiles because "it's just the dashboard." Wrap widget data loading in Cache::remember() keyed by user/role/date-bucket, and use withCount / with aggressively inside any widget that lists records.
Widget config is user-editable data — treat it as untrusted. If layouts are stored as JSON and rendered, no {!! !!} on user-supplied labels, no arbitrary class names, no query parameters passed through. An admin panel is a high-privilege surface; a layout editor that accepts a raw SQL fragment or a Blade string is a privilege-escalation path.
Authorization may not be wired. Verify the plugin respects Filament policies and panel access. Do not assume a widget running Invoice::all() is scoped for a non-admin role — gate widget registration yourself.
Blank-widget debugging checklist, in order: php artisan config:clear (stale config) → component name in resources/views/ vs. what is registered → Tailwind content globs (invisible-but-present markup) → storage/logs/laravel.log for swallowed Livewire exceptions. If the exception originates in vendor/, temporarily dd() in the package source; with a package this small, reading the source is the documentation.
Own a fork path before you need it. Zero dependents, solo maintainer, releases chained to Filament's majors. Mitigations: pin exactly, keep the app-owned registry seam above, and know how to add a "repositories": [{"type": "vcs", ...}] fork entry. State in the PR description that if the package lags a Filament release, you self-maintain. Cheap sentence now, expensive surprise later.
Extension points, in order of stability: your own widget classes → published views → the plugin config → subclassing the package's registry. Extend at the highest level that works; each layer down increases the chance a minor bump breaks you.
How can I help you explore Laravel packages today?