Configure teams
The config keys and environment variables the team layer adds, with what each one changes.
The team layer is configured by a handful of keys on top of the base's. Everything below has a working default: change a key only when your product needs the other behaviour. The base's own keys are documented on its site, in The environment file and Configure your project.
Environment variables
| Variable | Default | What it does |
|---|---|---|
APP_ENABLE_MULTI_TEAMS |
true |
Whether a person can create and belong to several teams. With false the switcher is skipped and the person is sent to their only team. |
TEAM_INVITATION_MODE |
approval_required |
What happens when a member is added who has no account: approval_required invites them to register, auto_provision creates the account. See Members and invitations. |
TEAM_DATA_IMPORT_TIMEOUT |
21600 |
How many seconds the server may spend checking or importing one team data package before it gives up. Keep your queue's retry_after above it. See Move team data between environments. |
TEAM_DATA_EXPORT_DISK |
local |
Where exported team packages are put together and then wait to be downloaded. The default works when the web server and every queue worker share a disk; otherwise name a disk on a private bucket, never one anybody can read without a signed link. See Move team data between environments. |
BILLING_TEAM_ENABLED |
true |
Registers the team billing adapter, so plans and add-ons attach to the team. |
BILLING_USER_ENABLED |
false |
Registers the base's user billing adapter next to the team's, for a product that sells to people and to teams. See Team plans and billing. |
The base's FEATURE_PLANS_ENABLED and FEATURE_ADDONS_ENABLED still decide whether plans and add-ons exist at all.
config/app.php
'home_route' => '/app',
'enable_multi_teams' => env('APP_ENABLE_MULTI_TEAMS', true),
'permissions' => [
'dashboard admin' => 'web',
'dashboard user' => 'web',
// * Media permissions
'retrieve media' => 'web',
'create media' => 'web',
'update media' => 'web',
'delete media' => 'web',
'retrieve media_folder' => 'web',
'create media_folder' => 'web',
'update media_folder' => 'web',
'delete media_folder' => 'web',
'browse media_folder' => 'web',
// * Team permissions
'retrieve members' => 'team',
'create members' => 'team',
'update members' => 'team',
'delete members' => 'team',
'edit settings' => 'team',
'manage plans' => 'team',
'manage media' => 'team',
// * Ticket permissions
'answer ticket' => 'web',
'view_team ticket' => 'team',
'use assistant' => 'web',
],
'team_restricted_permissions' => [ // Team permissions the owner must NOT receive on signup
],
'team_owner_role' => 'administrator',
'team_default_role' => 'user',
'team_roles' => [
'user' => [
'retrieve members',
],
],
| Key | What it does |
|---|---|
home_route |
Where a signed-in person lands: the team list, which opens the remembered team straight away. The base sets it to its own dashboard. |
enable_multi_teams |
Read from APP_ENABLE_MULTI_TEAMS, above. |
permissions |
Every permission, with its guard. The eight on the team guard are the ones the shipped team screens check; the web ones belong to the admin panel and the account. Add yours here with 'team' as the guard and seed; the seeder creates the permission but gives it to no role, so the existing teams need a migration, as Team roles and permissions explains. |
team_restricted_permissions |
Team permissions the owner role of a new team does not receive. Empty as shipped, so the owner role gets every team permission. |
team_owner_role |
The name of the role created in each team with every team permission except the restricted ones, assigned to the creator. |
team_default_role |
The role every member added later receives. It must be one of the keys of team_roles. |
team_roles |
The roles created inside each new team, each with the permissions it starts with. |
See Team roles and permissions for how the role keys play together.
config/teams.php
'invitation_mode' => env('TEAM_INVITATION_MODE', 'approval_required'),
'data_import' => [
'timeout' => (int) env('TEAM_DATA_IMPORT_TIMEOUT', 21600),
'watch_seconds' => 15,
'max_parts' => 10000,
],
'data_export' => [
'budget_seconds' => 3,
'chunk_rows' => 500,
'tries' => 3,
'stalled_after' => 3600,
'keep_days' => 7,
'disk' => env('TEAM_DATA_EXPORT_DISK', 'local'),
],
| Key | What it does |
|---|---|
invitation_mode |
Read from TEAM_INVITATION_MODE, above. |
data_import.timeout |
Read from TEAM_DATA_IMPORT_TIMEOUT, above. |
data_import.watch_seconds |
When an import ends and its window asked for news within these seconds, the result is shown there; otherwise the person who started it gets a notification in the product. |
data_import.max_parts |
The most parts S3 joins into one file. Times the upload part size, it is the largest package a bucket accepts. |
data_export.budget_seconds |
How many seconds of work each step of an export does before it leaves the rest to the next step. An export is put together in many short steps, so your queue needs no special setting for it. |
data_export.chunk_rows |
How many records each step of an export reads at most. |
data_export.tries |
How many times a step of an export that fails is tried again before the export fails. |
data_export.stalled_after |
How many seconds an export may go without moving forward before it is given up as interrupted, so the team can export again. |
data_export.keep_days |
How many days an exported package can be downloaded before it is deleted. |
data_export.disk |
Read from TEAM_DATA_EXPORT_DISK, above. |
config/permission.php
'teams' => true,
'column_names' => [
'team_foreign_key' => 'team_id',
],
Spatie Permission's teams mode, already on. team_id is the column added to roles, model_has_roles and model_has_permissions by the kit's migrations, and the value 0 in it means the global context of the admin panel. Leave both as they are unless you rename the column, in which case rename it in the migrations too.
packages/billing-team/config/billing-team.php
'enabled' => env('BILLING_TEAM_ENABLED', true),
'model' => App\Models\Team::class,
'owner_resolver' => null,
'plan_limits' => App\Classes\TeamPlanLimits::class,
'plan_features' => App\Classes\TeamPlanFeatures::class,
'user_billing_enabled' => env('BILLING_USER_ENABLED', false),
| Key | What it does |
|---|---|
enabled |
Read from BILLING_TEAM_ENABLED. |
model |
The model that owns a billing account: the team. |
owner_resolver |
A class that answers which team is being billed in the current request. null uses the team() helper, which is right for every screen under /team. |
plan_limits |
The class whose public methods count each limit for a team. |
plan_features |
The class whose public methods declare the capabilities a team can buy. |
user_billing_enabled |
Read from BILLING_USER_ENABLED. |
What stays as in the base
Sign-in identities, verification, mail, SMS, storage, the AI provider, tracking, referrals and the public site keep the base's keys and meaning. Nothing about a team changes how a person signs in or which language they read.