Teams and the team switcher
What a person sees after signing in, how a team is created, entered, configured, left and closed.
A person signs in once and works inside one team at a time. This guide follows that person from the sign-in to the team's settings screen, and says which config key changes each step. It assumes the base is running; see Get it running on the base's site for that.
The switcher at /app
After signing in the person lands on /app, the team switcher. It lists every team they belong to, with its logo, and a button to create a new one. Clicking a team opens its workspace at /team.
The choice is remembered in two places: a team_id cookie and the current_team_id column of the user. The next visit to /app skips the list and opens that team straight away, as long as the person still belongs to it. To see the list again the sidebar of the workspace has a Switch team link, which opens /app?redirect=false. Signing out forgets the cookie.
When the person belongs to no team, the switcher shows only the button to create one.
One team per person
Set APP_ENABLE_MULTI_TEAMS=false in .env and the switcher disappears from view: the person is sent to the only team they belong to, and someone with no team sees an error asking them to contact the administrator instead of a create button. Use it when your product creates the team for the customer and the customer never makes another.
Creating a team
The Create team button opens /app/teams/create. A name is required, a description is optional. Saving does the rest:
- The person becomes the team's owner, stored as
creator_user_id, and its first member. - The roles in
config/app.php→team_rolesare created inside the team, and the owner role named inteam_owner_roleis created with every team permission and assigned to the creator. See Team roles and permissions. - The switcher opens with the new team selected.
When plans are on, opening the team's dashboard puts a team with no plan on the free plan, so a team with no card can start working. When that is not possible the team stays without a plan and its members are told why. See Team plans and billing.
The workspace at /team
Everything under /team runs inside the selected team, guarded by the team middleware: it loads the team, checks the person is still a member, and activates the team's permissions for the request. A person removed from the team is sent back to the switcher on their next click. See The team context for what that means in code.
| URL | What it shows | Who reaches it |
|---|---|---|
/team |
The dashboard: counters of roles, members and invitations, and the usage of the plan's limits. | Any member. |
/team/members |
The members and the pending invitations. | Members with retrieve members. Removing a member or an invitation takes delete members, and changing a member's role takes update members. |
/team/members/create |
The form to add a member. | Members with create members; at the plan's limit the button to it stays on the list but disabled, and the form refuses on save. |
/team/roles |
The team's roles. | Members with the roles permissions. |
/team/media, /team/space |
The team's shared files, and how much disk they take up. | Members with manage media. |
/team/settings |
Name, description, logo, extra fields, importing and exporting the team's data, and leaving or closing the team. | Any member. Only members with edit settings can change anything there. |
/team/plans, /team/add-ons, /team/billing, /team/payment-methods, /team/debt |
The team's subscription, and the balance it owes. | The owner and members with manage plans; anyone else is sent back to the dashboard with a message. |
The owner passes every one of those checks without holding the permission.
The members, roles, files and space screens each ask only for their own permission. Plans being on or off, the team's subscription or balance, and manage plans do not enter into it: the menu offers each screen to exactly the members who can open it, and a member without the permission who opens its URL is refused. Only the billing screens ask for manage plans, and they never require a subscription, so a team whose plan lapsed can still reach the page that fixes it.
Settings asks for no permission to open, on purpose: it is where a member leaves the team, so every member reaches it and sees it in the menu, whatever else they may or may not do.
Links that open a team
A /team/... address opens against the team the person has active, so a link from an email about one team, opened while another is active, would show a screen where the record does not exist. A link can name its team instead, with ?team= and the team's id at the end, such as /team/members?team=12:
- A member of that team lands on the screen with that team active, exactly as if they had chosen it on the switcher. The address bar ends without
?team=, so reloading or bookmarking the page does not switch again. - Someone who is not a member, or a link to a team that no longer exists, lands on the switcher with the notice You are not a member of that team, and their active team does not change. With one team per person, the notice shows on the screen that mode already leads to.
- Someone not signed in signs in first and then arrives at the same place.
Opening a team this way grants nothing: the screen still asks for its own permission. A link without ?team= works as it always has. To build these links from your own code, see The team context.
Team settings
/team/settings edits what the team is:
- Name and description.
- Logo. A jpeg, png, gif, webp, heic, heif or avif file up to 5 MB, stored in the team's file library and counted against the team's storage quota. Upload another to replace it, take it off the team while keeping the file, or delete the file from the library to give the space back. Without one, the team shows a generated avatar from its name. See Team files and space.
- Extra fields. Key and value pairs stored in the
extra_fieldsjson column, for what your product needs to know about a team and the base does not: a tax id, an address, an industry. Read them asteam()->extra_fields['tax_id']. - Import and export data. Packs the team's data into a file, and reads one back into the team. See Move team data between environments.
Leaving or closing the team
The same screen has the button to leave the team, and for the owner, to close it. Both ask the person to type the team's name before anything happens.
- A member who confirms is removed from the team and sent to the switcher. They receive the same notification as someone removed by the owner.
- The owner who confirms closes the team: it is soft deleted, every member loses access, and the owner is sent to the switcher. The team's roles, subscription and records stay in the database, so an administrator can restore it from the admin panel.
There is no ownership transfer in the kit: the owner is the person who created the team, for as long as the team exists.
Notifications a team sends
| What happened | Who is told | How |
|---|---|---|
| Added to a team | The new member | In the account and by email. |
| Removed from a team, or left it | The member | In the account and by email. |
| Invited to a team that they have no account in yet | The invited email | By email, with a link to register. |
| An account was created for them | The provisioned email | By email, with a link to set a password. |
The last two are described in Members and invitations.