Removing Organizations from your Project

If your project does not need Organizations, follow this tutorial to remove them from your project

ยท5 min read
Cover Image for Removing Organizations from your Project

While having teams and organizations is an essential SaaS feature where users can share assets and resources with teammates, not every SaaS needs it.

In fact, many have asked me how to remove organizations and only keep individual users. So, in this recipe, I will write down my thoughts on removing organizations from your project.

There are two main ways to remove organizations:

  1. The more challenging way is refactoring the project and removing the code related to organizations
  2. The second and more straightforward way is to keep organizations, while hiding all the related UI. In this way, each user belongs to their organization. This way is more future-proof: if your SaaS will need refactoring for adding teammates to your user's accounts, the code is still there, and you will only need to show it.

Since the first way is highly challenging and will cause problems pulling changes from the latest version, I suggest you try the second solution: we will create organizations behind the scenes for each user, but these won't be shown in the front end.

Here is the list of changes we need to add:

  1. Skip onboarding: automatically create an Organization for the user
  2. Remove Organizations dropdown from the headers
  3. Remove the "Organization" tab within the settings pages

The above should take you less than 2 minutes to implement. Let's get started!

NB: This post is specific to the Next.js Firebase SaaS Kit. With that said - the same concepts apply to the others, but you need to find the equivalent files and components.

Skipping the Onboarding flow

You can change the onboarding flow and add your own steps if you need your users to set up their accounts. The organization, though, will be created without user input.

Let's update the Onboarding page at pages/onboarding/index.tsx. First, we will predefine the onboarding values, so that the form can easily be skipped. To do so, we will update the defaultValues object of the useForm hook:

const Onboarding = () => { const currentStep = 2; const organization = `Organization`; // or whatever you want to call it const form = useForm({ defaultValues: { data: { organization, invites: [] as Invite[], }, currentStep }, }); // ... more code here };

As you can see from the above, we predefined the organization value. This will be used to create the organization behind the scenes. Additionally, by setting the currentStep to 2, we will skip the first two steps of the onboarding flow.

This will automatically kick off the onboarding API request and create an organization named Organization.

Redirecting to Dashboard

We also want to redirect users away from the onboarding flow. To do so, we will update the CompleteOnboardingStep at src/components/onboarding/CompleteOnboardingStep.tsx.

import { useRouter } from 'next/router'; export const CompleteOnboardingStep: React.FCC<{ data: CompleteOnboardingStepData; }> = ({ data }) => { const router = useRouter(); const { trigger, error, data: response } = useCompleteOnboardingRequest(); const onboardingCompleteRequested = useRef(false); useEffect(() => { void (async () => { // React will run the effect twice // so we use the ref to prevent it if (!onboardingCompleteRequested.current) { onboardingCompleteRequested.current = true; const result = await trigger(data); if (result.returnUrl) { router.replace(result.returnUrl) } } })(); }, [data, router, trigger]); // ...

In the above we added the router.replace function to redirect the user to the dashboard.

  1. First you need to import useRouter from next/router at the top of the file
  2. Then, we inject the router using the useRouter hook
  3. Finally, we use router.replace to navigate to the dashboard once the onboarding flow is complete

Hiding the Organizations dropdown

To hide the organizations dropdown, we will update the headers of the layout you have chosen to use.

If you have chosen the sidebar layout, open the component AppSidebar.tsx at src/components/layouts/sidebar/AppSidebar.tsx and remove the code below:

<SidebarContent className={'mt-4'}> <OrganizationsSelector displayName={!ctx.collapsed} /> </SidebarContent>

In this way - the user will never see the organizations dropdown.

You can replace the above with your Logo importing the component Logo from src/core/ui/Logo.tsx.

<SidebarContent className={'mt-4'}> <Logo /> </SidebarContent>

Header Layout

If you are using the header layout, you need to remove the organizations dropdown from the header.

Open the component AppHeaderWithMenu at src/components/layouts/header/AppHeaderWithMenu.tsx and remove the component rendered by the constant OrganizationsDropdown:

<div className={'hidden lg:flex'}> <OrganizationsSelector displayName={true} /> </div>

Removing the Settings pages

Finally, we want to remove the settings pages. To do so, we need to first remove them from the settings navigation menu:

We open the component SettingsPageContainer.tsx and then remove the organization settings from the links array:

const links = [ { path: '/settings/profile', i18n: 'common:profileSettingsTabLabel', }, // remove the object below! { path: '/settings/organization', i18n: 'common:organizationSettingsTabLabel', }, { path: '/settings/subscription', i18n: 'common:subscriptionSettingsTabLabel', }, ];

Optionally, remove the pages at settings/organization.

Alternatively, you can automatically redirect them somewhere else using the getServerSideProps function on each page:

export function getServerSideProps(ctx) { return ctx.redirect(configuration.paths.appHome); }

Removing Organizations Page from Main Sidebar

To remove the Organizations page from the main sidebar, open the config src/navigation.config.tsx and remove the object pointing to the organizations page.

Updating the Firestore Rules

Finally, remove the rules to create new organizations in Firestore rules. You should only allow to read from them:

match /organizations/{organizationId} { allow read: if userId() in existingData().members; }

Final thoughts

That's it! While your application will still create an organization for each user, these do not exist as far as your SaaS users are concerned.

In terms of future-proofing, hiding organizations allows you to add them in the longer term if users need a way to share stuff with teammates.