Create a workspace starter

Creating your own custom workspace generators allows you to quickly ramp up complete projects according to your standards. The Workspace is the key part that controls your component-workflow and where your components are managed. Standardizing it can help with onboarding and delivery of new apps and components.

Use the base workspace generator template followed by the name you want to give your generator.

For example:

bit create workspace-generator my-workspace
CopiedCopy
1 component(s) were created

company.scope/my-workspace
    location: scope/my-workspace
    env:      teambit.harmony/aspect
CopiedCopy

This will give you a collection of files inside the my-workspace namespace, as below:

├── index.ts
├── my-workspace.aspect.ts
├── my-workspace.docs.mdx
├── my-workspace.main.runtime.ts
└── template
    ├── files
    │   ├── git-ignore.ts
    │   ├── readme-file.ts
    │   └── workspace-config.ts
    └── index.ts
CopiedCopy

Customize the template

In the templates folder we have a folder of files that will get generated such as the git-ignore and readme file which can be modified to how you like. The workspace-config file is how you can configure your workspace, more on this later. The index file is the one that registers all these files with the correct name, path and which contents to return.

generateFiles: async (context: WorkspaceContext) => {
    return [
      {
        relativePath: 'workspace.jsonc',
        content: await workspaceConfig(context)
      },
      {
        relativePath: '.gitignore',
        content: gitIgnore()
      },
      {
        relativePath: 'README.md',
        content: readme()
      }
    ];
  },
CopiedCopy

In this file you will also see an array of components that you can add to be generated in your workspace. You can import any component here for developers to modify it to their liking. In the generated workspace the component will no longer be tied to the scope we are cloning it from.

importComponents: () => {
  return [
    {
      id: 'learn-bit-react.ecommerce/entity/product',
      path: 'ecommerce/entity/product',
    },
  ];
};
CopiedCopy

We can also change the name of our template and description:

export const workspaceTemplate: WorkspaceTemplate = {
  name: 'learn-bit-workspace',
  description: 'workspace template for learn bit',
CopiedCopy

We are now ready to modify our template and we can test it out by adding something very simple to see if it works.

Let's modify the readme to include a new line at the top:

export function readme() {
  return `hello world from my workspace generator`;
}
CopiedCopy

Testing generator locally

As we have modified our generator we will need to compile it:

bit compile
CopiedCopy

Now if we use our generator to generate a new workspace we will get one with our custom text in the ReadMe. We want to test this locally and not export our workspace template yet as we are still developing it.

Open a new terminal window separate from this workspace and run the following command:

bit new <templateName> <workspaceName> --load-from <localProjectPath> --aspect <workspaceGeneratorID>
CopiedCopy
  • The <templateName> is taken from the name in the template index file. It can be changed to anything you like. If you do change it just remember to run bit compile before using it.
  • The <workspaceName> is the name you want to call your workspace
  • The <localProjectPath> is where the path is to the project that holds the template generator. Type pwd in the terminal to get the correct path.
  • <workspaceGeneratorID> is the id of the workspace generator

For example, the command may look like this:

bit new learn-bit-workspace sports-store --load-from /Users/me/path/to/this/dir --aspect learn-bit-react.base-ui/workspace-generator
CopiedCopy

This will now create a new workspace for us in the directory sports-store.

cd sports-store
CopiedCopy

If we open the sports-store directory it in our editor and inspect it we will see the custom message we added in the readMe file.

Exporting workspace generator

Once we have finished all customizations and our generator is ready to be exported for other teams to use, we can then tag a new version of this component and export it to our organization's repo.

bit tag --all --message "my workspace generator"
CopiedCopy

Once tagging has finished, you can export it to your remote scope.

bit export
CopiedCopy

Using a custom generator

Once it has been exported, you can now generate a new workspace with the following:

  • bit new <templateName>
  • <workspaceName>
  • --aspect flag
  • your full <workspaceGeneratorID>

Example:

bit new learn-bit-workspace shoe-store --aspect learn-bit-react.base-ui/workspace-generator
CopiedCopy

Further customizing the workspace

Now we are ready to put this to use. The workspace.json file is the file we will configure the most, as this will set up our workspace for all projects across our organization. We want different teams to own different features and have their own workspaces but we want to have standards across all of them and this is how we can do it.

You are able to configure anything you want. For now, let's take a look at some example of things we can configure.

Put your team's logo in the workspace.

...
export async function workspaceConfig({
  name,
  defaultScope
}: WorkspaceContext) {
  const configParsed = await getWorkspaceConfigTemplateParsed();
  configParsed['teambit.workspace/workspace'].name = name;
  configParsed['teambit.workspace/workspace'].icon =
    'https://my-organization/my-logo.svg';
  ...

  return stringifyWorkspaceConfig(configParsed);
}
CopiedCopy

Set a defaultScope

The default scope can be added when we generate our workspace but if users forget to add the --default-scope <myScope> flag then we can set a default scope for them.

...
export async function workspaceConfig({
  name,
  defaultScope
}: WorkspaceContext) {
  const configParsed = await getWorkspaceConfigTemplateParsed();
  configParsed['teambit.workspace/workspace'].name = name;
  ...
  configParsed['teambit.workspace/workspace'].defaultScope =
    defaultScope || 'my organization';
  ...

  return stringifyWorkspaceConfig(configParsed);
}
CopiedCopy

Add a component generator

It is more than likely that you have already created your own component generator to generate components to you organization's liking that include the correct styling method, docs etc. We can register this component generator aspect so that it will be available for our workspace to use.

...
export async function workspaceConfig({
  name,
  defaultScope
}: WorkspaceContext) {
  const configParsed = await getWorkspaceConfigTemplateParsed();
  configParsed['teambit.workspace/workspace'].name = name;
  ...
  configParsed['teambit.generator/generator'] = {
    aspects: ['learn-bit-react.base-ui/component-generator']
  };
  configParsed['learn-bit-react.base-ui/component-generator'] = {};
  ...

  return stringifyWorkspaceConfig(configParsed);
}
CopiedCopy

Add dependencies

You may need to add some components as dependencies to your workspace or you may need to add peerDependencies.

...
export async function workspaceConfig({
  name,
  defaultScope
}: WorkspaceContext) {
  const configParsed = await getWorkspaceConfigTemplateParsed();
  configParsed['teambit.workspace/workspace'].name = name;
  ...
  configParsed['teambit.dependencies/dependency-resolver'].policy = {
    "dependencies": {
      "@company/scope.namespace.component": "0.0.1",
    },
    "peerDependencies": {
      "react": "^16.8.0 || ^17.0.2",
      "react-dom": "^16.8.0 || ^17.0.2"
    }
  ...
 return stringifyWorkspaceConfig(configParsed);
}
CopiedCopy

Additional configuration

You can add any config to the workspace.json file using configParse[...].keyName ={}