Advanced
Team-Based Authentication
Scope data and API calls to specific teams
Enable team-based authentication to automatically scope all data and API calls to the current team context.
Enable Team Utilities
Add the team utility flag to your Crouton config:
// crouton.config.js
export default {
collections: [
{ name: 'products', fieldsFile: './schemas/product-schema.json' },
],
targets: [
{
layer: 'shop',
collections: ['products']
}
],
flags: {
useTeamUtility: true // Enable team-based multi-tenancy
}
}
What This Enables
When useTeamUtility: true is set, the generator automatically:
- Adds database fields to all collections:
teamId(text, required) - References the team/organizationuserId(text, required) - References the user who created the record
- Generates simplified API endpoints that:
- Automatically inject
teamIdanduserIdfrom the authenticated session - Include team membership validation via
resolveTeamAndCheckMembership - Scope all database queries to the current user's team
- Automatically inject
- Provides team-scoped queries:
- All
getAll*queries filter byteamId - All create operations automatically set
teamIdanduserId - Team switching triggers automatic query invalidation
- All
Important: Do NOT manually define
teamId or userId in your schema JSON files. The generator adds these automatically when useTeamUtility: true, and manual definitions will cause duplicate key errors.See Schema Format - Auto-Generated Fields for details.Use in Components
The useTeam composable provides team context throughout your app:
Query Examples: For complete
useCollectionQuery patterns, see Querying Data.<script setup lang="ts">
const { currentTeam } = useTeam()
// All API calls include team context
const { items } = await useCollectionQuery('shopProducts')
// → Fetches /api/teams/[teamId]/shop-products
</script>
API Routes
When team utilities are enabled, create team-scoped API routes:
// server/api/teams/[team]/shop-products/index.get.ts
export default defineEventHandler(async (event) => {
const teamId = getRouterParam(event, 'team')
// Query scoped to team
const products = await db
.select()
.from(products)
.where(eq(products.teamId, teamId))
return products
})
Team Switching
Allow users to switch between teams with automatic query refetching:
<script setup lang="ts">
const { currentTeam, teams, switchTeam } = useTeam()
const handleSwitchTeam = async (teamId: string) => {
await switchTeam(teamId)
// All queries auto-refetch for new team!
}
</script>
<template>
<USelectMenu
v-model="currentTeam"
:options="teams"
@update:model-value="handleSwitchTeam"
/>
</template>
How It Works
When team utilities are enabled:
- All queries automatically include the current team ID
- API routes receive the team parameter
- Switching teams invalidates and refetches all queries
- Data is automatically scoped to the active team
Related Sections
- Querying Data - Query patterns
- Caching - Cache invalidation
- Data Operations - CRUD operations