Laravel Jetstream Teams: Setup, Policies, and Limitations
Enable Laravel Jetstream Teams to scaffold team models, invitations, and authorization policies without building multi-user access from scratch.
30 Jul 2026, 06:57 UTC

Shared access without rebuilding invitations
Your Laravel application needs more than individual user accounts. A customer wants to invite coworkers to a shared project, control who can edit settings, and transfer ownership when someone leaves. Building invitations, membership records, and team-scoped authorization from scratch is repetitive and error-prone.
Laravel Jetstream offers an optional Teams feature that scaffolds the models, migrations, policies, and UI for this workflow. The useful takeaway is that you can enable multi-user team access with one installation flag, but you accept tight coupling to your chosen frontend stack and a single-database assumption.
What Jetstream teams generates
When enabled, Jetstream creates an Eloquent Team model, migrations for teams and team invitations, a TeamPolicy authorization class, and routes for team creation, membership, and invitations. Team membership is stored in a team_user pivot table, which connects users to teams through standard Eloquent relationships.
Jetstream integrates teams with Laravel's authorization gates. A policy method such as view lets you write Gate::allows('view', $team) in controllers or Blade templates instead of writing manual membership checks.
Worked example: enable teams and authorize team access
Run the installation command from your Laravel project root:
php artisan jetstream:install livewire --teams
Where to run: Terminal in the project root. Permissions: The command needs write access to app/, database/, routes/, and composer dependencies. Expected checks: Confirm app/Models/Team.php and a migration such as database/migrations/xxxx_create_teams_table.php were created. Inspect app/Policies/TeamPolicy.php for view, create, update, delete, and invite methods. Risks: The command modifies authentication scaffolding and may overwrite published Jetstream views. Review the diff before committing.
After installation, use the generated policy in a controller:
<?php
namespace App\Http\Controllers;
use App\Models\Team;
use Illuminate\Support\Facades\Gate;
class TeamController extends Controller
{
public function show(Team $team)
{
if (! Gate::allows('view', $team)) {
abort(403);
}
return view('teams.show', compact('team'));
}
}
The route-model binding resolves $team, and the policy decides whether the authenticated user may see it. Because teams use Eloquent relationships, you can scope queries with auth()->user()->teams() or attach custom observers to the Team model.
Trade-offs and limitations
- Frontend coupling: Team views are generated for either Livewire or Inertia. Switching stacks later means reworking team-related UI.
- Single database: Jetstream assumes one application database. Cross-database or distributed team architectures need custom implementation.
- Orphaned artifacts: Disabling teams after installation can leave unused migrations, tables, and policy classes that require manual cleanup.
Verify the result
- Check that
app/Models/Team.phpand the teams and team_invites migrations exist. - Open
app/Policies/TeamPolicy.phpand confirm it contains team view, create, update, delete, and invite abilities. - Register a test user, create a team through the Jetstream dashboard, invite a second user by email, and confirm the signed invitation link attaches that user to the team.
- Query the
team_userpivot table or runauth()->user()->teams()->first()->usersin a test route to confirm membership.
Rollback
Because jetstream:install changes application state, roll back by reverting the installation commit in git, or manually remove the generated Team model, migrations, policies, routes, and views. Roll back migrations separately with php artisan migrate:rollback if they were part of the installation batch.
Closing
Jetstream Teams is practical when you need team invitations and membership quickly and your application runs on one database with a Livewire or Inertia frontend. Enable it only if you plan to keep the generated stack, and verify the policy and pivot table before inviting real users.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.