Building applications that work seamlessly across multiple platforms has been a long-standing challenge in mobile development. The dream of "write once, run anywhere" has driven the creation of numerous frameworks and libraries, each with their own strengths and limitations. Tamagui emerges as a modern solution that addresses these challenges by providing a unified approach to styling and component development across React web and React Native mobile platforms.
Unlike other cross-platform solutions that offer limited compatibility between platforms, Tamagui provides true 100% parity between React and React Native, meaning you can write your UI code once and have it work properly on both web and mobile without platform-specific adjustments or workarounds.
What makes Tamagui particularly special is that it operates both at runtime and compile-time, giving developers the flexibility to develop quickly while still achieving excellent performance when needed. By implementing a cohesive design system, teams can maintain consistency across all touchpoints while significantly reducing development time.
Key benefits that make Tamagui a compelling choice for cross-platform development
True Cross-Platform Parity
Write your UI code once and have it work identically across React web and React Native mobile platforms, eliminating the need for separate codebases.
Performance Optimization
The optional compiler transforms styled components into optimized output with atomic CSS for web and hoisted styles for native.
Familiar Styling API
Built on React Native's styling foundation with additional modern CSS features, making it easy to learn and adopt.
Comprehensive UI Kit
Includes both styled and unstyled components that adapt to each platform, covering common UI elements out of the box.
Understanding Tamagui's Architecture
At its core, Tamagui consists of three main components that work together to provide a complete design system solution.
@tamagui/core
The foundation style library that expands on React Native's style API. This package provides the fundamental styling capabilities that power the entire system, extending React Native's approach with additional features inspired by modern CSS.
@tamagui/static
An optional optimizing compiler that significantly improves performance. This compiler analyzes your code and optimizes it for each target platform. On the web, it converts styled components into simple HTML elements with atomic CSS. On mobile, it hoists style objects for better runtime performance.
tamagui
A comprehensive UI kit with components that adapt to each platform. This UI kit includes both styled and unstyled components that you can use to build common UI elements without having to create everything from scratch.
By understanding these three pillars--core styling, static optimization, and the UI kit--you can leverage Tamagui effectively to build scalable, maintainable cross-platform applications.
Creating Your Design System: Step by Step
Step 1: Create a Package for Your Design System
Your design system needs to live in its own npm module, which can be private to just your application. This approach allows you to later direct the compiler to look for that package and enables proper tree-shaking and optimization.
Design systems can extend off each other. The tamagui package extends off @tamagui/core, which contains simple base-level components. You can build upon existing components or start from scratch with just View and Text.
Your package.json should include proper module configuration and use @tamagui/build to ensure JSX is preserved in the output for compiler optimization.
Step 2: Create Your Design System Configuration
The configuration file is where you define the foundation of your design system with tokens, themes, media queries, and shorthands. Tokens provide reusable values for colors, spacing, font sizes, and more. Themes are collections of token values that enable features like light and dark mode. Media queries define breakpoints for responsive design. Shorthands are aliases for longer style property names.
Step 3: Define and Export Components
Create custom components using the styled() function or re-export from tamagui. Proper exports enable the compiler to recognize and optimize your components when used in applications.
Step 4: Set Up Your Build Configuration
Configure your build system to work with Tamagui's compiler. The setup differs for Webpack (using tamagui-loader), Next.js (using withTamagui plugin), or React Native (using Babel plugin). For modern React applications, these integrations are straightforward to implement.
1import { createFont, createTokens, createTamagui } from 'tamagui'2 3// Define size tokens4const size = {5 0: 0,6 1: 4,7 2: 8,8 3: 16,9 4: 24,10}11 12// Define space tokens13const space = {14 ...size,15 '-1': -4,16 '-2': -8,17}18 19// Create font definition20const defaultFont = createFont({21 family: 'Arial',22 size: { 1: 14, 2: 18, 3: 22 },23 lineHeight: { 1: 15, 2: 20 },24 weight: { 4: '300', 7: '600' },25 letterSpacing: { 4: 0, 7: -1 },26})27 28// Create tokens29const tokens = createTokens({30 size,31 space,32 font: { title: defaultFont, body: defaultFont },33 color: {34 primary: '#3498db',35 secondary: '#2ecc71',36 background: '#ffffff',37 text: '#333333',38 },39 radius: { 0: 0, 1: 4, 2: 8, 3: 16 },40})41 42// Define shorthands43const shorthands = {44 m: 'margin', p: 'padding',45 mt: 'marginTop', mb: 'marginBottom',46 px: 'paddingHorizontal', py: 'paddingVertical',47} as const48 49// Define media queries50const media = {51 sm: { maxWidth: 640 },52 md: { maxWidth: 768 },53 lg: { maxWidth: 1024 },54 xl: { maxWidth: 1280 },55}56 57// Create configuration58const config = createTamagui({59 defaultTheme: 'light',60 shorthands,61 media,62 tokens,63 themes: {64 light: {65 background: tokens.color.background,66 color: tokens.color.text,67 },68 dark: {69 background: '#121212',70 color: '#ffffff',71 },72 },73})74 75export default configDefining and Exporting Components
Once your configuration is set up, you can create custom components for your design system. Using the styled() function, you can build reusable components that leverage your design tokens and themes.
Creating Custom Components
The styled() function accepts a base component and a style object or function. Variants allow you to define different styles based on props, making components flexible and reusable across your application.
Exporting from Your Package
Proper exports from your design system package enable the compiler to recognize and optimize components. When components are properly exported and the build is configured correctly, the compiler can generate optimized output that significantly improves performance.
Building a well-structured component library is essential for maintaining consistency across your mobile applications. This approach ensures that every team member uses the same validated components, reducing inconsistencies and accelerating development cycles.
1import { GetProps, YStack, styled } from 'tamagui'2 3export const Circle = styled(YStack,4 alignItems: 'center',5 justifyContent: 'center',6 borderRadius: 100_000_000,7 overflow: 'hidden',8 9 variants: {10 size: {11 '...size': (size, tokens) => ({12 width: tokens.size[size] ?? size,13 height: tokens.size[size] ?? size,14 }),15 },16 }17)18 19export type CircleProps = GetProps<typeof Circle>20 21// Usage in your app22import { Circle } from '@yourapp/components'23 24function MyComponent() {25 return (26 <Circle size="$large" backgroundColor="$primary" />27 )28}Using Tamagui in Your Application
Using your design system in an application is straightforward. First, wrap your application with the Tamagui.Provider component and pass in your configuration. This makes your tokens and themes available throughout your component tree.
Token Access
With the provider in place, you can use the '$' prefix to access token values throughout your application. This approach ensures consistency while keeping your code readable and maintainable.
Component Usage
Import and use your design system components just like any other React component. The components automatically adapt to your tokens and themes, providing a consistent look and feel across your entire application.
Build Setup
Configure your build system to enable compiler optimization. For Webpack, use the tamagui-loader. For Next.js, use the withTamagui plugin. For React Native, configure the Babel plugin. Each approach tells the compiler where to find your components for optimization.
Integrating a design system into your development workflow significantly improves team productivity and consistency. Teams can iterate faster because changes to the design system propagate automatically to all consuming applications.
1import { TamaguiProvider } from 'tamagui'2import config from './tamagui.config'3import { YStack, Text, XStack, Button } from '@yourapp/components'4 5export default function App() {6 return (7 <TamaguiProvider config={config}>8 <MyAppContent />9 </TamaguiProvider>10 )11}12 13function MyAppContent() {14 return (15 <YStack padding="$4" space="$2">16 <Text fontSize="$6" fontWeight="bold">17 Hello Tamagui18 </Text>19 20 <XStack space="$2">21 <Button theme="blue">Primary</Button>22 <Button theme="gray">Secondary</Button>23 </XStack>24 </YStack>25 )26}Theming and Responsive Design
Theming System
Tamagui's theming system makes it easy to support multiple themes including light and dark modes. Define themes in your configuration with collections of token values, then apply them using the Theme component or programmatically with the useTheme hook.
Themes enable consistent color schemes across your application while allowing instant switching between different visual appearances. This is essential for supporting user preferences like system-wide dark mode.
Responsive Design
For responsive design, Tamagui provides the useMedia hook for programmatic access to screen size information. You can also use responsive props directly in styled components using breakpoint prefixes like $sm, $md, and $lg.
This dual approach--hooks for conditional logic and props for styling--gives you flexibility in how you implement responsive layouts while maintaining consistency with your design tokens.
Creating responsive user interfaces that adapt to different screen sizes is crucial for modern applications. Tamagui's unified approach means you write responsive styles once and they work identically across platforms.
Performance Benefits
One of the most compelling reasons to adopt Tamagui for your design system is the performance optimization through its compiler. When enabled, the compiler analyzes your styled components and generates highly optimized output.
Web Optimization
On the web, the compiler converts styled components into simple HTML elements with atomic CSS. This means that if multiple components use the same style values, they share CSS classes instead of generating duplicate styles. This approach, inspired by atomic CSS frameworks, results in smaller CSS bundle sizes and faster rendering.
Native Optimization
On React Native, the compiler hoists style objects, reducing the runtime overhead of style computation. This can result in measurable performance improvements, especially for applications with many components or frequent re-renders.
Verification
You can verify the compiler is working by checking your build output or using the debug pragma. The output will show metrics indicating how many components were optimized and flattened, giving you confidence that your design system is generating efficient code.
Performance optimization is a key consideration when building scalable web applications. The compiler ensures that the developer experience remains excellent without sacrificing the end-user experience.
Integration with Expo
Tamagui works great with Expo, a popular framework for building React Native applications. The setup process involves installing the necessary packages, configuring Babel, and creating your configuration file.
Installation
Install Tamagui and its Babel plugin in your Expo project. The plugin handles the compilation step during the build process, enabling optimization without requiring changes to your development workflow.
Babel Configuration
Add the Tamagui Babel plugin to your babel.config.js with appropriate options. The logTimings option helps you see the compiler at work during development, while disableExtraction can speed up development builds.
Configuration File
Create your tamagui.config.ts file with tokens, themes, and other settings. The configuration should align with your design system's specifications and be referenced by the Babel plugin.
With Expo and Tamagui configured together, you get the full power of cross-platform development with excellent performance characteristics for both web and native targets. This combination is particularly valuable when building mobile applications that need to reach users on multiple platforms efficiently.
1module.exports = function(api) {2 api.cache(true)3 return {4 presets: ['babel-preset-expo'],5 plugins: [6 ['@tamagui/babel-plugin', {7 components: ['tamagui'],8 config: './tamagui.config.ts',9 logTimings: true,10 disableExtraction: process.env.NODE_ENV === 'development',11 }],12 ],13 }14}Conclusion
Tamagui offers a powerful solution for building cross-platform applications with React and React Native. Its combination of a familiar styling API, performance optimizations through the compiler, and comprehensive UI kit makes it a compelling choice for developers looking to create design systems that work seamlessly across platforms.
Whether you're building a simple app or a complex enterprise application, Tamagui provides the tools you need to create consistent, performant user interfaces. The ability to adopt Tamagui gradually--starting with just the styling system and adding the compiler and UI components as needed--makes it accessible for both new projects and existing applications.
The step-by-step process for creating a design system, from setting up a dedicated package to configuring tokens and themes, provides a clear path to building maintainable, scalable UI libraries. The compile-time optimization ensures you don't have to sacrifice performance for developer experience, making Tamagui an excellent foundation for any cross-platform project.
Ready to implement a design system for your next project? Our web development team has experience building scalable, performant design systems for React and React Native applications.
Frequently Asked Questions
What is Tamagui and how does it differ from other cross-platform solutions?
Tamagui is a styling and UI kit library that provides true 100% parity between React web and React Native. Unlike solutions that offer limited compatibility, Tamagui's components work identically on both platforms without platform-specific conditionals. It also includes an optional compiler that optimizes styles for better performance.
Do I need to use the compiler with Tamagui?
The compiler is optional but highly recommended for production applications. During development, you can disable extraction for faster build times. When ready to deploy, enabling the compiler optimizes your styled components into atomic CSS for web and hoisted styles for native, resulting in better runtime performance.
Can I use Tamagui with existing React Native projects?
Yes, Tamagui can be added to existing React Native projects. Simply install the packages, configure the Babel plugin, and create your configuration file. You can gradually adopt Tamagui components alongside your existing styling, making migration straightforward.
How does Tamagui theming work?
Tamagui's theming system is built into its configuration. You define themes as collections of token values (colors, spacing, etc.) and then switch between them using the Theme component or programmatically with useTheme. This enables features like dark mode support out of the box.
What is the difference between @tamagui/core and tamagui packages?
@tamagui/core provides the foundational styling library with basic View and Text components. The tamagui package includes the complete UI kit with many more styled components like Button, Input, Card, and more. Most projects use tamagui, while @tamagui/core is for minimal custom implementations.