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

Otter Laravel Package

poowf/otter

Poowf Otter is a Laravel package for quickly building admin panels and CRUD screens. It provides configurable resources, authentication, role-based access, and a clean interface for managing your application’s data without building a backend from scratch.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and first login (roughly 15 minutes):

composer require poowf/otter
php artisan otter:install      # publishes config, migrations, assets, seeds an admin
php artisan migrate

Then visit /otter in your browser and log in with the seeded credentials (they're printed by the install command / stored in config/otter.php — change them immediately).

Where to look first, in order:

  1. config/otter.php — this is the heart of the package. The resources array is where you declare every model you want a CRUD screen for. Everything else (fields, labels, validation) hangs off this.
  2. config/auth.php and the published Otter migrations — Otter ships its own guard and user table (otter_users) so admin operators are separate from your application users. Confirm the guard name and middleware before you start wiring permissions.
  3. public/vendor/otter/ — the compiled Vue/Vuetify front end. Understanding that it's a pre-built bundle tells you early what you can and can't customize.

First use case — pick a low-risk internal model, not your User table. A Product, Ticket, or Article model with 5–10 fields is ideal. Register it:

// config/otter.php
'resources' => [
    'products' => [
        'model' => App\Models\Product::class,
        'label' => 'Products',
        'fields' => [
            ['name' => 'name', 'type' => 'text', 'rules' => 'required|max:255'],
            ['name' => 'price', 'type' => 'number', 'rules' => 'required|numeric'],
            ['name' => 'published', 'type' => 'boolean'],
        ],
    ],
],

Run php artisan config:cache (or at minimum config:clear), reload /otter, and you have a working list/create/edit/delete screen. This is the moment Otter earns its keep: a back-office panel in an afternoon instead of a week.

Before you commit, check compatibility. Otter's last meaningful activity was around Laravel 6/7. Verify the illuminate/* constraints in composer.json against your app version; on Laravel 9+ you may need to fork and bump constraints. Given it has ~0 dependents, treat it as "vendor-and-own" rather than "install-and-forget."

Implementation Patterns

Config-as-schema. The resources array is your admin schema. Keep it close to your models but don't duplicate truth: put rules on fields for form-level validation, and let model casts / mutators handle type coercion. Group resources by domain with a label and icon so the sidebar stays navigable as you add screens.

Relationship fields for foreign keys. Use belongsTo fields rather than raw select where the option list is large — Otter's searchable relationship inputs query via its own API and degrade badly on unindexed tables. Always define the display column (e.g. name) that the search dropdown shows, and add a DB index on it.

Custom actions for anything with consequences. Rather than letting an operator toggle a status column directly, define a custom action (approve, refund, resend, archive) that calls a service class in your app. This keeps business logic in one place, auditable, and testable — Otter becomes the UI, not the brain. This pattern also solves cross-field validation, which per-field rules can't express.

Separate the admin operator model from app users. Otter's own guard means you can hand an ops contractor an Otter account without giving them an application login. If you need to map the two, do it with a nullable user_id foreign key on the Otter user, not by merging tables.

Treat /otter as an internal surface. In config/otter.php, set the route prefix and middleware to something defensible: IP allowlist, auth:otter plus a role check, and ideally a separate DB connection user with limited grants. In production, never leave the seeded demo credentials active.

Use it as a stopgap, scoped honestly. Otter is at its best covering internal CRUD over 5–30 tables where the alternative is a week of hand-built Blade screens. If you need fine-grained authorization, audit trails, custom dashboards, or a design system that matches your product, price out Filament/Nova/Backpack — Otter will fight you on all four.

Iterate schema in source control. Because screens are defined in config/otter.php, resource changes are reviewable diffs. Commit them alongside the migration that adds the column — reviewers can see the admin impact of a schema change in the same PR.

Gotchas and Tips

  • Config caching bites. Editing config/otter.php on a cached environment does nothing until php artisan config:clear. "My new field doesn't show up" is almost always this.
  • Asset publishing is a one-way street. The front end is a compiled Vue bundle in public/vendor/otter. Re-publish after upgrades and run php artisan view:clear, but don't expect to restyle it without rebuilding from source — budget for that or accept the default look.
  • Password fields double-hash easily. If you use a password type on a model that already has a hashed cast or a setPasswordAttribute mutator, you'll hash twice and lock users out. Verify with Hash::check after a test save.
  • Silent field failures. A malformed field definition often surfaces as a blank column or missing input rather than an exception. Watch the browser network tab against Otter's API endpoints and storage/logs/laravel.log — the errors are there, just not in the UI.
  • Route ordering. Otter registers its own routes; if you have a catch-all or a localized route group, register Otter's prefix earlier or your admin URL will 404 into your front end.
  • Guards and sessions confuse people. After install, check config/auth.php — Otter's guard is separate. Mixing Auth::user() from your app middleware into Otter views returns null and produces confusing authorization behavior.
  • Global scopes and soft deletes apply. Resources respect your model's global scopes, which is good for tenant isolation but surprising when a "missing" row is actually soft-deleted. Decide explicitly whether admins see trashed records.
  • Don't run otter:install twice casually — it re-publishes config and can overwrite local edits or reseed users. Read the command's prompts before confirming.
  • Extension points worth knowing: the route prefix, middleware stack, guard name, and per-page pagination are config keys; custom actions are the sanctioned place for domain logic. If you need more than that, you're patching vendor code — fork it into packages/ and take ownership, because upstream is quiet.
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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console