Skip to main content

Migration Plan: Big Bang Approach

Strategy Overview​

The Big Bang approach rewrites the @digiwedge/react-native-paper wrapper library to use Gluestack UI v3 internals while maintaining backward-compatible exports where feasible. All mobile apps are migrated simultaneously, eliminating the need for dual-library support.

Note: @digiwedge/react-native-paper has been removed from the workspace; legacy screens/hooks now live in @digiwedge/mobile-auth. References below capture the migration record.

┌──────────────────────────────────────────────────────────────────┐
│ BIG BANG MIGRATION │
│ │
│ Week 1-2 Week 3-4 Week 5-6 Week 7-8 Week 9-10 │
│ ──────── ──────── ──────── ──────── ────────── │
│ Foundation Forms Overlays Business Integration │
│ & Setup & Input & Modals Logic & QA │
│ │
│ ▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ │
└──────────────────────────────────────────────────────────────────┘

Pre-Migration Checklist​

Environment Setup​

  • Expo SDK 54 aligned across all apps
  • React Native 0.81.5 baseline
  • Node 22 LTS
  • pnpm workspace configured

Audit Tasks​

  • Complete grep audit for all react-native-paper imports
  • Document all custom theme tokens in use
  • List all third-party packages depending on Paper
  • Screenshot all major screens for visual comparison

Team Preparation​

  • NativeWind/Tailwind training session
  • Gluestack v3 component API walkthrough
  • Compound component pattern explanation
  • Code review guidelines for migration PRs

Phase 1: Foundation & Setup (Week 1-2)​

Goals​

  • Initialize Gluestack UI v3 in monorepo
  • Configure NativeWind across all mobile apps
  • Create new wrapper library scaffold
  • Port core primitives

Tasks​

1.1 Initialize Gluestack UI​

# Use the existing libs/ui/gluestack-ui scaffold.
# Only run the CLI in libs/ui/gluestack-ui when adding new components.
cd libs/ui/gluestack-ui
pnpm dlx gluestack-ui add box text icon divider spinner

1.2 Create @digiwedge/gluestack-ui Library​

libs/ui/gluestack-ui/
├── src/
│ ├── index.ts # Main exports
│ ├── components/
│ │ ├── primitives/ # Box, Text, Icon, Divider, Spinner
│ │ ├── forms/ # Button, Input, Switch, etc.
│ │ ├── overlays/ # Modal, Menu, Toast, etc.
│ │ └── business/ # Auth, Profile, Booking modals
│ ├── hooks/ # Re-export existing hooks unchanged
│ ├── stores/ # Re-export existing stores unchanged
│ ├── types/ # Re-export existing types unchanged
│ └── theme/
│ ├── tokens.ts # Design tokens
│ ├── tailwind.config.js # Tailwind configuration
│ └── Provider.tsx # GluestackUIProvider wrapper
├── package.json
└── tsconfig.json

1.3 Configure NativeWind in Apps​

Each app needs:

// metro.config.js
const { withNxMetro } = require('@nx/expo');
const { getDefaultConfig } = require('@expo/metro-config');
const { mergeConfig } = require('metro-config');
const { withNativeWind } = require('nativewind/metro');

const defaultConfig = getDefaultConfig(__dirname);
const baseConfig = withNxMetro(mergeConfig(defaultConfig, {}), {
watchFolders: [],
extensions: [],
});

module.exports = withNativeWind(baseConfig, { input: './global.css' });

// .babelrc.*
module.exports = function (api) {
api.cache(true);
const isTest =
process.env.BABEL_ENV === 'test' || process.env.NODE_ENV === 'test';

return {
presets: [['babel-preset-expo', { jsxImportSource: 'nativewind' }]],
plugins: isTest ? [] : ['nativewind/babel'],
};
};

// tailwind.config.js
module.exports = {
content: [
'./src/**/*.{js,jsx,ts,tsx}',
'../../libs/ui/gluestack-ui/src/**/*.{js,jsx,ts,tsx}',
],
presets: [require('nativewind/preset')],
theme: {
extend: {
colors: {
primary: { /* token values */ },
secondary: { /* token values */ },
},
},
},
};

1.4 Port Primitives​

Paper ComponentGluestack ComponentMigration Notes
TextTextDirect mapping, add className support
SurfaceBoxReplace with Box, use bg-* classes
DividerDividerDirect mapping
ActivityIndicatorSpinnerRename import
IconIconConfigure with lucide-react-native

Deliverables​

  • @digiwedge/gluestack-ui library created
  • NativeWind configured in all 4 apps
  • Primitives (Box, Text, Icon, Divider, Spinner) working
  • Apps build successfully with new provider (QA pending)

Phase 2: Form Components (Week 3-4)​

Goals​

  • Migrate all form-related components
  • Implement compound component wrappers
  • Update form validation patterns

Tasks​

2.1 Button Migration​

Before (Paper):

<Button mode="contained" icon="plus" onPress={handlePress}>
Add Item
</Button>

After (Gluestack wrapper):

// @digiwedge/gluestack-ui/components/forms/Button.tsx
export const Button = ({
mode = 'contained',
icon,
children,
...props
}) => {
const variant = mode === 'contained' ? 'solid'
: mode === 'outlined' ? 'outline'
: 'link';

return (
<GlueButton variant={variant} {...props}>
{icon && <ButtonIcon as={getIcon(icon)} />}
<ButtonText>{children}</ButtonText>
</GlueButton>
);
};

2.2 TextInput → Input Migration​

Before (Paper):

<TextInput
label="Email"
value={email}
onChangeText={setEmail}
error={!!errors.email}
mode="outlined"
/>
<HelperText type="error" visible={!!errors.email}>
{errors.email}
</HelperText>

After (Gluestack wrapper):

// @digiwedge/gluestack-ui/components/forms/TextInput.tsx
export const TextInput = ({
label,
error,
helperText,
mode = 'outlined',
...props
}) => {
const variant = mode === 'outlined' ? 'outline' : 'underlined';

return (
<FormControl isInvalid={!!error}>
{label && <FormControlLabel><FormControlLabelText>{label}</FormControlLabelText></FormControlLabel>}
<Input variant={variant}>
<InputField {...props} />
</Input>
{(error || helperText) && (
<FormControlHelper>
<FormControlHelperText className={error ? 'text-error-500' : ''}>
{error || helperText}
</FormControlHelperText>
</FormControlHelper>
)}
</FormControl>
);
};

2.3 IconButton Migration​

Before (Paper):

<IconButton icon="menu" size={24} onPress={openMenu} />

After (Gluestack wrapper):

// @digiwedge/gluestack-ui/components/forms/IconButton.tsx
export const IconButton = ({ icon, size = 24, ...props }) => {
return (
<GlueButton variant="link" className="p-2" {...props}>
<ButtonIcon as={getIcon(icon)} size={size} />
</GlueButton>
);
};

2.4 Other Form Components​

ComponentApproach
SwitchDirect mapping with className styling
CheckboxDirect mapping
RadioButtonUse Gluestack Radio group
SearchbarCompose from Input + InputSlot + Icon

Deliverables​

  • Button, IconButton components with Paper-like API
  • TextInput with label, error, helperText support
  • Switch, Checkbox, Radio components
  • Searchbar composite component
  • All form screens updated and working

Phase 3: Overlay Components (Week 5-6)​

Goals​

  • Migrate modal and overlay components
  • Implement Portal-based overlays
  • Update toast notification system

Tasks​

3.1 Modal/Dialog Migration​

Before (Paper):

<Portal>
<Dialog visible={visible} onDismiss={hide}>
<Dialog.Title>Confirm</Dialog.Title>
<Dialog.Content>
<Text>Are you sure?</Text>
</Dialog.Content>
<Dialog.Actions>
<Button onPress={hide}>Cancel</Button>
<Button onPress={confirm}>OK</Button>
</Dialog.Actions>
</Dialog>
</Portal>

After (Gluestack wrapper):

// @digiwedge/gluestack-ui/components/overlays/Dialog.tsx
export const Dialog = ({ visible, onDismiss, children }) => {
return (
<AlertDialog isOpen={visible} onClose={onDismiss}>
<AlertDialogBackdrop />
<AlertDialogContent>
{children}
</AlertDialogContent>
</AlertDialog>
);
};

Dialog.Title = ({ children }) => (
<AlertDialogHeader>
<Heading>{children}</Heading>
</AlertDialogHeader>
);

Dialog.Content = ({ children }) => (
<AlertDialogBody>{children}</AlertDialogBody>
);

Dialog.Actions = ({ children }) => (
<AlertDialogFooter>{children}</AlertDialogFooter>
);

3.2 Menu Migration​

Before (Paper):

<Menu
visible={visible}
onDismiss={closeMenu}
anchor={<IconButton icon="dots-vertical" onPress={openMenu} />}
>
<Menu.Item onPress={edit} title="Edit" />
<Menu.Item onPress={delete} title="Delete" />
</Menu>

After (Gluestack wrapper):

// @digiwedge/gluestack-ui/components/overlays/Menu.tsx
export const Menu = ({ visible, onDismiss, anchor, children }) => {
return (
<GlueMenu
isOpen={visible}
onClose={onDismiss}
trigger={(props) => cloneElement(anchor, props)}
>
{children}
</GlueMenu>
);
};

Menu.Item = ({ title, onPress, ...props }) => (
<MenuItem onPress={onPress} {...props}>
<MenuItemLabel>{title}</MenuItemLabel>
</MenuItem>
);

3.3 Toast Migration​

import { useToast } from '@digiwedge/gluestack-ui';

const { showToast } = useToast();

showToast({
type: 'success',
text1: 'Saved',
text2: 'Your changes are live.',
});

Deliverables​

  • Dialog/AlertDialog with compound API
  • Menu with Menu.Item pattern
  • Portal component
  • Popover, Tooltip components
  • Toast notification system
  • All modal screens migrated

Phase 4: Business Components (Week 7-8)​

Goals​

  • Migrate all domain-specific components
  • Update auth flows
  • Migrate booking and profile screens

Tasks​

4.1 Auth Components​

ComponentFilesNotes
LoginModal1Form inputs, social buttons
SignUpView1Multi-step form
ResetPasswordModal1Email input, confirmation
ConfirmOTPModal1OTP input, timer
MFAMessagingModal1Method selection
FullScreenAuthModal1Container wrapper

4.2 Profile Components​

ComponentFilesNotes
ProfileSettings1Settings list, switches
EditProfileView1Form with avatar
ProfileAvatar1Avatar with camera
MyBuddies1List with actions

4.3 Booking Components​

ComponentFilesNotes
BookingInformationModal1Read-only display
DeletePaymentCardModal1Confirmation dialog
MakeCardDefault1Selection modal
ClubContactForm1Contact form

4.4 Buddy Management​

ComponentFilesNotes
BuddyList1Scrollable list
BuddyInputModal1Add buddy form
PlayerSearchModal1Search + select
DeleteBuddyModal1Confirmation
AddPlayersFromBuddies1Multi-select

Deliverables​

  • All auth screens functional
  • Profile management working
  • Booking modals migrated
  • Buddy management complete
  • All business logic preserved

Phase 5: App Integration & QA (Week 9-10)​

Goals​

  • Remove react-native-paper dependency
  • Update all app entry points
  • Comprehensive visual QA
  • Performance validation

Tasks​

5.1 Remove Paper Dependencies​

# Remove from each app
pnpm remove react-native-paper --filter teetime-mobile
pnpm remove react-native-paper --filter teetime-country-club
pnpm remove react-native-paper --filter scl-mobile
pnpm remove react-native-paper --filter messaging_mobile

# Remove from root
pnpm remove react-native-paper -w

# Update workspace
pnpm install

5.2 Update App Providers​

Before:

import { PaperProvider, MD3LightTheme } from 'react-native-paper';

export default function App() {
return (
<PaperProvider theme={MD3LightTheme}>
<NavigationContainer>
{/* ... */}
</NavigationContainer>
</PaperProvider>
);
}

After:

import { GluestackUIProvider } from '@digiwedge/gluestack-ui';
import '../global.css';

export default function App() {
return (
<GluestackUIProvider>
<NavigationContainer>
{/* ... */}
</NavigationContainer>
</GluestackUIProvider>
);
}

5.3 Visual QA Checklist​

Screenteetime-mobileteetime-country-clubscl-mobilemessaging
Login[ ][ ][ ][ ]
Signup[ ][ ][ ][ ]
Home[ ][ ][ ][ ]
Profile[ ][ ][ ][ ]
Settings[ ][ ][ ][ ]
Booking[ ][ ]N/AN/A
Buddies[ ][ ]N/AN/A

5.4 Performance Validation​

  • Measure initial bundle size (before/after)
  • Measure TTI (Time to Interactive)
  • Profile render performance
  • Test on low-end devices

Deliverables​

  • Zero react-native-paper imports
  • All apps building successfully
  • Visual parity with before-state
  • Performance metrics documented
  • Dev clients rebuilt for all apps

Rollback Plan​

If critical issues are discovered post-migration:

  1. Git Revert: All changes are in a single branch, easy to revert
  2. Package Restore: Re-add react-native-paper dependencies
  3. Provider Swap: Switch back to PaperProvider
# Emergency rollback
git revert --no-commit HEAD~N..HEAD
pnpm add react-native-paper@5.14.5 -w
pnpm install

Success Metrics​

MetricTargetMeasurement
Build Success100%All 4 apps build
Test Pass Rate100%Existing tests pass
Bundle SizeNo more than currentBundle analyzer
Visual Parity95%+Screenshot diff
TTINo more than currentPerformance profiling
Paper Imports0grep audit

Post-Migration Tasks​

  • Delete libs/ui/react-native-paper/ directory
  • Update CI/CD pipelines
  • Update developer documentation
  • Archive this migration epic
  • Communicate to team