# Use Organization slugs in URLs

**Example Repository**

- [Demo app](https://github.com/clerk/orgs/tree/main/examples/sync-org-with-url)

**Before you start**

- [Set up a Next.js + Clerk app](https://clerk.com/docs/nextjs/getting-started/quickstart.md)
- [Enable Organizations for your instance](https://clerk.com/docs/guides/organizations/overview.md)
- [Enable Organization slugs for your application](https://clerk.com/docs/guides/organizations/configure.md#organization-slugs)

Organization slugs are human-readable URL identifiers (like `acme-corp` or `marketing-team`) that help users reference which Organization they're working in. A common pattern for Organization-scoped areas in an application is to include the Organization slug in the URL path, making links sharable and providing clear context about which tenant the page belongs to.

For example, a B2B application named "Petstore" has two customer Organizations: **Acmecorp** and **Widgetco**. Each Organization uses its name as a slug in the URL:

- **Acmecorp**: `https://petstore.example.com/orgs/`**`acmecorp`**`/dashboard`
- **Widgetco**: `https://petstore.example.com/orgs/`**`widgetco`**`/dashboard`

Alternatively, [Organization IDs](https://clerk.com/docs/reference/objects/organization.md#properties) can be used to identify Organizations in URLs:

- **Acmecorp**: `https://petstore.example.com/orgs/`**`org_1a2b3c4d5e6f7g8e`**`/dashboard`
- **Widgetco**: `https://petstore.example.com/orgs/`**`org_1a2b3c4d5e6f7g8f`**`/dashboard`

### When to use Organization slugs

This feature is intended for apps that **require** Organization slugs in URLs. **We don't recommend adding slugs to URLs unless necessary.**

Use Organization slugs if:

- Users frequently share links for public-facing content (e.g., documentation, marketing materials, and third-party blogs).
- Users regularly switch between multiple Organizations.
- Organization-specific URLs provide meaningful context.

**Don't** use Organization slugs if:

- Most users belong to only one Organization.
- You want to keep URLs simple and consistent.
- You're primarily using the Clerk session for Organization context.

This guide shows you how to add Organization slugs to your app's URLs, configure Clerk components to handle slug-based navigation, and access Organization data based on the URL slug at runtime.

1. ## Configure `<OrganizationSwitcher />` and `<OrganizationList />`

   The [<OrganizationSwitcher />](https://clerk.com/docs/reference/components/organization/organization-switcher.md) and [<OrganizationList />](https://clerk.com/docs/reference/components/organization/organization-list.md) components provide a robust set of options to manage Organization slugs and IDs in your application's URLs.

   Set the following properties to configure the components to handle slug-based navigation:

   - Set `afterCreateOrganizationUrl` to `/orgs/:slug` to navigate the user to the Organization's slug after creating an Organization.
   - Set `afterSelectOrganizationUrl` to `/orgs/:slug` to navigate the user to the Organization's slug after selecting it.

   For example, if the Organization has the slug `acmecorp`, when a user creates or selects that Organization using either component, they'll be redirected to `/orgs/acmecorp`.

   **<OrganizationSwitcher />**

   filename: components/Header.tsx

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

   export default function Header() {
     return (
       <OrganizationSwitcher
         afterCreateOrganizationUrl="/orgs/:slug" // Navigate to the org's slug after creating an org
         afterSelectOrganizationUrl="/orgs/:slug" // Navigate to the org's slug after selecting  it
       />
     )
   }
   ```

   **<OrganizationList />**

   filename: app/organization-list/[[...organization-list]]/page.tsx

   ```tsx
   import { OrganizationList } from '@clerk/nextjs'

   export default function OrganizationListPage() {
     return (
       <OrganizationList
         afterCreateOrganizationUrl="/orgs/:slug" // Navigate to the org's slug after creating an org
         afterSelectOrganizationUrl="/orgs/:slug" // Navigate to the org's slug after selecting it
       />
     )
   }
   ```
2. ## Configure `clerkMiddleware()` to set the Active Organization

   > If your app doesn't use `clerkMiddleware()`, or you prefer to manually set the Active Organization, use the [setActive()](https://clerk.com/docs/reference/objects/clerk.md) method to control the Active Organization on the client-side.

   With [clerkMiddleware()](https://clerk.com/docs/reference/nextjs/clerk-middleware.md), you can use the [organizationSyncOptions](https://clerk.com/docs/reference/nextjs/clerk-middleware.md#organization-sync-options) property to declare URL patterns that determine whether a specific Organization should be activated.

   If the middleware detects one of these patterns in the URL and finds that a different Organization is active in the session, it'll attempt to set the specified Organization as the active one.

   In the following example, two `organizationPatterns` are defined: one for the root (e.g., `/orgs/acmecorp`) and one as the wildcard matcher `(.*)` to match `/orgs/acmecorp/any/other/resource`. This configuration ensures that the path `/orgs/:slug` with any optional trailing path segments will set the Organization indicated by the slug as the active one.

   > If no Organization with the specified slug exists, or if the user isn't a member of the Organization, then `clerkMiddleware()` **won't** modify the Active Organization. Instead, it will leave the previously Active Organization unchanged on the Clerk session.

   filename: proxy.ts

   ```tsx
   import { clerkMiddleware } from '@clerk/nextjs/server'

   export default clerkMiddleware(
     (auth, req) => {
       // Add your middleware checks
     },
     {
       organizationSyncOptions: {
         organizationPatterns: [
           '/orgs/:slug', // Match the org slug
           '/orgs/:slug/(.*)', // Wildcard match for optional trailing path segments
         ],
       },
     },
   )

   export const config = {
     matcher: [
       // Skip Next.js internals and all static files, unless found in search params
       '/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)',
       // Always run for API routes
       '/(api|trpc)(.*)',
       // Always run for Clerk-specific frontend API routes
       '/__clerk/(.*)',
     ],
   }
   ```
3. ### Handle failed activation

   Now that `clerkMiddleware()` is configured to activate Organizations, you can build an Organization-specific page while handling cases where the Organization can't be activated.

   Failed activation occurs if no Organization with the specified slug exists, or if the given user isn't a member of the Organization. When this happens, the middleware won't change the Active Organization, leaving the previously active one unchanged.

   For troubleshooting, Clerk will also log a message on the server:

   > Clerk: Organization activation handshake loop detected. This is likely due to an invalid Organization ID or slug. Skipping Organization activation.

   It's ultimately the responsibility of the page to ensure that it renders the appropriate content for a given URL, and to handle the case where the expected Organization **isn't** active.

   In the following example, the Organization slug is detected as a Next.js [Dynamic Route](https://nextjs.org/docs/pages/building-your-application/routing/dynamic-routes) param and passed as a parameter to the page. If the slug doesn't match the Active Organization slug, an error message is rendered and the [<OrganizationList />](https://clerk.com/docs/reference/components/organization/organization-list.md) component allows the user to select a valid Organization.

   filename: app/orgs/[slug]/page.tsx

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

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

     // Check if the org slug from the URL params doesn't match
     // the active org slug from the user's session.
     // If they don't match, show an error message and the list of valid Organizations.
     if (slug != orgSlug) {
       return (
         <>
           <p>Sorry, Organization {slug} is not valid.</p>
           <OrganizationList
             afterCreateOrganizationUrl="/orgs/:slug"
             afterSelectOrganizationUrl="/orgs/:slug"
           />
         </>
       )
     }

     return <div>Welcome to Organization {orgSlug}</div>
   }
   ```
4. ## Render Organization-specific content

   Use the following tabs to learn how to access Organization information on the server-side and client-side.

   **Server-side**

   To get Organization information on the server-side, access the [`Auth`](https://clerk.com/docs/reference/backend/types/auth-object.md) object which includes the active org's `orgId` and `orgSlug` and the current user's `orgRole` and `orgPermissions`. To access _additional_ Organization information server-side, like the Organization name, you can store the additional information in the user's session token. To [customize the session token](https://clerk.com/docs/guides/sessions/customize-session-tokens.md), do the following:

   1. In the Clerk Dashboard, navigate to the [**Sessions**](https://dashboard.clerk.com/~/sessions) page.
   2. Under **Customize session token**, in the **Claims** editor, add any claim you need to your session token. For this guide, add the following claim:

      ```json
      {
        "org_name": "{{org.name}}"
      }
      ```
   3. Select **Save**.

   Now that you've added the claim to the session token, you can access it from the [`sessionClaims`](https://clerk.com/docs/reference/backend/types/auth-object.md) property on the `Auth` object.

   filename: app/orgs/[slug]/page.tsx

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

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

     // Check if the org slug from the URL params doesn't match
     // the active org slug from the user's session.
     // If they don't match, show an error message and the list of valid Organizations.
     if (slug != orgSlug) {
       return (
         <>
           <p>Sorry, Organization {slug} is not valid.</p>
           <OrganizationList
             afterCreateOrganizationUrl="/orgs/:slug"
             afterSelectOrganizationUrl="/orgs/:slug"
           />
         </>
       )
     }

     // Access the org name from the session claims
     let orgId = sessionClaims['org_id'] as string

     return <div>{orgId && `Welcome to organization ${orgId}`}</div>
   }
   ```

   **Client-side**

   To get Organization information on the client-side, use the [useOrganization()](https://clerk.com/docs/reference/hooks/use-organization.md) hook to access the [organization](https://clerk.com/docs/reference/objects/organization.md) object.

   filename: app/orgs/[slug]/page.tsx

   ```tsx
   'use client'

   import { OrganizationList, useOrganization } from '@clerk/nextjs'

   export default function Home({ params }: { params: { slug: string } }) {
     // Use `useOrganization()` to access the currently active org's `Organization` object
     const { organization } = useOrganization()

     // Check if the org slug from the URL params doesn't match
     // the active org slug from the user's session.
     // If they don't match, show an error message and the list of valid Organizations.
     if (!organization || organization.slug != params.slug) {
       return (
         <>
           <p>Sorry, Organization {params.slug} is not valid.</p>
           <OrganizationList
             hidePersonal={false}
             afterCreateOrganizationUrl="/orgs/:slug"
             afterSelectOrganizationUrl="/orgs/:slug"
             afterSelectPersonalUrl="/me"
           />
         </>
       )
     }

     // Access the org name from the `Organization` object
     return <div>{organization && `Welcome to Organization ${organization.name}`}</div>
   }
   ```

---

## Sitemap

[Overview of all docs pages](https://clerk.com/docs/llms.txt)
