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

Hexa Lite Laravel Package

hexters/hexa-lite

Hexa Lite is a lightweight admin panel package for Laravel that speeds up backend development with ready-made CRUD scaffolding, user and role management, and a simple, configurable UI—ideal for quickly building dashboards without heavy dependencies.

View on GitHub
Deep Wiki
Context7

Getting Started

Hexa Lite is a thin Filament plugin on top of spatie/laravel-permission. Treat it as a UI + scaffolding layer, not a permission framework of its own — the day-to-day work is still Spatie roles, permissions, and gates, just with a Filament screen to manage them.

Minimal setup:

  1. composer require hexters/hexa-lite
  2. Run the package installer and publish migrations/config. The package ships an install command; confirm the exact name in your version with php artisan list | grep hexa (typically php artisan hexa:install, sometimes combined with vendor:publish --tag=hexa-lite-config / --tag=hexa-lite-migrations).
  3. php artisan migrate — this creates the Spatie tables (roles, permissions, model_has_roles, model_has_permissions, role_has_permissions) if they don't already exist.
  4. Register the plugin in the panel provider you actually want the UI in:
    public function panel(Panel $panel): Panel
    {
        return $panel
            ->plugin(\Hexters\HexaLite\HexaLitePlugin::make())
            // ...
    }
    
  5. Ensure your User model uses Spatie\Permission\Traits\HasRoles.
  6. Log in as a user, open the panel — you should see a Roles resource. Create a role, tick permissions, assign it to yourself.

Where to look first:

  • config/hexa-lite.php (or hexa.php depending on version) — this is where the guard, roles/permissions model bindings, and any UI toggles live. Read it before writing code; it explains which guard is assumed.
  • vendor/hexters/hexa-lite/src/ — the package is small enough (93 stars, single-maintainer) to read end-to-end in ~15 minutes. Do this before building anything non-trivial; you will hit undocumented behavior and the source is the real docs.
  • Your PanelProvider — confirm the plugin is only registered where intended.

First real use case: take one existing Filament resource (PostResource), add a PostPolicy, and gate viewAny/create/update/delete on permissions you created in the Hexa UI. That single loop — create permission in UI → assign to role → enforce in policy → verify as a non-admin user — is the whole package in miniature.

Implementation Patterns

Permission naming: pick a convention and stick to it. Hexa Lite will happily store edit_posts, PostResource.update, and posts.update side by side. Pick one (I recommend resource.action or Spatie's posts.update) and enforce it in code review. The UI is free-form; drift is your problem, not the package's.

Enforce in policies, not in resources. Filament resources call policy methods (viewAny, create, update, delete, deleteAny, restore) automatically. Put $user->can('posts.update') in the policy and let Filament do the rest — buttons and nav items hide themselves. Avoid overriding canViewAny() on the resource directly; you lose the policy caching and the ability to test in isolation.

class PostPolicy
{
    public function viewAny(User $user): bool { return $user->can('posts.view'); }
    public function create(User $user): bool  { return $user->can('posts.create'); }
    public function update(User $user, Post $post): bool
    {
        return $user->can('posts.update') && $post->author_id === $user->id;
    }
}

Super-admin bypass via Gate::before, not a magic role check. The standard Spatie pattern works fine alongside Hexa Lite:

// AppServiceProvider::boot()
Gate::before(fn (User $user) => $user->hasRole('super-admin') ? true : null);

Returning null (not false) is essential — false short-circuits every other check.

Seed roles idempotently. The panel is for humans; the baseline roles should be in code so fresh environments and CI are deterministic.

$permissions = ['posts.view', 'posts.create', 'posts.update', 'posts.delete'];
foreach ($permissions as $name) {
    Permission::findOrCreate($name, 'web');
}
$admin = Role::findOrCreate('admin', 'web');
$admin->syncPermissions($permissions);

Run this after migrations, and make it safe to re-run (findOrCreate, syncPermissions, never create).

Assign roles at the boundary, not inside Filament. Registration, invitation acceptance, SSO callback, and admin tooling are the places to call $user->assignRole(...). Keep role-assignment logic in one service/action class so it's testable without booting Filament.

Multi-panel, one database. If you have admin and app panels, registering the plugin in only admin is usually correct — the roles are global but the management UI belongs in one place. Registering in both gives you two UIs over the same tables; harmless but confusing for operators.

Compose with existing authorization. If you already use Laravel policies with plain $user->can(), Hexa Lite slots in with no changes — it's just the admin surface for Spatie. If you already use Filament Shield or another role UI, pick one. Two plugins writing the same Spatie tables will fight over permission naming and cache invalidation.

Gotchas and Tips

Permission cache is the #1 source of "I gave them the role and it didn't work." Spatie caches permissions; new permissions created via the UI usually refresh, but seeders, deploy scripts, and raw DB edits frequently don't. When in doubt: php artisan permission:cache-reset. Add it to your deploy script after migrations. php artisan optimize:clear also works but nukes more than you need.

Guard mismatches are the #2 source. If your panel authenticates via web but the plugin config or your Permission::create() calls default to sanctum (or vice versa), checks silently fail. Confirm config/auth.php guards, the Spatie guard_name in config/permission.php, the Hexa config, and whatever guard you pass to $user->can() — they must all agree. Hexa Lite typically assumes web; if you have API guards, be explicit.

Renaming a Filament resource orphans permissions. Resource class renames, page slug changes, and refactors leave stale permission rows that appear in the Hexa UI forever. Either script a cleanup pass (Permission::whereNotIn('name', $expected)->delete()) or accept the drift and prune periodically. This is a real operational cost of any permission-management UI.

Don't hardcode permission strings across the codebase. Once they live in a UI, someone will rename one and break production in a way no IDE will catch. Centralize them in a Permissions enum or class Permissions { const POSTS_UPDATE = 'posts.update'; } and reference that everywhere, including the seeder.

The UI is not the source of truth for CI. Tests should create the permissions and roles they need in setUp() or a factory, not rely on seeders or on whatever state the local database is in. RefreshDatabase + a makeAdmin() test helper will save you hours.

Filament's canAccessPanel() is separate. Hexa Lite controls what a user can do inside the panel, not whether they can reach it. A user with zero permissions can still log in to the panel and see an empty nav. Add a FilamentUser::canAccessPanel() check if that's not the UX you want.

Tenancy caveat. If you enable Filament tenancy, be aware that Spatie's roles are global by default unless you enable teams. Hexa Lite does not add team-scoped role assignment for you. If you need per-tenant roles, enable Spatie's team support before running migrations — retrofitting it is painful.

Version pinning matters more than usual. Single-maintainer, sub-100-star package with a fast-moving Filament target. Pin the version in composer.json and read the changelog before bumping, especially across Filament major versions. There's no large community to catch regressions for you.

Read the source when something is off. The plugin's value is convenience; when the convenience breaks (custom guard, non-standard user model, unusual panel setup), the fix is almost always a 5-line override or config tweak you'll find by reading vendor/hexters/hexa-lite/src/. The package is small — this is a feature, not a failure mode.

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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib