Skip to main content
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.

This guide demonstrates how to use Clerk's API to build a custom flow for creating organizations.

The following example uses the useOrganizationList() hook to access 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-based framework.

app/components/CreateOrganization.tsx
'use client'

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

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

  if (!isLoaded) return null

  const handleSubmit: FormEventHandler<HTMLFormElement> = async (e) => {
    e.preventDefault()
    createOrganization({ name: organizationName })
      .then((res) => {
        console.log(res)
      })
      .catch((err) => {
        // See https://clerk.com/docs/custom-flows/error-handling
        // for more info on error handling
        console.error(JSON.stringify(err, null, 2))
      })
    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(pubKey)
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