Configuration
config/packstub-teams.php holds app-wide settings; the plugin overrides any of them per panel.
| Key | Default | Purpose |
|---|---|---|
team_model |
App\Models\Team |
the tenant model |
membership.table / team_foreign_key / user_foreign_key / role_column |
team_user / team_id / user_id / role |
the pivot |
membership.team_relationship / user_relationship |
members / joinedTeams |
relation names to prefer when your models define them |
invitations_table |
team_invitations |
|
connection |
null |
connection for the pivot + invitations (central DB in database-per-tenant apps) |
roles.provider |
null (auto) |
simple, spatie, or a RoleProvider class |
roles.owner / roles.default / roles.managers |
owner / member / ['admin'] |
reserved owner role, role for new invites, roles allowed to manage |
roles.roles |
owner/admin/member | name => label or name => ['label', 'description', 'permissions'] |
invitations.expire_after_days |
7 | |
invitations.require_email_match |
true | only the invited address may accept an e-mail invitation |
invitations.count_pending_toward_seats |
true | |
invitations.resend_cooldown_minutes |
5 | |
invitations.max_batch |
10 | addresses per Invite action |
invitations.links |
true | offer shareable links in the UI |
invitations.notify_existing_users |
true | database notification for invitees with an account |
invitations.auto_accept_on_login |
false | accept every pending invitation for the e-mail on login |
invitations.prune_accepted_after_days |
30 | retention for teams:prune-invitations |
invitations.mail.queue |
false | |
personal_teams.enabled / name |
false / :name's Team |
see Installation |
seat_limit |
null | global default |
The plugin API
TeamsPlugin::make()
->roles([...], default: 'member', managers: ['admin'])
->roleProvider('spatie') // or 'simple' / a class
->seatLimit(fn (Team $team): ?int => $team->plan?->seats)
->canManageUsing(fn (User $user, Team $team): bool => ...)
->canInviteUsing(fn (User $user, Team $team): bool => ...)
->personalTeams(fn (User $user): Team => Team::create([...]), name: ":name's Team")
->navigationGroup('Team')->navigationSort(90)
->tenantMenuItem() // "Members" in the tenant switcher menu
->membersPage(MyMembers::class) // or null to skip
->invitationsPage(null)
->acceptRoute() // /{panel}/invitations/{token}
->config(['seat_limit' => 10]) // any packstub-teams.* key, per panel
->useFilamentTenancy(); // preset for packstub/filament-tenancy
The service
Packstub\Teams\Facades\Teams — invite, inviteMany, createInviteLink, resend, revoke, accept, acceptAllFor, addMember, changeRole, removeMember, transferOwnership, roles, assignableRoles, defaultRoleFor, userCan, canManage, canInvite, seatLimit, seatsUsed, hasAvailableSeats, membersOf, teamsOf, invitationsOf, ownersOf, isMember, roleOf, pruneInvitations, createPersonalTeam.
Rule violations throw a Packstub\Teams\Exceptions\TeamsException subclass: SeatLimitReached, LastOwnerException, InvalidInvitation, InvalidRole, NotAMember, AlreadyAMember, ResendTooSoon. The Filament pages turn them into notifications.