home / skills / clerk / skills / orgs

orgs skill

/skills/orgs

This skill helps you manage multi-tenant Clerk orgs with RBAC, org switching, and protected routes to streamline enterprise SaaS.

npx playbooks add skill clerk/skills --skill orgs

Review the files below or copy the command above to add this skill to your agents.

Files (2)
SKILL.md
4.7 KB
---
name: clerk-orgs
description: Clerk Organizations for B2B SaaS - create multi-tenant apps with org switching, role-based access, verified domains, and enterprise SSO. Use for team workspaces, RBAC, org-based routing, member management.
allowed-tools: WebFetch
license: MIT
metadata:
  author: clerk
  version: "1.0.0"
---

# Organizations (B2B SaaS)

> **Prerequisite**: Enable Organizations in Clerk Dashboard first.

## Quick Start

1. **Create an organization via dashboard** or through Clerk API
2. **Use OrganizationSwitcher** to let users switch between orgs
3. **Protect routes** using orgSlug from URL and role checks

## Documentation Reference

| Task | Link |
|------|------|
| Overview | https://clerk.com/docs/guides/organizations/overview |
| Org slugs in URLs | https://clerk.com/docs/guides/organizations/org-slugs-in-urls |
| Roles & permissions | https://clerk.com/docs/guides/organizations/control-access/roles-and-permissions |
| Check access | https://clerk.com/docs/guides/organizations/control-access/check-access |
| Invitations | https://clerk.com/docs/guides/organizations/add-members/invitations |
| OrganizationSwitcher | https://clerk.com/docs/reference/components/organization/organization-switcher |
| Verified domains | https://clerk.com/docs/guides/organizations/verified-domains |
| Enterprise SSO | https://clerk.com/docs/guides/organizations/add-members/sso |

## Key Patterns

### 1. Get Organization from Auth

Server-side access to organization:

```typescript
import { auth } from '@clerk/nextjs/server'

const { orgId, orgSlug } = await auth()
console.log(`Current org: ${orgSlug}`)
```

### 2. Dynamic Routes with Org Slug

Create routes that accept org slug:

```
app/orgs/[slug]/page.tsx
app/orgs/[slug]/settings/page.tsx
```

Access the slug:

```typescript
export default function DashboardPage({ params }: { params: { slug: string } }) {
  return <div>Organization: {params.slug}</div>
}
```

### 3. Check Organization Membership

Verify user has access to specific org:

```typescript
import { auth } from '@clerk/nextjs/server'

export default async function ProtectedPage() {
  const { orgId, orgSlug } = await auth()

  if (!orgId) {
    return <div>Not in an organization</div>
  }

  return <div>Welcome to {orgSlug}</div>
}
```

### 4. Role-Based Access Control

Check if user has specific role:

```typescript
const { has } = await auth()

if (!has({ role: 'org:admin' })) {
  return <div>Admin access required</div>
}
```

### 5. OrganizationSwitcher Component

Let users switch between organizations:

```typescript
import { OrganizationSwitcher } from '@clerk/nextjs'

export default function Nav() {
  return (
    <header>
      <h1>Dashboard</h1>
      <OrganizationSwitcher />
    </header>
  )
}
```

## Default Roles

All new members get assigned a role:

| Role | Permissions |
|------|-------------|
| `org:admin` | Full access, manage members, settings |
| `org:member` | Limited access, read-only |

Custom roles can be created in the dashboard.

## Default Permissions

| Permission | Role |
|-----------|------|
| `org:create` | Can create new organizations |
| `org:manage_members` | Can invite/remove members (default: admin) |
| `org:manage_roles` | Can change member roles (default: admin) |
| `org:update_metadata` | Can update org metadata (default: admin) |

## Authorization Pattern

Complete example protecting a route:

```typescript
import { auth } from '@clerk/nextjs/server'
import { redirect } from 'next/navigation'

export default async function AdminPage({ params }: { params: { slug: string } }) {
  const { orgSlug, has } = await auth()

  // Verify user is in the org
  if (orgSlug !== params.slug) {
    redirect('/dashboard')
  }

  // Check if admin
  if (!has({ role: 'org:admin' })) {
    redirect(`/orgs/${orgSlug}`)
  }

  return <div>Admin settings for {orgSlug}</div>
}
```

## Common Pitfalls

| Symptom | Cause | Solution |
|---------|-------|----------|
| `orgSlug` is undefined | Not calling `await auth()` | Use `const { orgSlug } = await auth()` |
| Role check always fails | Not awaiting `auth()` | Add `await` before `auth()` |
| Users can access other orgs | Not checking orgSlug matches URL | Verify `orgSlug === params.slug` |
| Org not appearing in switcher | Organizations not enabled | Enable in Clerk Dashboard → Organizations |
| Invitations not working | Wrong role configuration | Ensure members have invite role permissions |

## Workflow

1. **Setup** - Enable Organizations in Clerk Dashboard
2. **Create org** - Users create org or admin creates via API
3. **Add members** - Send invitations or add directly
4. **Assign roles** - Default member role, promote to admin as needed
5. **Build protected routes** - Use auth() to check orgSlug and roles
6. **Use OrganizationSwitcher** - Let users switch between orgs

Overview

This skill helps build multi-tenant B2B SaaS apps with Clerk Organizations, enabling org switching, role-based access control, verified domains, and enterprise SSO. It provides patterns and snippets for org-aware routing, member management, and protecting pages based on organization membership and roles. Use it to implement team workspaces, RBAC, and enterprise onboarding flows quickly.

How this skill works

The skill inspects authentication context via Clerk's auth() helper to extract orgId, orgSlug, and role checks. It shows how to wire dynamic routes that include an org slug, protect pages by verifying org membership and roles, and integrate the OrganizationSwitcher UI component. It also covers verified domains, invitations, and enterprise SSO setup as part of the org workflow.

When to use it

  • Building a multi-tenant app where users belong to teams or organizations
  • Enforcing org-scoped authorization for pages and API routes
  • Providing a UI for users to switch between multiple organizations
  • Implementing role-based features like admin-only settings
  • Onboarding enterprise customers with SSO and verified domains

Best practices

  • Enable Organizations in the Clerk dashboard before using org features
  • Always call await auth() server-side to access orgId/orgSlug and role checks
  • Include org slug in the URL and verify params.slug === orgSlug to prevent cross-org access
  • Use OrganizationSwitcher for consistent cross-org navigation and UX
  • Assign minimal default permissions and promote users to admin only as needed

Example use cases

  • Admin settings page guarded by org:admin role and matching org slug
  • Team dashboard rendered under /orgs/[slug]/ where slug drives data scoping
  • Inviting members to an organization with role assignments and invite links
  • Enterprise onboarding flow using verified domains and SSO for single-sign on
  • Routing users to their current org on sign-in and enabling quick org switching

FAQ

What if orgSlug is undefined?

Ensure you call await auth() on the server to populate orgId and orgSlug; enable Organizations in the Clerk dashboard if not already enabled.

How do I prevent users from accessing other orgs?

Include the org slug in your route and verify orgSlug === params.slug from auth(); redirect or deny access when they do not match.