Skip to content

<OrganizationProfile />

Organization profile dialog on the General tab, with logo, name, slug and the leave and delete actions

<OrganizationProfile /> is the settings dialog for the active organization. Owners and admins edit its name, slug and logo, manage members and invitations, and the owner can delete it. It opens from the settings icon in <OrganizationSwitcher /> through <OrganizationProfileHost />. It needs organizations: true in src/convex/auth.constants.ts.

Quick start

The base registry item mounts <OrganizationProfileHost /> once in the root layout, behind the organizations flag. This is the relevant part of that layout; the rest of it, such as createSvelteAuthClient andthe header, stays as installed:

src/routes/+layout.svelte (excerpt)
src/app/layout.tsx (excerpt)

In SvelteKit, the host needs the <AuthProvider> ancestor shown above.

In Next.js, the host needs the ConvexClientProvider.

Invitations need sendEmails: true as well (see Organizations).

What it includes

On larger screens the dialog has a tab list on the left. On mobile it opens on a list of the tabs, and each tab slides in as its own panel with a back button.

General

Everyone who opens the dialog sees this tab. It shows the organization’s logo, name and slug.

  • Name and slug: owners and admins select either one to edit it inline. A slug may contain lowercase letters, numbers and hyphens, and must be unused. When the current path contains the old slug, saving it rewrites the URL to the new one.
  • Logo: selecting the logo lets the user pick an image and crop it; it’s uploaded to Convex storage through api.storage.generateUploadUrl.

Better Auth’s organization plugin rejects these changes from members on the server.

Below the settings are the two actions that end a membership:

  • Leave organization is shown when the organization has more than one member. An owner has to choose a new owner from the other members before leaving. After leaving, the user goes to /.
  • Delete organization is shown to the owner only. It asks for confirmation, deletes the organization and its logo, makes another of the user’s organizations active, and navigates to /. A user can’t delete their last organization: the mutation refuses with “Cannot delete organization. At least one organization must remain.”

Members

Members tab with a searchable member list, role badges and a pending invitations list

Shown to owners and admins only. It has two lists, Members and Invitations, each with its count, and an Invite members button.

  • Members lists everyone in the organization, owner first, then admins, then members, with a search field. Each row lets you change the member’s role between Admin and Member, or remove them after a confirmation. On small screens, selecting a member opens these actions in a drawer. The owner’s row and your own can’t be edited.
  • Invitations lists pending invitations with their email, role and expiry date, with a search field. Each one can be revoked.
  • Invite members takes one or more comma-separated email addresses and a role, Member or Admin, and sends an invitation to each. Without sendEmails: true, the form says that sending emails isn’t enabled.

The invitation email links to /api/organization/accept-invitation/<id>, a page the organizations/routes item installs. Organizations covers the acceptance flow.

Props

  • open tells the profile whether its dialog is open. When it turns false, the mobile view returns to the tab list for the next opening. The host passes it.
  • onSuccessfulDelete runs after the organization is deleted, before the navigation to /. The host uses it to close the dialog.
  • initialData takes the data loaded on the server, so the tabs render on first paint. The types come from #lib/auth/types.js; the base/ssr item’s src/routes/+layout.server.ts returns this data as data.initialData.

Render <OrganizationProfile /> directly only if you build your own dialog or page around it; the host already handles the URL and the dialog.

Behavior

<OrganizationProfileHost /> opens the dialog while the URL has ?dialog=organization-profile and the user is signed in. The selected tab is kept in a tab query parameter, so a reload returns to the same tab. On desktop, switching tabs replaces the history entry, so the browser’s back button closes the dialog. On mobile, opening a tab adds a history entry, so back, including the iOS back swipe, returns to the tab list first.