AgentSkillsCN

clerk-orgs

Clerk 组织功能——面向 B2B SaaS,支持多租户应用,提供组织切换、基于角色的访问控制、已验证域名以及企业级单点登录。适用于团队工作空间、RBAC、基于组织的路由、成员管理。

SKILL.md
--- frontmatter
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

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:

code
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:

RolePermissions
org:adminFull access, manage members, settings
org:memberLimited access, read-only

Custom roles can be created in the dashboard.

Default Permissions

PermissionRole
org:createCan create new organizations
org:manage_membersCan invite/remove members (default: admin)
org:manage_rolesCan change member roles (default: admin)
org:update_metadataCan 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

SymptomCauseSolution
orgSlug is undefinedNot calling await auth()Use const { orgSlug } = await auth()
Role check always failsNot awaiting auth()Add await before auth()
Users can access other orgsNot checking orgSlug matches URLVerify orgSlug === params.slug
Org not appearing in switcherOrganizations not enabledEnable in Clerk Dashboard → Organizations
Invitations not workingWrong role configurationEnsure 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