1.1.Bundling and publishing a design system library for Web and React Native
March 22, 2026
Misael Cázares
In this artiticle I’ll explain how to build a design systems library that works both on web and mobile using React Native and Tamagui. I’ll show how we can extend Tamagui capabilities and underlygin core system and UI libraries to build a higliby customizable designs system tthat we can share between our web and mobile applications, and distribute across different projects using AWS CodeArtifact and yarn, to manage and publish our build artifacts and types.
What is Tamagui?
Tamagui is an open source UI kit and styling system for React and React Native that lets you write a single codebase for both web and native apps with high performance. It provides a universal design system toolkit, with components, themes, and a styling engine that work across native mobile (using React Native) and web (via React DOM).
Here’re some of its main features:
- *Universal components — write once, run on iOS, Android, and web
- *Optimizing compiler — a build-time compiler that flattens component trees and converts styles to atomic CSS (on web) or StyleSheet (on native), making it significantly faster than runtime-only solutions.
- *Theming system — powerful token-based themes with support for dark mode, sub-themes, and dynamic switching
- *Animations — built-in animation drivers (CSS, Reanimated, or its own) with a unified API
- *Tamagui UI — a headless + styled component library (buttons, inputs, sheets, dialogs, etc.)
Here's a diagram of the final structure:

Initialize the Yarn 4 Monorepo
Add animations to Tamagui with an animation driver. Animation drivers are designed to be swappable, so you can use lightweight CSS animations or other web-focused animation libraries on the web, while using larger but more advanced libraries like Reanimated on native - all without having to change a line outside of configuration.
For this guide, we’ll use the React Native driver as an example, but you can choose from several Animation Drivers. For mount and unmount animations, see AnimatePresence.
Step 1 — Initialize the root project
{
"name": "universal-ui",
"private": true,
"workspaces": ["packages/", "apps/"],
"packageManager": "yarn@4.6.0"
}Then add it to your Tamagui config:
{
"name": "universal-ui",
"private": false,
"workspaces": ["packages/", "apps/"],
"packageManager": "yarn@4.6.0"
}Final file structure
{
"name": "universal-ui",
"private": true,
"workspaces": ["packages/", "apps/"],
"packageManager": "yarn@4.6.0"
}useMedia
If you add a transition prop, you must always keep the prop. If you need the animation to be disabled, pass false, null or even undefined if it suits you.
The spring-based animation drivers have expensive hooks that would degrade runtime performance if present on every component. As a workaround, the animation hooks are called conditionally based on whether the transition key is present in the props object.
So, <Square transition={isActive ? "bouncy" : null}/>
If you’d like to remove or add a transition prop after a component has already rendered, you’d have to change the key.