While building the web version of Paw, a Mac application, I chose to build its UI around a reusable component library. Later, our CEO decided to make those components available across the company. I extracted the library from the application and developed it into RapidAPI's shared UI Toolkit.
I built the initial architecture and component library, created Storybook and integration documentation, and worked with designers on components and themes. I continued developing the toolkit as other engineers joined and helped product teams adopt it. By late 2022, 13 projects consumed it as a dependency.
A library without shared application ownership
I put the toolkit in a dedicated monorepo and published its components as private packages. Product teams installed them as dependencies and kept their application code in their own repositories. They retained control over their applications and could contribute changes to the toolkit through pull requests.
I considered Bit.dev, but Storybook, private packages, and versioning already covered our needs. Adding Bit.dev would have introduced another ecosystem and contribution workflow. I planned to start with compiled packages installed as regular dependencies. A shared development workspace between the library and an application could provide live updates, but would require extra build configuration.
That boundary gave us a shared place to develop components while leaving application-specific work with the product teams. It also made the consuming projects part of the library's design problem: a component API or dependency change had consequences outside our repository.
A bridge for Vue teams
Some teams could not use a React component library directly because their applications used Vue. Teams were moving to React following a decision by the CEO, but needed to use the shared components in their existing applications during the transition.
I proposed using Vuera, an existing library for using React components inside Vue applications. I documented the integration, including the React dependencies, Vuera setup, and theme settings needed by the wrapped components.
The compromise was an additional integration layer and the React runtime inside a Vue application. We could reuse the existing components without maintaining a second native Vue implementation. The toolkit remained a React library, with Vuera providing a bridge during migration.
Supporting the engineers using it
I created Storybook and the integration documentation so engineers could inspect the components and see how to use them. The guides covered installation, basic usage, layout, customization, and Vue integration.
Installation involved a private package registry. Using the library also meant setting up its theme and fonts. I documented those steps alongside working examples.
I also met with engineers from other teams to answer questions and help them adopt the toolkit. The Vue adapter addressed one concrete obstacle; the documentation gave teams instructions they could return to without needing another meeting.
Supporting changes across consuming projects
In May 2021, I set up CI to run the library's tests and send Storybook builds to Chromatic for visual regression checks. Engineers could inspect test results and component previews when reviewing changes to the shared library.
Breaking changes still required work in the applications using it. For UI-lib 2, I wrote a migration guide covering changes to peer dependencies, ThemeProvider imports, and Box and Flex usage. It gave engineers specific steps to update their integrations with the new library version.
In January 2023, I replaced Lerna's release workflow with Changesets to manage package versions and changelogs. Publishing a library version and integrating it into a product remained separate steps: each team consumed published packages from its own repository.
Shared foundations and local needs
I worked with designers to keep the implementation aligned with Figma, including typography, colors, and component behavior. Changes to the common foundation could then be delivered through the toolkit instead of being implemented separately in each application.
Consumers still needed ways to adapt components. I added theme-customization utilities and component-level style overrides. A team could extend the shared theme and adjust a component's styles without copying its implementation into the application.
I also introduced polymorphic component types and migrated foundational components such as Box and Typography. They could render different underlying elements while retaining the shared styling API. This gave application engineers another way to adapt the library to their interfaces.
These extension points added maintenance work to the library. The theme structure, overrides, and component types became APIs that consuming projects depended on. Replacing the styling approach would have required considering those integrations as well as the component implementation.
The result
By late 2022, the UI Toolkit had become a shared standard used as a dependency in 13 projects, including a proof-of-concept project. Vue-based projects could use the same components during their transition to React. Teams had Storybook, integration and migration guides, and versioned packages for adopting the library and its updates.