Tailwind CSS Integration Guide
Status: ✅ Phase 1.2 Complete
Date: October 11, 2025
Branch: feat/tailwind-integration
Overview
Section titled “Overview”This guide documents the Tailwind CSS and NativeWind integration for the CloudAlt monorepo. The setup enables utility-first CSS styling across both web and React Native mobile apps, with a shared design token system.
Architecture
Section titled “Architecture”packages/ config/ tailwind-preset.js # Shared Tailwind preset with design tokens theme/ # Design tokens (colors, typography, spacing)
apps/ [brand]/[app]/mobile/ tailwind.config.js # App-specific Tailwind config (extends preset) babel.config.js # Babel config with NativeWind plugin metro.config.js # Metro config for NativeWind support [brand]/[app]/web/ tailwind.config.js # App-specific Tailwind config (extends preset) postcss.config.js # Tailwind v4 PostCSS plugin vite.config.ts # Vite aliases for web-only bundlingInstallation
Section titled “Installation”Tailwind CSS and NativeWind are installed at the root level:
{ "devDependencies": { "tailwindcss": "^4.1.14", "nativewind": "^4.2.1" }}Shared Tailwind Preset
Section titled “Shared Tailwind Preset”Location: packages/config/tailwind-preset.js
The shared preset includes:
- Design token colors (primary, secondary, semantic colors)
- Typography scales (font families, sizes, line heights)
- Spacing system (extends Tailwind default)
- Border radius scale
- Box shadows
- Custom animations (fade-in, slide-up, etc.)
Usage in Apps
Section titled “Usage in Apps”Each mobile app extends the shared preset:
module.exports = { presets: [require('@cloudalt-frontend/config/tailwind-preset')], content: [ './src/**/*.{js,jsx,ts,tsx}', './App.{js,jsx,ts,tsx}' ], // App-specific overrides (optional) theme: { extend: { colors: { brand: '#custom-color' } } }};NativeWind Setup
Section titled “NativeWind Setup”1. Babel Configuration
Section titled “1. Babel Configuration”Update babel.config.js to include NativeWind plugin:
module.exports = function (api) { api.cache(true); return { presets: ['babel-preset-expo'], plugins: [ 'nativewind/babel', // ... other plugins ], };};2. Metro Configuration
Section titled “2. Metro Configuration”Update metro.config.js for NativeWind CSS support:
const { getDefaultConfig } = require('expo/metro-config');const { withNativeWind } = require('nativewind/metro');
const config = getDefaultConfig(__dirname);
module.exports = withNativeWind(config, { input: './global.css', // Optional: global CSS file});3. TypeScript Support
Section titled “3. TypeScript Support”Add type definitions for NativeWind (if using TypeScript):
/// <reference types="nativewind/types" />Usage Examples
Section titled “Usage Examples”Web (Vite) Setup
Section titled “Web (Vite) Setup”In each web app, configure Tailwind and Vite as follows:
- PostCSS plugin (Tailwind v4):
apps/.../web/postcss.config.js
module.exports = { plugins: { '@tailwindcss/postcss': {}, autoprefixer: {}, },};- Tailwind config: extend the shared preset and set content globs
/** @type {import('tailwindcss').Config} */module.exports = { presets: [require('@cloudalt-frontend/config/tailwind-preset')], content: ['./src/**/*.{js,jsx,ts,tsx,html}', './index.html'], darkMode: 'class',};- Vite aliases to avoid React Native code in web bundles and to target the web entry of shared UI
resolve: { alias: { 'react-native$': 'react-native-web', 'react-native-svg': 'react-native-svg-web', '@cloudalt-frontend/ui': '@cloudalt-frontend/ui/index.web', },},optimizeDeps: { exclude: ['react-native'],},This ensures the web build never pulls Flow-typed RN source files and consistently uses the web barrel of shared UI.
Basic Styling
Section titled “Basic Styling”import { View, Text } from 'react-native';
export function MyComponent() { return ( <View className="flex-1 bg-primary-500 p-4"> <Text className="text-white text-lg font-bold"> Hello, Tailwind! </Text> </View> );}Responsive Design
Section titled “Responsive Design”<View className="w-full md:w-1/2 lg:w-1/3"> <Text className="text-sm sm:text-base md:text-lg"> Responsive text </Text></View>Dark Mode Support
Section titled “Dark Mode Support”<View className="bg-white dark:bg-gray-900"> <Text className="text-gray-900 dark:text-white"> Adaptive text </Text></View>Custom Animations
Section titled “Custom Animations”<View className="animate-fade-in"> <Text>Fading in...</Text></View>Design Token Integration
Section titled “Design Token Integration”Current State (Phase 1.2)
Section titled “Current State (Phase 1.2)”The Tailwind preset includes placeholder design tokens. These should be replaced with tokens from packages/theme once the design system is fully implemented.
Future Enhancement (Phase 2)
Section titled “Future Enhancement (Phase 2)”const designTokens = require('@cloudalt-frontend/theme');
module.exports = { theme: { extend: { colors: designTokens.colors, fontFamily: designTokens.typography.families, fontSize: designTokens.typography.sizes, // ... } }};Testing
Section titled “Testing”Unit Tests
Section titled “Unit Tests”NativeWind classes are processed at build time. For testing:
import { render } from '@testing-library/react-native';
test('renders with Tailwind classes', () => { const { getByText } = render( <Text className="text-primary-500">Test</Text> ); expect(getByText('Test')).toBeTruthy();});Visual Regression
Section titled “Visual Regression”Use Storybook (Phase 1.3) to create stories for components with Tailwind styling:
export const PrimaryButton = () => ( <Button className="bg-primary-500 text-white px-4 py-2 rounded-lg"> Primary Button </Button>);Migration Guide
Section titled “Migration Guide”Converting from StyleSheet to Tailwind
Section titled “Converting from StyleSheet to Tailwind”Before:
const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#0ea5e9', padding: 16, }, text: { color: '#ffffff', fontSize: 18, fontWeight: 'bold', },});
<View style={styles.container}> <Text style={styles.text}>Hello</Text></View>After:
<View className="flex-1 bg-primary-500 p-4"> <Text className="text-white text-lg font-bold">Hello</Text></View>Hybrid Approach (Gradual Migration)
Section titled “Hybrid Approach (Gradual Migration)”You can mix Tailwind classes with StyleSheet:
<View className="flex-1 bg-primary-500" style={customStyles.container}> <Text className="text-white">Hybrid styling</Text></View>Performance Considerations
Section titled “Performance Considerations”Build Time
Section titled “Build Time”NativeWind processes className props at build time, converting them to React Native styles. This means:
- ✅ No runtime performance penalty
- ✅ Tree-shaking removes unused styles
- ✅ Type-safe with TypeScript
Bundle Size
Section titled “Bundle Size”- Tailwind utilities are purged based on
contentglob patterns - Only used classes are included in the final bundle
- Typical overhead: < 5KB gzipped
Troubleshooting
Section titled “Troubleshooting”Classes Not Applying
Section titled “Classes Not Applying”-
Check content paths in tailwind.config.js
content: ['./src/**/*.{js,jsx,ts,tsx}'] -
Verify Babel plugin is loaded
Terminal window yarn nx run [app]:start --clear -
Check Metro bundler output for errors
TypeScript Errors
Section titled “TypeScript Errors”If you see className type errors, ensure nativewind/types is referenced:
/// <reference types="nativewind/types" />Metro Bundler Issues
Section titled “Metro Bundler Issues”Clear Metro cache if styles aren’t updating:
yarn nx run [app]:start --clear# ornpx expo start --clearIDE Support
Section titled “IDE Support”VS Code Extensions
Section titled “VS Code Extensions”Recommended extensions for Tailwind development:
- Tailwind CSS IntelliSense: Autocomplete, syntax highlighting, linting
- PostCSS Language Support: Syntax highlighting for CSS
IntelliSense Configuration
Section titled “IntelliSense Configuration”Add to .vscode/settings.json:
{ "tailwindCSS.experimental.classRegex": [ ["className\\s*=\\s*['\"`]([^'\"`]*)['\"`]", "([\\w-]+)"] ], "tailwindCSS.includeLanguages": { "typescript": "javascript", "typescriptreact": "javascript" }}Nx Integration
Section titled “Nx Integration”Generate Tailwind Config
Section titled “Generate Tailwind Config”npx nx g @nx/react:tailwind-config --project=[app-name]Build with Tailwind
Section titled “Build with Tailwind”Nx automatically processes Tailwind during builds:
# Web appsnpx nx build [web-app] --with-deps
# Mobile apps (Metro bundler handles it)npx nx run [mobile-app]:startBest Practices
Section titled “Best Practices”- Use the shared preset: Always extend
@cloudalt-frontend/config/tailwind-presetfor consistency - Semantic class names: Prefer semantic utilities (
bg-primary-500) over arbitrary values (bg-[#0ea5e9]) - Component composition: Create reusable components rather than repeating class strings
- Dark mode first: Design with dark mode in mind from the start
- Responsive by default: Use responsive prefixes (
sm:,md:,lg:) for adaptive layouts - Avoid !important: Use proper specificity instead of forcing styles
Next Steps
Section titled “Next Steps”- ✅ Phase 1.2 Complete: Tailwind preset with design tokens
- 🔄 Phase 1.3: Storybook integration for visual design system
- 📅 Phase 2: Migrate pinkguest app to Tailwind styling
- 📅 Phase 2: Extract reusable styled components to
@cloudalt-frontend/ui - 📅 Phase 3: Replicate Tailwind setup to all mobile apps
References
Section titled “References”Support
Section titled “Support”For questions or issues with Tailwind integration:
- Check this guide first
- Review Metro bundler output for errors
- Consult NativeWind documentation
- Check
docs/WORK_LOG.mdfor known issues