Inspired by BulletProof React, I applied its codebase architecture concepts to the Twenty codebase.
This article focuses only on the API layer in Twenty codebase.
Prerequisite
Approach
The approach we take is simple:
Pick a route
Locate this route in Twenty codebase.
Review how the api layer is implemented.
We repeat this process for 3 pages to establish a common pattern, see if there’s any exceptions.
In this part 1.2, you will learn the API layer in the /create/workspace route and see what library is used to create a workspace, where these files are located.
I reviewed the /create/workspace route and found that the following files give us a clear picture about API layer.
CreateWorkspace.tsx
In the CreateWorkspace.tsx, you will find the below code:
import { useMutation } from '@apollo/client/react';
import { ActivateWorkspaceDocument } from '~/generated-metadata/graphql'; export const CreateWorkspace = () => { ... const [activateWorkspace] = useMutation(ActivateWorkspaceDocument); ... // Form const { control, handleSubmit, formState: { isValid, isSubmitting }, } = useForm<Form>({ mode: 'onChange', defaultValues: { name: '', }, resolver: zodResolver(validationSchema), }); const onSubmit: SubmitHandler<Form> = useCallback( async (data) => { try { setTimeout(() => { setPendingCreationLoaderStep(PendingCreationLoaderStep.Step1); }, 500); setTimeout(() => { setPendingCreationLoaderStep(PendingCreationLoaderStep.Step2); }, 2000); setTimeout(() => { setPendingCreationLoaderStep(PendingCreationLoaderStep.Step3); }, 5000); const result = await activateWorkspace({ variables: { input: { displayName:data.name, }, }, }); if (isDefined(result.error)) { throw result.error ?? new Error(Unknown error); } await refreshObjectMetadataItems(); await fetchAndLoadIndexViews(); await loadCurrentUser(); setNextOnboardingStatus(); } catch (error: any) { setPendingCreationLoaderStep(PendingCreationLoaderStep.None); enqueueErrorSnackBar({ apolloError: CombinedGraphQLErrors.is(error) ? error : undefined, }); } }, [ activateWorkspace, enqueueErrorSnackBar, loadCurrentUser, refreshObjectMetadataItems, fetchAndLoadIndexViews, setNextOnboardingStatus, t, ], );
This below piece of code handles creating the workspace.
const result = await activateWorkspace({ variables: { input: { displayName: data.name, }, }, });
Remember, Twenty CRM uses GraphQL. Let’s learn more about activateWorkspace function.
activateWorkspace.ts
In activateWorkspace.ts, you will find the below code:
import { gql } from '@apollo/client'; export const ACTIVATE_WORKSPACE = gq mutation ActivateWorkspace($input: ActivateWorkspaceInput!) { activateWorkspace(data: $input) { id } } ;
Below is an example for GraphQL mutations I picked from their docs.
Operation
mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) { createReview(episode: $ep, review: $review) { stars commentary } }
Variables
{ "ep": "JEDI", "review": { "stars": 5, "commentary": "This is a great movie!" } }
Response
{ "data": { "createReview": { "stars": 5, "commentary": "This is a great movie!" } } }
Learn more about GraphQL mutations.
About me:
Hey, my name is Ramu Narasinga. Email: ramu.narasinga@gmail.com
Tired of AI slop?
I spent 3+ years studying OSS codebases and wrote 350+ articles on what makes them production-grade. I built an open source tool that reviews your PR against your existing codebase patterns.
Your codebase. Your patterns. Enforced.

Top comments (0)