Custom Team Roles in Laravel Jetstream
Add custom team roles to Laravel Jetstream using the team_user pivot table and authorization policies.
21 Jul 2025, 21:53 UTC

The Problem: Jetstream's default team roles are limited to owner and member.
When you need additional roles such as billing administrator or read‑only viewer, the default UI and model do not expose a clean way to store or enforce those roles.
How Jetstream Stores Team Roles
Jetstream builds on Laravel's native teams feature. Membership is recorded in a `team_user` pivot table that already contains a `role` column. The column accepts any string, so you can add custom roles without changing the database schema.
A pivot table is an intermediate table that records a many‑to‑many relationship. In this case it links `users` to `teams`. Laravel's Eloquent reads the pivot column when you eager‑load it.
Worked Example: Adding a Billing Administrator Role
1. Verify the pivot table includes `role` (no migration needed).
php artisan migrate:status
2. Ensure the `Team` model loads the pivot column:
public function users(): BelongsToMany {
return $this->belongsToMany(User::class)
->withPivot('role')
->withTimestamps();
}
3. Define role constants in the model:
const ROLE_BILLING_ADMIN = 'billing_admin';
4. Create a policy that checks the pivot role:
public function manageBilling(User $user, Team $team): bool {
$membership = $user->teams()
->where('teams.id', $team->id)
->first();
return $membership && in_array($membership->pivot->role, [Team::ROLE_OWNER, Team::ROLE_BILLING_ADMIN]);
}
5. Use the check in a controller:
if (auth()->user()->cannot('manageBilling', $team)) {
abort(403);
}
Limitation: Jetstream UI Does Not Recognize Custom Roles
The built‑in team management pages only allow selecting owner or member. To assign `billing_admin` you must create a custom admin form, run a tinker session, or update the database directly.
Actionable Closing
Start by listing features that need roles beyond owner and member. Add the role constants, update the `Team` relationship, and write a policy for each sensitive feature. Before exposing the feature to team owners, build a small internal admin screen or seed script for role assignment and test thoroughly in staging.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.