Use organization slugs in URLs
You will learn the following:
- Configure your app's URL structure for organizations
- Configure Clerk components to handle organization slugs
- Set up middleware to sync organizations with URLs
- Render organization-specific content
Before you start
Example repository
Organization slugs are human-readable URL identifiers 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.
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 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. Adding slugs to URLs isn't recommended 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.
Configure your app's URL structure
Your application URLs should be structured to indicate which sections of your app are scoped to organizations versus personal accounts.
The following example uses the following URL structure:
/orgs/
indicates the active organization, followed by the organization slug/me/
indicates the active personal account
URL | What should be active? | What should be displayed? |
---|---|---|
/orgs/acmecorp | Organization Acmecorp | Acmecorp's home page |
/orgs/acmecorp/settings | Organization Acmecorp | Acmecorp's settings page |
/me | Personal account | Personal home page |
/me/settings | Personal account | Personal settings page |
Configure <OrganizationSwitcher />
and <OrganizationList />
The <OrganizationSwitcher />
and <OrganizationList />
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
hideSlug
tofalse
to allow users to customize the organization's URL slug when creating an organization. - Set
hidePersonal
tofalse
to allow users to select their personal account. - 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. - Set
afterSelectPersonalUrl
to/me
to navigate the user to their personal account 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
. - When a user selects their personal account using either component, they'll be redirected to
/me
.
With clerkMiddleware()
, you can use the organizationSyncOptions
property to declare URL patterns that determine whether a specific organization or user's personal account 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.
The same pattern is used with personalAccountPatterns
to match the user's personal account.
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, a message will also be logged 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 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 />
component allows the user to select a valid organization.
Render organization-specific content
Use the following tabs to learn how to access organization information on the server-side and client-side.
To get organization information on the server-side, access the Auth
object. In Next.js apps, this object is returned by auth()
. In other frameworks, use the getAuth()
helper to get the Auth
object.
To access additional organization information like the organization name, you'll need to customize the Clerk session token to include these details:
- In the Clerk Dashboard, navigate to the Sessions page.
- In the Customize session token section, select Edit.
- In the modal that opens, add any claim you need to your session token. For this guide, add the following:
- Select Save.
You can now access the sessionClaims
on the Auth
object.
To get organization information on the client-side, use the useOrganization()
hook to access the organization
object.
Feedback
Last updated on