Docs

Build a custom flow for creating organizations

Warning

This guide is for users who want to build a custom user interface using the Clerk API. To use a prebuilt UI, use the Account Portal pages or prebuilt components.

Organizations are a powerful feature in Clerk that allow you to group users together and manage their permissions. Organizations can be created and managed using the Clerk Dashboard, but you can also allow users within your application to create organizations.

This guide will demonstrate how to use the Clerk API to build a custom flow for creating organizations.

The following example uses the useOrganizationList() hook to get the createOrganization() method. This method is used to create a new organization with the provided name.

This example is written for Next.js App Router but can be adapted for any React meta framework, such as Remix.

app/components/CreateOrganization.tsx
'use client'

import { useOrganizationList } from '@clerk/nextjs'
import { FormEventHandler, useState } from 'react'

export default function CreateOrganization() {
  const { createOrganization } = useOrganizationList()
  const [organizationName, setOrganizationName] = useState('')

  const handleSubmit: FormEventHandler<HTMLFormElement> = (e) => {
    e.preventDefault()
    createOrganization({ name: organizationName })
    setOrganizationName('')
  }

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        name="organizationName"
        value={organizationName}
        onChange={(e) => setOrganizationName(e.currentTarget.value)}
      />
      <button type="submit">Create organization</button>
    </form>
  )
}

The following example uses the clerk.createOrganization() method to create a new organization with the provided name.

Use the tabs to view the code necessary for the index.html and main.js files.

index.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Clerk + JavaScript App</title>
  </head>
  <body>
    <div id="app"></div>

    <h1>Create an organization</h1>
    <form id="create-organization">
      <label for="name">Name</label>
      <input id="name" name="name" />
      <button>Create organization</button>
    </form>

    <script type="module" src="/src/main.js" async crossorigin="anonymous"></script>
  </body>
</html>
main.js
import { Clerk } from '@clerk/clerk-js'

const pubKey = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY

if (!pubKey) {
  throw new Error('Add your VITE_CLERK_PUBLISHABLE_KEY to .env file')
}

const clerk = new Clerk('YOUR_PUBLISHABLE_KEY')
await clerk.load()

if (clerk.user) {
  const form = document.getElementById('create-organization')

  form.addEventListener('submit', function (e) {
    e.preventDefault()

    const inputEl = document.getElementById('name')

    if (!inputEl) {
      // ... handle empty input
      return
    }

    clerk
      .createOrganization({ name: inputEl.value })
      .then((res) => console.log(res))
      .catch((error) => console.log('An error occurred:', error))
  })
} else {
  // If there is no active user, mount Clerk's <SignIn />
  document.getElementById('app').innerHTML = `
    <div id="sign-in"></div>
  `

  const signInDiv = document.getElementById('sign-in')

  clerk.mountSignIn(signInDiv)
}

Feedback

What did you think of this content?

Last updated on