# Migrating an existing project from SpiroKit v1 to v2

> This document is a work in progress. I'll keep updating this in case I find an edge case I forget to document.

In this article, I'll describe the required steps to migrate an existing SpiroKit v1 project so you can use v2, which comes with an entire rewrite and uses Tamagui's compiler. If you want to learn more about v2, please check out [this article](https://blog.spirokit.com/introducing-spirokit-v2-unleashing-the-power-of-tamagui).

> If you are just starting a new project with SpiroKit, you can already use our two starter templates for v2:
> 
> ```bash
> # Starter with Expo SDK 49, Expo Router v2, TypeScript and SpiroKit v2
> npx create-spirokit-app@latest --template expo-template-typescript-v2
> 
> # Web Starter with NextJS 13, TypeScript and SpiroKit v2
> npx create-spirokit-app@latest --template nextjs-template-typescript-v2
> ```

---

# Package.json

On v1, the package you installed from the private repo was called `@spirokit/core`. On v2, you need to remove that package, and add the following packages:

* For native development with Expo
    
    * @spirokit/ui
        
    * @spirokit/native
        
* For web development with NextJS
    
    * @spirokit/ui
        
    * @spirokit/web
        

Besides, SpiroKit is now using `@tamagui/lucide-icons` instead of `react-native-heroicons` (More info about how to replace the items below)

Here's an example of your package.json after the changes

```diff
{
	"name": "expo-example",
	"version": "1.0.0",
	"main": "index.js",
	"scripts": {
-		"start": "expo start",
+       "start": "TAMAGUI_TARGET=native expo start",
-		"android": "expo start --android",
+       "android": "TAMAGUI_TARGET=native expo start --android",
-		"ios": "expo start --ios",
+       "ios": "TAMAGUI_TARGET=native expo start --ios",
-		"web": "expo start --web",
+       "web": "TAMAGUI_TARGET=web expo start --web",
	},
	"dependencies": {
-		"@spirokit/core": "latest",
+       "@spirokit/ui": "next",
+       "@spirokit/native": "next",
+       "@shopify/flash-list": "^1.4.3",
        "@expo-google-fonts/poppins": "^0.2.2",
-       "@expo/webpack-config": "^0.17.2",
-       "expo": "^47.0.0",
+       "expo": "^49.0.0",
-       "expo-linear-gradient": "~12.0.1",
        "expo-status-bar": "~1.4.2",
        "react": "18.1.0",
        "react-dom": "18.1.0",
        "react-native": "0.70.5",
-       "react-native-heroicons": "2.0.2",
+       "@tamagui/lucide-icons": "1.40.0",
        "react-native-safe-area-context": "4.4.1",
        "react-native-svg": "13.4.0",
        "react-native-web": "~0.18.7"
	},
	"devDependencies": {
		"@babel/core": "^7.19.3",
		"@types/react": "~18.0.24",
		"@types/react-native": "~0.70.6",
		"typescript": "^4.6.3"
	},
	"private": true
}
```

If you can, start from scratch using our new templates mentioned above, and then copy / paste your code.

If you want to keep your current project, check the package.json from our v1 and v2 templates

* v1 expo template: [https://github.com/spirokit/templates/blob/main/expo-template-typescript/package.json](https://github.com/spirokit/templates/blob/main/expo-template-typescript/package.json)
    
* v2 expo template (with expo router): [https://github.com/spirokit/templates/blob/main/expo-template-typescript-v2/package.json](https://github.com/spirokit/templates/blob/main/expo-template-typescript-v2/package.json)
    

---

# Upgrading imports

Search for `from "@spirokit/core"` and replace all the occurrences for `from "@spirokit/ui"`.

> You may get errors on missing components like `DateTimePicker` and `Pressable`. More info about this below.

---

# Tokens

One big change from v1 to v2, is that all the design tokens are now strings, and are pre-pended with a "$" sign. This is how Tamagui works. Let me show you an example:

```typescript
// v1
return (
  <Box padding={4} marginTop={2}>
    <Body fontWeight="bold">Hello world</Body>
  </Box>
)

// v2
return (
  <Box padding="$4" marginTop="$2">
    <Body fontWeight="$bold">Hello world</Body>
  </Box>
)
```

On v1, you usually use numbers to set things like `padding`, `margin`, `borderRadius`, etc. But there were "special values" defined on [this list](https://docs.spirokit.com/?path=/docs/getting-started-design-tokens-size-tokens--page) that were mapped to other values:

* Use 4 to get 16px
    
* Use 6 to get 24px
    

That was convenient but also confusing: If you were using 32, you would get 128px, but if you used 33, you get 33px.

On v2, you can still use numeric values, but all the size tokens now are strings with the "$" prefix.

After migrating a few apps to v2, I came up with a list of things you may need to check and replace. Thankfully, VSCode provides an excellent tool to find and replace these tokens quickly.

## Font tokens

* fontWeight
    
    * Search for `fontWeight=`
        
    * Add the "$" prefix. [Here are the values](https://docs.spirokit.com/?path=/docs/getting-started-design-tokens-typography-tokens--page#font-weight)
        
        * `<Body fontWeight="bold" />` -&gt; `<Body fontWeight="$bold" />`
            
* fontSize
    
    * Search for `fontSize=`
        
    * Add the "$" prefix. [Here are the values](https://docs.spirokit.com/?path=/docs/getting-started-design-tokens-typography-tokens--page#font-size)
        
        * `<Body fontSize="lg" />` -&gt; `<Body fontSize="$lg" />`
            
* lineHeight
    
    * Search for `lineHeight=`
        
    * Add the "$" prefix. [Here are the values](https://docs.spirokit.com/?path=/docs/getting-started-design-tokens-typography-tokens--page#line-height)
        
        * `<Body lineHeight="xl" />` -&gt; `<Body lineHeight="$xl" />`
            
* letterSpacing
    
    * Search for `letterSpacing=`
        
    * Add the "$" prefix. [Here are the values](https://docs.spirokit.com/?path=/docs/getting-started-design-tokens-typography-tokens--page#letter-spacing)
        
        * `<Body letterSpacing="xl" />` -&gt; `<Body letterSpacing="$xl" />`
            

## Color tokens

* backgroundColor, borderColor, color, shadowColor, outlineColor
    
    * Search for `backgroundColor=`, `borderColor=`, `shadowColor`, `outlineColor`
        
    * Add the "$" prefix
        
        * `<Box backgroundColor="primary.500" />` -&gt; `<Box backgroundColor="$primary.500" />`
            

## Size tokens

* margin, marginLeft, marginRight, marginTop, marginBottom
    
    * Search for `margin={`, `marginLeft={`, `marginRight={`, `marginTop={`, `marginBottom={`
        
    * Search for values in the size scale, like 1 to 10, 12,16,20,24, etc. Replace those values with strings with the "$" prefix. [Full list of values](https://docs.spirokit.com/?path=/docs/getting-started-design-tokens-size-tokens--page)
        
        * `<Box margin={4} />` -&gt; `<Box margin="$4" />`
            
        * `<Box marginTop={4} />` -&gt; `<Box marginTop="$4" />`
            
* padding, paddingLeft, paddingRight, paddingTop, paddingBottom
    
    * Search for `padding={`, `paddingLeft={`, `paddingRight={`, `paddingTop={`, `paddingBottom={`
        
    * Search for values in the size scale, like 1 to 10, 12,16,20,24, etc. Replace those values with strings with the "$" prefix. [Full list of values](https://docs.spirokit.com/?path=/docs/getting-started-design-tokens-size-tokens--page)
        
        * `<Box padding={4} />` -&gt; `<Box padding="$4" />`
            
        * `<Box paddingBottom={4} />` -&gt; `<Box paddingBottom="$4" />`
            
* marginX
    
    * Search for `marginX={`
        
    * On v2, it was renamed to use `marginHorizontal` instead
        
    * Search for values in the size scale, like 1 to 10, 12,16,20,24, etc. Replace those values with strings with the "$" prefix. [Full list of values](https://docs.spirokit.com/?path=/docs/getting-started-design-tokens-size-tokens--page)
        
        * `<Box marginX={4} />` -&gt; `<Box marginHorizontal="$4" />`
            
* marginY
    
    * Search for `marginY={`
        
    * On v2, it was renamed to use `marginVertical` instead
        
    * Search for values in the size scale, like 1 to 10, 12,16,20,24, etc. Replace those values with strings with the "$" prefix. [Full list of values](https://docs.spirokit.com/?path=/docs/getting-started-design-tokens-size-tokens--page)
        
        * `<Box marginY={4} />` -&gt; `<Box marginVertical="$4" />`
            
* paddingX
    
    * Search for `paddingX={`
        
    * On v2, it was renamed to use `paddingHorizontal` instead
        
    * Search for values in the size scale, like 1 to 10, 12,16,20,24, etc. Replace those values with strings with the "$" prefix. [Full list of values](https://docs.spirokit.com/?path=/docs/getting-started-design-tokens-size-tokens--page)
        
        * `<Box paddingX={4} />` -&gt; `<Box paddingHorizontal="$4" />`
            
* paddingY
    
    * Search for `paddingY={`
        
    * On v2, it was renamed to use `paddingVertical` instead
        
    * Search for values in the size scale, like 1 to 10, 12,16,20,24, etc. Replace those values with strings with the "$" prefix. [Full list of values](https://docs.spirokit.com/?path=/docs/getting-started-design-tokens-size-tokens--page)
        
        * `<Box paddingY={4} />` -&gt; `<Box paddingVertical="$4" />`
            
* space
    
    * Search for `space={`
        
    * Search for values in the size scale, like 1 to 10, 12,16,20,24, etc. Replace those values with strings with the "$" prefix. [Full list of values](https://docs.spirokit.com/?path=/docs/getting-started-design-tokens-size-tokens--page)
        
        * `<Box space={4} />` -&gt; `<Box space="$4" />`
            
* width, minWidth, maxWidth
    
    * Search for `width={`, `minWidth={`, `maxWidth={`
        
    * Search for values in the size scale, like 1 to 10, 12,16,20,24, etc. Replace those values with strings with the "$" prefix. [Full list of values](https://docs.spirokit.com/?path=/docs/getting-started-design-tokens-size-tokens--page)
        
        * `<Box width={4} />` -&gt; `<Box width="$4" />`
            
        * `<Box width={"full"} />` -&gt; `<Box width="$full" />`
            
* height, minHeight, maxHeight
    
    * Search for `height={`, `minHeight={`, `maxHeight={`
        
    * Search for values in the size scale, like 1 to 10, 12,16,20,24, etc. Replace those values with strings with the "$" prefix. [Full list of values](https://docs.spirokit.com/?path=/docs/getting-started-design-tokens-size-tokens--page)
        
        * `<Box height={4} />` -&gt; `<Box height="$4" />`
            
        * `<Box height={"full"} />` -&gt; `<Box height="$full" />`
            

---

## Border-radius tokens

On v1, border-radius allowed numeric values and the following tokens:

```typescript
{
	"none": 0,
	"xs": 2,
	"sm": 4,
	"md": 6,
	"lg": 8,
	"xl": 12,
	"2xl": 16,
	"3xl": 24,
	"full": 9999
}
```

On v2, you can still use numeric values, and the following tokens (as string, with the "$" prefix:

```typescript
{
  0: 0,
  1: 3,
  2: 5,
  3: 7,
  4: 9,
  true: 9,
  5: 10,
  6: 16,
  7: 19,
  8: 22,
  9: 26,
  10: 34,
  11: 42,
  12: 50,
}
```

You can use the new tokens like this

* `<Box borderRadius="2xl"/>` -&gt; `<Box borderRadius="$6"`
    
* `<Box borderRadius="full"/>` -&gt; `<Box borderRadius="$12"`
    

Or you can replace the old tokens with the numeric values

* `<Box borderRadius="2xl"/>` -&gt; `<Box borderRadius={16}`
    

---

# Pseudo props

SpiroKit v1 was built on top of NativeBase. That's why you could use pseudo props like:

* `_hover`
    
* `_pressed`
    
* `_focus`
    
* Platform-specific
    
    * `_web`
        
    * `_iOS`
        
    * `_android`
        

On SpiroKit v2, we are inheriting pseudo props from Tamagui. Platform-specific props are not available yet, so you'll need to check for the platform and conditionally add styles for now.

But you can still use the hover, pressed, and focus props with a new name.

* `_hover` -&gt; `_hoverStyle`
    
* `_pressed` -&gt; `_pressStyle`
    
* `_focus` -&gt; `_focusStyle`
    

Learn more about these props [here](https://tamagui.dev/docs/intro/props#pseudo-style-props)

---

# Media props

On v1, you were able to set responsive values like this:

```typescript
<Box width={{ base: "full", lg: "1/2" }}/>
```

On v2, we have separated props for each breakpoint:

```typescript
<Box width="$full" $gtLg="$1/2" />
```

---

# Breaking changes in components

* The `Pressable` component was removed. Now all the common layout components like `Box`, `VStack`, `HStack`, etc already include a `onPress` prop.
    
* **Button** component
    
    * The `size` prop no longer include the value "xs". use "sm" instead.
        
        > You may notice that the buttons are a little bit smaller than in v1. This was based on feedback from users.
        
* **Badge** and **FlatList** components
    
    * On v1, you could add style props like this:
        
        ```typescript
        <Badge paddingX={4} paddingY={2}>Hello</Badge>
        ```
        
    * On v2, style props were moved into the `_container` prop
        
        ```typescript
        <Badge _container={{ 
          paddingHorizontal: "$4", 
          paddingVertical: "$2"
        }}>Hello</Badge>
        ```
        
* **Switch** component
    
    * `value` prop was replaced with the `checked` prop.
        
* Use **DateTimeInput** instead of **DateTimePicker**
    
    * The DatePicker component was temporarily removed. v1 was built on top of react-native-modern-datepicker and it had performance issues.
        
    * I'll rebuild this component soon. In the meantime, you can use the new **DateTimeInput** component. Documentation with examples will be available soon.
        
* **Select** component
    
    * `ItemComponent` prop was renamed. Use `renderItem` instead.
        
        > This component is now using [FlashList by Shopify](https://github.com/Shopify/flash-list), so enjoy the new performance boost 😉
        
* Box, HStack, VStack, etc
    
    * LinearGradient is not available yet. Will be added later.
        
    * SafeArea props are no longer available. I'll probably add them again later. In the meantime, you can get the same functionality doing the following refactor:
        
        ```typescript
        // v1
        <Box safeAreaTop />
        
        // v2
        import { useSafeAreaInsets } from "react-native-safe-area-context";
        const { top } = useSafeAreaInsets();
        
        <Box top={top}>
        ```
        

---

# Upgrading icons

* SpiroKit v1 was using `react-native-heroicons` (292 icons)
    
* SpiroKit v2 is now using `@tamagui/lucide-icons` (1237 icons)
    
* Components like `Button`, `Alert`, `Badge`, `HorizontalCard`, `VerticalCard`, `PortraitCard`, `Input`, `Tab`, `TextArea` should still work with the old icons, but I highly recommend you to make the switch. You can search for all the available components [here](https://lucide.dev/)
    

Migration is straightforward:

```typescript
// v1
import { MapIcon } from "react-native-heroicons/outline"
<Button IconLeftComponent={MapIcon}>

// v2
import { Map } from "@tamagui/lucide-icons"
<Button IconLeftComponent={Map}>
```

---

# Hooks

## useColorMode

* In v1, there was a "useColorMode" hook inherited from NativeBase. In v2, I decided to remove this hook, and unify all the features related to color mode and accent color in the "useTheme" hook. More information about this in an upcoming post introducing new features related to theming capabilities.
    
* If you were using this hook to check for the active color mode, or to toggle between dark and light mode, you can now use the "useTheme" hook to achieve the same
    

```typescript
// v1
const { colorMode, toggleColorMode } = useColorMode()

// v2
const { colorMode, setColorMode, accentColor, setAccentColor } = useTheme()
```

---

# Feedback is appreciated 🙏

If you are trying to migrate and you find another issue that is not included on this post, please feel free to reach out to me at [mauro@spirokit.com](http://mailto:mauro@spirokit.com) or [send me a DM on Twitter](https://twitter.com/mauro_codes)
