{"id":22765221,"url":"https://github.com/vidundergunder/expo-prototype-tutorial","last_synced_at":"2026-04-12T00:34:48.294Z","repository":{"id":135435356,"uuid":"312257410","full_name":"VidunderGunder/expo-prototype-tutorial","owner":"VidunderGunder","description":"Beginner's guide to development for iOS, Android and Web with Expo (React Native).  Made in collaboration with Eik Lab and NMBU.","archived":false,"fork":false,"pushed_at":"2020-11-21T23:01:29.000Z","size":24797,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-30T10:16:33.064Z","etag":null,"topics":["android","calculator","cat","cats","course","eik","eik-lab","expo","guide","ios","kitten","kitten-ui","lab","nmbu","react","react-native","tutorial","vercel","web","website"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/VidunderGunder.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-11-12T11:33:11.000Z","updated_at":"2023-10-12T09:45:25.000Z","dependencies_parsed_at":null,"dependency_job_id":"30f72e6c-b567-4ce6-9529-6648574d50b7","html_url":"https://github.com/VidunderGunder/expo-prototype-tutorial","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/VidunderGunder/expo-prototype-tutorial","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VidunderGunder%2Fexpo-prototype-tutorial","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VidunderGunder%2Fexpo-prototype-tutorial/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VidunderGunder%2Fexpo-prototype-tutorial/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VidunderGunder%2Fexpo-prototype-tutorial/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/VidunderGunder","download_url":"https://codeload.github.com/VidunderGunder/expo-prototype-tutorial/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VidunderGunder%2Fexpo-prototype-tutorial/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265631340,"owners_count":23801797,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","calculator","cat","cats","course","eik","eik-lab","expo","guide","ios","kitten","kitten-ui","lab","nmbu","react","react-native","tutorial","vercel","web","website"],"created_at":"2024-12-11T12:12:14.796Z","updated_at":"2026-04-12T00:34:43.242Z","avatar_url":"https://github.com/VidunderGunder.png","language":"JavaScript","readme":"# App and Web with [Expo](https://expo.io/) \u003c!-- omit in toc --\u003e\n\n\u003cimg src=\"images/7a80253aa6176407709dacea6e8f38760c031c9b31e782ebe7a44b332b354665.png\" /\u003e  \n\nLet's create an application prototype from start to finish!\n\nWhat we'll make:\n\n- A calculator that calculates how much you love cats 🐱  \n    In other words...  \n    a **Catculator™**\n\n\nWhat we'll support:\n\n-  Web (all platforms)\n-  App (iOS and Android)\n\nThis is all made possible by [React Native](https://reactnative.dev/) and [Expo](https://expo.io/).\n\n[React Native](https://reactnative.dev/) is a framework for writing applications for iOS and Android. It is native, meaning your app is developed specifically for one platform and can take full advantage of all the devices features.\n\n[Expo](https://expo.io/) is a tool to make [React Native](https://reactnative.dev/) easier - it makes it possible to write code that can be used both on iOS, Android and even on the web (thanks to [React Native for Web](https://github.com/necolas/react-native-web)). You will lose some advanced functionalities with [Expo](https://expo.io/), but for the average developer the trade-offs are absolutely worth it - and you can always eject your project, if you ever need to!\n\nReact Native is working on native support for Windows and Mac, and Expo already supports [wrapping your application](https://docs.expo.io/guides/using-electron/) with [Electron](https://www.electronjs.org/) (although experimentally), if you want native desktop support down the line.\n\nFor simplicity's sake, we will only support Web, iOS and Android here, as that is sufficient in most cases.\n\nHuge thanks to Astrid Lye Moum for valuable feedback!\n\n## Table of contents \u003c!-- omit in toc --\u003e\n- [🚀 Quick Start](#-quick-start)\n- [🎓 Prerequisites](#-prerequisites)\n- [🔧 Setup](#-setup)\n- [🕸️ Create a Web App](#️-create-a-web-app)\n- [📱 iOS and Android](#-ios-and-android)\n- [✨ Icons and Info](#-icons-and-info)\n- [🌐 Publish to web *- free!*](#-publish-to-web---free)\n- [📲 Publish app for testing *- free!*](#-publish-app-for-testing---free)\n- [💲 Publish to app stores *- not free...*](#-publish-to-app-stores---not-free)\n- [💾 Save and push changes to GitHub](#-save-and-push-changes-to-github)\n- [🤔 What's next?](#-whats-next)\n- [💡 Tips and Tricks](#-tips-and-tricks)\n\n## 🚀 Quick Start\n\nIf you are a proficient developer already, clone this repo and start developing, or take a look at [Expo's documentation](https://docs.expo.io/).\n\nOtherwise, follow the guide below.\n\n## 🎓 Prerequisites\n\nThis guide assumes no prior knowledge, but if this is going a bit fast, feel free to check out the links below. You won't actually code as much as copy-paste from the guide. The goal here is to show you how to get a functional prototype out there - you can fill in the gaps later.\n\n---\n\n_Warning: If you are new to all of this, don't spend too much time on the tutorials below; just skip through to get a feeling for what they do - you can look them up later when you need to._ 🔍\n\n_I see too many new developers get stuck in tutorial land, and I would recommend you to learn as you work towards a goal, as it's often the most effective way of learning for most people. You may be different, so do what you feel is right, but that's my two cents._ 👛\n\n---\n\n- Terminal ([Windows](https://www.youtube.com/watch?v=jbvqCqb-HJk), [Linux](https://www.suse.com/c/working-command-line-basic-linux-commands/), [Mac](https://www.youtube.com/watch?v=5XgBd6rjuDQ))\n- [HTML](https://www.youtube.com/watch?v=UB1O30fR-EE\u0026list=PLzWjrc7MKKxyffsM7YTBnogYpBh_QUIO0)\n- [CSS](https://www.youtube.com/watch?v=yfoY53QXEnI\u0026list=PLzWjrc7MKKxyffsM7YTBnogYpBh_QUIO0)\n- [Javascript](https://www.youtube.com/watch?v=2nZiB1JItbY\u0026list=PLzWjrc7MKKxyffsM7YTBnogYpBh_QUIO0)\n- [Node](https://www.youtube.com/watch?v=uVwtVBpw7RQ\u0026list=PLzWjrc7MKKxyffsM7YTBnogYpBh_QUIO0)\n- [NPM](https://www.youtube.com/watch?v=s70-Vsud9Vk) and [Yarn](https://www.youtube.com/watch?v=g9_6KmiBISk\u0026list=PLzWjrc7MKKxyffsM7YTBnogYpBh_QUIO0)\n- [React](https://www.youtube.com/watch?v=Tn6-PIqc4UM\u0026list=PLzWjrc7MKKxyffsM7YTBnogYpBh_QUIO0)\n- [React Native](https://www.youtube.com/watch?v=6oFuwhIibo4\u0026list=PLzWjrc7MKKxyffsM7YTBnogYpBh_QUIO0)\n\n## 🔧 Setup\n\nWe will need an integrated development environment (IDE), and I will use VSCode. I recommend you do the same, as it will be easier to follow along, but if you are familiar with another IDE I won't stop you.\n\n_Note: If you know your way around an IDE, Git, GitHub and developer tools, you only need to follow the **mandatory steps in bold text**._\n\n1. Make sure you have a popular and modern browser set as default\n\n    - [Chrome](https://www.google.com/chrome/) (What I'll use)\n    - [Edge](https://www.microsoft.com/edge) (the new one with the twirly logo)\n    - [Firefox](https://www.mozilla.org/firefox/new)\n    - Safari\n   \n2. Install [VSCode](https://code.visualstudio.com/)\n3. Install [Node](https://nodejs.org/en/download/)\n4. Install [Yarn](https://yarnpkg.com/lang/en/docs/install/)\n5. Install [Git](https://git-scm.com/)  \n\n    Set the Git's default editor to Visual Studio Code  \n        \u003cimg src=\"images/5656a524e4f9bc0f958b07a92d420a538417a784d80a24be1bf2e281c2307b4d.png\" /\u003e  \n    I usually leave all other options to default\n\n_Now might be a good time to restart your computer. You may not need to, but it is always a good idea after installing so many tools._\n\n6. [Create a GitHub user](https://github.com/join)\n7. Open VSCode\n8. Install VSCode extensions (optional, but recommended)\n    1. Open extensions  \n        \u003cimg src=\"images/b27c35716c2c2d47bb7a315129cb4b2d11137caed957a6504af43f53f94735e2.png\" width=400 /\u003e\n    2. Install these extensions\n        - Prettier - Code formatter\n        - React Native Tools\n        - ES7 React/Redux/GraphQL/React-Native snippets\n        - Bracket Pair Colorizer 2\n        - Community Material Theme (very optional)\n        - Material Icon Theme (very optional)\n    3. Setup theme and icons (very optional)  \n        _The following only applies if you weren't prompted automatically_\n        - Open the command palette (\u003ckbd\u003eCtrl\u003c/kbd\u003e + \u003ckbd\u003eShift\u003c/kbd\u003e + \u003ckbd\u003eP\u003c/kbd\u003e or \u003ckbd\u003eF1\u003c/kbd\u003e)\n        - Run the command `Preferences: Color Theme`  \n            \u003cimg src=\"images/b7b486319d909dbe3d8fd60d7ba2e9171f3e71df22dbe3b39574025d7600e975.png\" width=600 /\u003e  \n        - Choose a Community Material Theme of your liking  \n            \u003cimg src=\"images/049d49f0b1c004fc27a4aaf20020a3b4678e09a8bb8e45935b9739927cb99d3a.png\" /\u003e  \n        - Open the command palette (\u003ckbd\u003eCtrl\u003c/kbd\u003e + \u003ckbd\u003eShift\u003c/kbd\u003e + \u003ckbd\u003eP\u003c/kbd\u003e or \u003ckbd\u003eF1\u003c/kbd\u003e)\n        - Run the command `Preferences: File Icon Theme`  \n            \u003cimg src=\"images/18a94da6249f537a78ba2210036e7d142cdb3588859c9f35acffae2f4e425c87.png\" width=600 /\u003e  \n        - Choose `Material Icons: Activate Icon Theme`  \n            \u003cimg src=\"images/5477297bee57ea4eab9516d7280489a34586b87f4fc5348f6a0dd1bb3515099e.png\" /\u003e  \n    4. Reload VSCode  \n\n        Run `Developer: Reload Window` with the command palette (\u003ckbd\u003eCtrl\u003c/kbd\u003e + \u003ckbd\u003eShift\u003c/kbd\u003e + \u003ckbd\u003eP\u003c/kbd\u003e or \u003ckbd\u003eF1\u003c/kbd\u003e)\n            \u003cimg src=\"images/295089e991f67335f54fe79f8ea84d0c463b525a72765c0ea5be69e92e832563.png\" /\u003e  \n        (You can also close and reopen VSCode, if you prefer)\n\n9.  Open your terminal with one of the following methods\n    - NO: \u003ckbd\u003eCtrl\u003c/kbd\u003e + \u003ckbd\u003eØ\u003c/kbd\u003e\n    - US/UK: \u003ckbd\u003eCtrl\u003c/kbd\u003e + \u003ckbd\u003e`\u003c/kbd\u003e\n    - Click `View`, `Terminal` in the toolbar  \n        \u003cimg src=\"images/16747341513ca5f8b46e48606d4146f4bae05c3b4dca580817fc56b028bc2d4b.png\" width=480 /\u003e  \n\n10. **Install Expo, by pasting the following to the terminal. Press \u003ckbd\u003eEnter\u003c/kbd\u003e to run the command**\n\n    ```shell\n    yarn global add expo-cli\n    ```\n\n11. **Initialize a expo project**\n\n    _Note: The project will be saved where your terminal is located, so change this if you have a preferred place to store coding projects._\n\n    The last argument, `catculator` , is the project name - feel free to change it.\n\n    ```shell\n    expo init catculator\n    ```\n\n    Choose `blank` as your template when prompted (it should be the default option), by pressing \u003ckbd\u003eEnter\u003c/kbd\u003e\n\n12. **Open your newly created project**\n\n    Click on `File`, `Open Folder...` or use your OS' shortcut  \n    (\u003ckbd\u003eCtrl\u003c/kbd\u003e + \u003ckbd\u003eK\u003c/kbd\u003e followed by \u003ckbd\u003eCtrl\u003c/kbd\u003e + \u003ckbd\u003eO\u003c/kbd\u003e on Windows)\n\n    \u003cimg src=\"images/4d4debf5d52d1f336d3e99ee58f962ae66de80e6f7657f8a050ba6e1c771eec3.png\" /\u003e  \n\n    Select the folder with your project and press \u003cbutton\u003eSelect Folder\u003c/button\u003e\n\n     \u003cimg src=\"images/efcfa5aa34755cea48a03c8eedc7906475e07e4044fdb88c3925ef4327465cbd.png\" /\u003e  \n\n    You should see the project files in the explorer tab if done correctly\n\n    \u003cimg src=\"images/5cf6ea38b191df48880fc7cdcebba6e03933a6ecb556291876e2637217d80e2b.png\" /\u003e  \n\n\n13. **Start your app in your browser**\n\n    Open up a terminal (if the old one closed on you) and start Expo with a web client\n\n    ```shell\n    yarn web\n    ```\n   \n    If everything worked correctly you should be met with `Open up App.js to start working on your app!` in a web browser after Expo has started up.\n\n    \u003cimg src=\"images/31fa0ce5cfe21e26b4494b04f2f4ffe4944a1391596f8d3fa15d11b2255eeccc.png\" /\u003e  \n\n    So let's do just that, but first - we want to store our code in the cloud and open up some developer tools.\n\n14. Configure username and email in Git\n\n    ```shell\n    git config --global user.email \"you@example.com\"\n    git config --global user.name \"Your Name\"\n    ```\n\n    For me, that will be\n\n    ```shell\n    git config --global user.email \"kristiankramas@outlook.com\"\n    git config --global user.name \"VidunderGunder\"\n    ```\n\n15. Commit your initial files\n\n    Go to the Source Control tab\n\n    \u003cimg src=\"images/ba95cff7e8851ff59e68658a683f10953979537535fa8389b874f732d863fb96.png\" /\u003e  \n\n    Write `init` as the commit message and press commit (the ✔-mark or \u003ckbd\u003eCtrl\u003c/kbd\u003e + \u003ckbd\u003eEnter\u003c/kbd\u003e)\n\n    \u003cimg src=\"images/cd2a1cfee2473157444d4d968ecc290a4e54d9c34e1255e043e5031882d4a0e2.png\" /\u003e  \n\n16. Publish your repository\n\n    Open the command palette (\u003ckbd\u003eCtrl\u003c/kbd\u003e + \u003ckbd\u003eShift\u003c/kbd\u003e + \u003ckbd\u003eP\u003c/kbd\u003e or \u003ckbd\u003eF1\u003c/kbd\u003e)\n\n    Use the command `Publish to GitHub`\n\n    \u003cimg src=\"images/3127c33be77dc36f7f1710f8f0d78c3c4316e2ef430e32655940da9d9f8e70f4.png\" /\u003e  \n\n    Accept all prompts\n\n    \u003cp align=\"center\"\u003e\u003cimg src=\"images/9981f3a05207068b3c5aa0bda18c533f79c81824a4ea69ea61cf2396238729c4.png\" /\u003e\u003c/p\u003e\n \n    \u003cp align=\"center\"\u003e\u003cimg src=\"images/b1ad0e640e0e7c6fe7af2a06a51ec1d7f139bc22304c8058386579d7ab4227b2.png\" width=500 /\u003e\u003c/p\u003e\n\n    \u003cp align=\"center\"\u003e\u003cimg src=\"images/cc47c0dbd5a7e20b5ae1afda132baee4ccdb2364b9f83eb6e4841989b7f380c1.png\" width=500 /\u003e\u003c/p\u003e\n\n    Confirm the repo name and choose if you want to have it public or private\n\n    \u003cimg src=\"images/2987f71ba191c8a4691dc16c92cce630735c259f9afe9faf1b66f48791239f35.png\" width=500 /\u003e\n\n    It is now hosted on your GitHub!\n\n17. Go to your browser and open developer tools\n\n    _Note: I am using Chrome, so this may differ if you are using something else._\n\n    - Windows:\n        - Press \u003ckbd\u003eCtrl\u003c/kbd\u003e + \u003ckbd\u003eShift\u003c/kbd\u003e + \u003ckbd\u003eC\u003c/kbd\u003e\n        - ... or press \u003ckbd\u003eF12\u003c/kbd\u003e\n        - ... or right click the web page and choose inspect  \n            \u003cimg src=\"images/90cb4533fd532fc42d28e1321f70fe9455b8eee7021d787cb00858a3fe24db8d.png\" /\u003e\n    - Mac:\n        - Press \u003ckbd\u003eCommand\u003c/kbd\u003e + \u003ckbd\u003eOption\u003c/kbd\u003e + J\u003c/kbd\u003e\n        - ... or right click the web page and choose inspect  \n            \u003cimg src=\"images/94a50925f5922d92cf7dda769c18f3271422b8b66f4da34fd10a80116f26f1be.png\" /\u003e\n    - Linux:\n        - Press \u003ckbd\u003eCtrl\u003c/kbd\u003e + \u003ckbd\u003eShift\u003c/kbd\u003e + \u003ckbd\u003eC\u003c/kbd\u003e\n\n    Click on the console-tab, as that's where we want to be most of the time. It should look something like this:\n\n    \u003cimg src=\"images/c13ccd5054a2d8e9f56a0df563bfb6f8b9d370331761bfbeb8f4c2ba8f4f74ec.png\" /\u003e\n\n    If something goes wrong during development, you should get some kind of explanation or pointers here.\n\n## 🕸️ Create a Web App\n\nYour app starts inn App.js\\*,\n\n\u003cimg src=\"images/7c8e918208c3769dec6ed687b06e271a8fd98737faf29ef6f8473f19a7d35c8e.png\" width=200 /\u003e  \n\n_\\*I will rename the file to App.jsx, because of personal preference. Feel free to do the same - just remember to restart Expo, by terminating it in the console (Click on the terminal, \u003ckbd\u003eCtrl\u003c/kbd\u003e + \u003ckbd\u003eC\u003c/kbd\u003e) and running `yarn web` afterwards._\n\nThe file will look something like this:\n\n```js\n// App.jsx\nimport { StatusBar } from 'expo-status-bar';\nimport React from 'react';\nimport { StyleSheet, Text, View } from 'react-native';\n\nexport default function App() {\n  return (\n    \u003cView style={styles.container}\u003e\n      \u003cText\u003eOpen up App.js to start working on your app!\u003c/Text\u003e\n      \u003cStatusBar style=\"auto\" /\u003e\n    \u003c/View\u003e\n  );\n}\n\nconst styles = StyleSheet.create({\n  container: {\n    flex: 1,\n    backgroundColor: '#fff',\n    alignItems: 'center',\n    justifyContent: 'center',\n  },\n});\n\n```\n\nLet's reduce this as much as possible.\n\n```js\n// App.jsx\nimport React from \"react\";\n\nexport default () =\u003e {\n  return null;\n}\n```\n\n_Note: Remember to save for each change we do in the code!_ \n\nFirst we want a nice background. Go to [PixaBay](https://pixabay.com/) and find yourself a nice one. They are open source and free for commercial use.\n\nDrag and drop it to your 📂 `assets`-folder.  \nIf that didn't work, right click the folder and pick `Reveal in File Explorer` (or equivalent, e.g. Finder), and put the image there.\n\nThen, we import it and use it as source in an `ImageBackground`-tag.\n\n```js\n// App.jsx\nimport React from \"react\";\nimport { ImageBackground } from \"react-native\";\nimport background from \"./assets/kitten.jpg\";\n\nexport default () =\u003e {\n  return (\n    \u003cImageBackground\n      source={background}\n      style={{ height: \"100%\" }}\n    \u003e\u003c/ImageBackground\u003e\n  );\n};\n```\n\nMake sure this line is actually pointing to your image, and that the image exists in `assets`.\n\n```js\n// App.jsx, line 3\nimport background from \"./assets/kitten.jpg\";\n```\n\n\u003cimg src=\"images/52b419ec2c1726e40081bfd45317d45e1a93271eb7d798a5c7804fa1b6769026.png\" /\u003e  \n\nWow. Amazing.\n\nLet's hide that cute cat behind a card where we can sketch out our actual app.\n\nWe could reinvent the wheel here, and design all our components ourselves - but I would almost exclusively recommend using a library or framework for your UI, as you will save an enormous amount of time and effort.\n\nI will use [UI Kitten](https://akveo.github.io/react-native-ui-kitten/), for obvious reasons. 🐈\n\nFirst, we need to install it, so open up a new terminal.\n\n\u003cimg src=\"images/b0722cb2d3c674783474d50f45cc44c6048f4a44075c9117ecd9029100bea662.png\" /\u003e  \n\nAnd run these commands.\n\n```shell\nyarn add @ui-kitten/components @eva-design/eva\n```\n\n```shell\nexpo install react-native-svg@9.13.6 @expo/webpack-config\n```\n\nUI Kitten has some problems running with Expo out of the box at the moment, so we will have to show them how to be friends first.\n\nCreate a new file `webpack.config.js` in the *root* of your project (make sure it's not in a folder)...\n\n\u003cimg src=\"images/c5e1cf1e829f8b2dad8ecb47a2554a9ab35b37f79fbd4a2809ff9789ba5b2dc2.png\" width=200 /\u003e\n\u003cbr\u003e\n\u003cimg src=\"images/41edf6b646fcf62cfa350e21c214dfc68b518134e790645bc63cf569624fe1e2.png\" width=200 /\u003e  \n\n...and paste this into it:\n\n```js\n// webpack.config.js\nconst createExpoWebpackConfigAsync = require(\"@expo/webpack-config\");\n\nmodule.exports = async function (env, argv) {\n  const config = await createExpoWebpackConfigAsync(\n    {\n      ...env,\n      babel: {\n        dangerouslyAddModulePathsToTranspile: [\"@ui-kitten/components\"],\n      },\n    },\n    argv\n  );\n  return config;\n};\n```\n\n_Note: Remember to save._\n\nMake sure you are in the node terminal running Expo.\n\n\u003cimg src=\"images/a5c7bafcfdf52efa75a44b86b66737af4ed3780a239002f74310c92639f836c1.png\" /\u003e  \n\nRestart Expo by terminating it in the console (Click on the terminal, \u003ckbd\u003eCtrl\u003c/kbd\u003e + \u003ckbd\u003eC\u003c/kbd\u003e) and running `yarn web` when done.\n\nWrap our app with UI Kittens `\u003cApplicationProvider /\u003e` and add a card with some text from their library.\n\n```js\n// App.jsx\nimport React from \"react\";\nimport { ImageBackground } from \"react-native\";\nimport background from \"./assets/kitten.jpg\";\nimport * as eva from \"@eva-design/eva\";\nimport { ApplicationProvider, Card, Text } from \"@ui-kitten/components\";\n\nexport default () =\u003e {\n  return (\n    \u003cApplicationProvider {...eva} theme={eva.dark}\u003e\n      \u003cImageBackground source={background} style={{ height: \"100%\" }}\u003e\n        \u003cCard\n          style={{\n            margin: \"auto\",\n            width: 500,\n            maxWidth: \"100%\",\n          }}\n          disabled\n        \u003e\n          \u003cText\u003eApp\u003c/Text\u003e\n        \u003c/Card\u003e\n      \u003c/ImageBackground\u003e\n    \u003c/ApplicationProvider\u003e\n  );\n};\n```\n\n\u003cimg src=\"images/ec3a0b224364dd435f427efa9299b2fbbc17f115525b673fc74e3176485db643.png\" /\u003e  \n\nAdd a header to your card, so you can display the app name and optionally a tagline or something of the sort.\n\n```js\n// App.jsx\nimport React from \"react\";\nimport { ImageBackground, View } from \"react-native\";\nimport background from \"./assets/kitten.jpg\";\nimport * as eva from \"@eva-design/eva\";\nimport { ApplicationProvider, Card, Text } from \"@ui-kitten/components\";\n\nexport default () =\u003e {\n  return (\n    \u003cApplicationProvider {...eva} theme={eva.dark}\u003e\n      \u003cImageBackground source={background} style={{ height: \"100%\" }}\u003e\n        \u003cCard\n          header={Header}\n          style={{\n            margin: \"auto\",\n            width: 500,\n            maxWidth: \"100%\",\n          }}\n          disabled\n        \u003e\n          \u003cText\u003eApp\u003c/Text\u003e\n        \u003c/Card\u003e\n      \u003c/ImageBackground\u003e\n    \u003c/ApplicationProvider\u003e\n  );\n};\n\nconst Header = (props) =\u003e (\n  \u003cView {...props}\u003e\n    \u003cText category=\"h6\"\u003eCatculator\u003c/Text\u003e\n    \u003cText category=\"s1\"\u003ePurr purr\u003c/Text\u003e\n  \u003c/View\u003e\n);\n```\n\n\u003cimg src=\"images/1728522c5ef048d6c4c4c1ee5df5998939a64eb26fb3897d77a674cd08163558.png\" /\u003e  \n\n_Yes, I know it says **Kitten App** in the pictures. I didn't get the very official trademark **Catculator™** certified by a [qualified lawyer ](https://upload.wikimedia.org/wikipedia/commons/4/45/Cat_lawyer.jpg) before the tutorial was complete. Will I redo all the pictures? Nopetiy-nope._\n\nMost often an app needs input from a user, so let's add a tiny form.\n\n```js\n// App.jsx\nimport React from \"react\";\nimport { ImageBackground, View } from \"react-native\";\nimport background from \"./assets/kitten.jpg\";\nimport * as eva from \"@eva-design/eva\";\nimport {\n  ApplicationProvider,\n  Button,\n  Card,\n  Input,\n  Text,\n} from \"@ui-kitten/components\";\n\nexport default () =\u003e {\n  return (\n    \u003cApplicationProvider {...eva} theme={eva.dark}\u003e\n      \u003cImageBackground source={background} style={{ height: \"100%\" }}\u003e\n        \u003cCard\n          header={Header}\n          style={{\n            margin: \"auto\",\n            width: 500,\n            maxWidth: \"100%\",\n          }}\n          disabled\n        \u003e\n          \u003cInput\n            label=\"Describe your favorite cat\"\n            placeholder=\"Type here...\"\n          /\u003e\n          \u003cSeparator /\u003e\n          \u003cInput\n            label=\"How many cats do you want?\"\n            placeholder=\"Give a number...\"\n          /\u003e\n          \u003cSeparator /\u003e\n          \u003cButton\u003eCalculate your love for Cats\u003c/Button\u003e\n        \u003c/Card\u003e\n      \u003c/ImageBackground\u003e\n    \u003c/ApplicationProvider\u003e\n  );\n};\n\nconst Separator = () =\u003e {\n  return \u003cView style={{ margin: 8 }}\u003e\u003c/View\u003e;\n};\n\nconst Header = (props) =\u003e (\n  \u003cView {...props}\u003e\n    \u003cText category=\"h6\"\u003eCatculator\u003c/Text\u003e\n    \u003cText category=\"s1\"\u003ePurr purr\u003c/Text\u003e\n  \u003c/View\u003e\n);\n```\n\n\u003cimg src=\"images/15cdc320e8da4fe73af11f7e90194200826abdfad4718e242a1a515d1d844a2a.png\" /\u003e  \n\nThe form is now just visual elements on the card, but we have to add some functionality to call it an app.\n\nThere are endless ways of doing this, so I will make it as simple as possible and only use React components and functions here. If you want to learn ways of doing stuff like this more efficiently and scalable, take a look at my playlist: [Zero to Fullstack Hero](https://www.youtube.com/playlist?list=PLzWjrc7MKKxyffsM7YTBnogYpBh_QUIO0).\n\nIf you are not familiar with what's going on below, just copy-paste the whole thing and learn those concepts later by watching the playlist.\n\n```js\n// App.jsx\nimport React, { useState } from \"react\";\nimport { ImageBackground, View } from \"react-native\";\nimport background from \"./assets/kitten.jpg\";\nimport * as eva from \"@eva-design/eva\";\nimport {\n  ApplicationProvider,\n  Button,\n  Card,\n  Input,\n  Text,\n} from \"@ui-kitten/components\";\n\nexport default () =\u003e {\n  const [fav, setFav] = useState(\"\");\n  const [num, setNum] = useState(\"\");\n  const [luv, setLuv] = useState(\"\");\n\n  return (\n    \u003cApplicationProvider {...eva} theme={eva.dark}\u003e\n      \u003cImageBackground source={background} style={{ height: \"100%\" }}\u003e\n        \u003cCard\n          header={Header}\n          style={{\n            margin: \"auto\",\n            width: 500,\n            maxWidth: \"100%\",\n          }}\n          disabled\n        \u003e\n          \u003cInput\n            label=\"Describe your favorite cat\"\n            placeholder=\"Type here...\"\n            value={fav}\n            onChangeText={(text) =\u003e {\n              setFav(text);\n            }}\n          /\u003e\n          \u003cSeparator /\u003e\n          \u003cInput\n            label=\"How many cats do you want?\"\n            placeholder=\"Give a number...\"\n            value={num}\n            onChangeText={(text) =\u003e {\n              setNum(text.replace(/[^0-9]/g, \"\"));\n            }}\n            number-pad=\"numeric\"\n          /\u003e\n          \u003cSeparator /\u003e\n          \u003cButton\n            onPress={() =\u003e {\n              if (fav !== \"\" \u0026\u0026 num !== \"\") {\n                setLuv(fav.length * Number(num));\n              } else {\n                setLuv(\"Fill in the important form above first.\");\n              }\n            }}\n          \u003e\n            Calculate your love for Cats\n          \u003c/Button\u003e\n          {!!luv \u0026\u0026 (\n            \u003c\u003e\n              \u003cSeparator /\u003e\n              \u003cText category=\"s1\" style={{ margin: \"auto\" }}\u003e\n                {luv}\n              \u003c/Text\u003e\n            \u003c/\u003e\n          )}\n        \u003c/Card\u003e\n      \u003c/ImageBackground\u003e\n    \u003c/ApplicationProvider\u003e\n  );\n};\n\nconst Separator = () =\u003e {\n  return \u003cView style={{ margin: 8 }}\u003e\u003c/View\u003e;\n};\n\nconst Header = (props) =\u003e (\n  \u003cView {...props}\u003e\n    \u003cText category=\"h6\"\u003eCatculator\u003c/Text\u003e\n    \u003cText category=\"s1\"\u003ePurr purr\u003c/Text\u003e\n  \u003c/View\u003e\n);\n```\n\n\u003cimg src=\"images/3879a39fbc496d50e409a5da6cc56d9f973ece7f15aae903e0dc734c28f95437.png\" /\u003e  \n\nCongrats - we now have a functioning web app! 😻\n\nThis level is sufficient for most prototypes, and you can be safe knowing that your code will be useable (with some tweaks) on mobile as well.\n\nIf you don't need an app yet, skip ahead to [🌐 Publish to web *- for free!*](#-publish-to-web---for-free).\n\n## 📱 iOS and Android\n\nInstall the [Expo Development Client](https://expo.io/tools#client) on your mobile device of choice.\n\n\u003cimg src=\"images/08ec57965f39030326e5dcd2d7b0d6329c3a98bb49da25c1e9fdd0e8b12e3a06.png\" /\u003e  \n\nConnect the device to the same network as your development environment (this probably won't work on a school- or work network - more on that below\\*).\n\nOpen up the Expo app\n\nPress `Scan QR Code`\n\nScan the QR code on your Expo server\n\n\u003cimg src=\"images/2e2c8081ac60d67e10ee523f667949bcfd643dbf1f49d7cba000f118041205ff.png\" width=500 /\u003e  \n\nYou should connect automatically\n\n\u003cimg src=\"images/33df5d97790ffc424766de51029298058e19abad1349399dc7b007abaddbbb8e.png\" width=250 /\u003e  \n\n\n_\\*IF you can't connect your device on the same network, switch to \u003cbutton\u003eTunnel\u003c/button\u003e instead of \u003cbutton\u003eLAN\u003c/button\u003e and try again._\n\n---\n\nIf you can't connect directly, you will have to install an emulator for iOS (Mac only) or Android. We won't go into detail about that here, but check out these guides if you had no luck with the above method:\n\n- [iOS](https://docs.expo.io/workflow/ios-simulator/)  \n- [Android](https://docs.expo.io/workflow/android-studio-emulator/)\n\nIf nothing works, just read on and try again on another network.\n\n---\n\nNow onto testing the app!\n\nI'll just press the calculate button...\n\n\u003cimg src=\"images/8067c0afedb5c84a3c1aec2e82401a80ee4847c77e3c6125740b1a615bd7cdba.png\" width=250 /\u003e  \n\nUh-oh 😓\n\nThat text is supposed to be center aligned. That probably means that `margin: \"auto\"` doesn't center things on the app. That can be fixed by using `textAlign: \"center\"` instead.\n\nThinking about it, the card was supposed to be vertically centered on the screen as well. We'll have to fix that by using [Flexbox](https://css-tricks.com/snippets/css/a-guide-to-flexbox/).\n\n`Describe your favorite cat` seems to work ok.\n\n`How many cats do you want?` does work, but should really have a number pad as the default input. Seems like I didn't do it right when writing the web app. I wrote `number-pad=\"numeric\"`, but it should really be `keyboardType=\"number-pad\"` - woopsies! 🤷‍♂️\n\n```js\n// App.jsx\nimport React, { useState } from \"react\";\nimport { ImageBackground, View } from \"react-native\";\nimport background from \"./assets/kitten.jpg\";\nimport * as eva from \"@eva-design/eva\";\nimport {\n  ApplicationProvider,\n  Button,\n  Card,\n  Input,\n  Text,\n} from \"@ui-kitten/components\";\n\nexport default () =\u003e {\n  const [fav, setFav] = useState(\"\");\n  const [num, setNum] = useState(\"\");\n  const [luv, setLuv] = useState(\"\");\n\n  return (\n    \u003cApplicationProvider {...eva} theme={eva.dark}\u003e\n      \u003cImageBackground\n        source={background}\n        style={{\n          height: \"100%\",\n          display: \"flex\",\n          justifyContent: \"center\",\n          alignItems: \"center\",\n        }}\n      \u003e\n        \u003cCard\n          header={Header}\n          style={{\n            width: 500,\n            maxWidth: \"100%\",\n          }}\n          disabled\n        \u003e\n          \u003cInput\n            label=\"Describe your favorite cat\"\n            placeholder=\"Type here...\"\n            value={fav}\n            onChangeText={(text) =\u003e {\n              setFav(text);\n            }}\n          /\u003e\n          \u003cSeparator /\u003e\n          \u003cInput\n            label=\"How many cats do you want?\"\n            placeholder=\"Give a number...\"\n            value={num}\n            onChangeText={(text) =\u003e {\n              setNum(text.replace(/[^0-9]/g, \"\"));\n            }}\n            keyboardType=\"number-pad\"\n          /\u003e\n          \u003cSeparator /\u003e\n          \u003cButton\n            onPress={() =\u003e {\n              if (fav !== \"\" \u0026\u0026 num !== \"\") {\n                setLuv(fav.length * Number(num));\n              } else {\n                setLuv(\"Fill in the important form above first.\");\n              }\n            }}\n          \u003e\n            Calculate your love for Cats\n          \u003c/Button\u003e\n          {!!luv \u0026\u0026 (\n            \u003c\u003e\n              \u003cSeparator /\u003e\n              \u003cText\n                category=\"s1\"\n                style={{\n                  textAlign: \"center\",\n                }}\n              \u003e\n                {luv}\n              \u003c/Text\u003e\n            \u003c/\u003e\n          )}\n        \u003c/Card\u003e\n      \u003c/ImageBackground\u003e\n    \u003c/ApplicationProvider\u003e\n  );\n};\n\nconst Separator = () =\u003e {\n  return \u003cView style={{ margin: 8 }} /\u003e;\n};\n\nconst Header = (props) =\u003e (\n  \u003cView {...props}\u003e\n    \u003cText category=\"h6\"\u003eCatculator\u003c/Text\u003e\n    \u003cText category=\"s1\"\u003ePurr purr\u003c/Text\u003e\n  \u003c/View\u003e\n);\n```\n\n\u003cimg src=\"images/974dbf31eef43fd0a2ecf583ea462c103f79e8caa6021193a83dc54a865f1308.png\" width=250 /\u003e  \n\nThat's better! 😸\n\n## ✨ Icons and Info\n\nIn your files there is a folder named 📁 `assets`, where you'll find some images other than our background:\n\n- `splash.png`  \n    The opening/loading screen of your application\n- `icon.png`  \n    Icon used on iOS, Android and on Expo\n- `adaptive-icon.png`  \n    Two layered icon used on Android, which will be used by the OS for things like animations.\n- `favicon.png`  \n    Icon shown on the web\n\n_Note that there are [guidelines](https://docs.expo.io/guides/app-icons/) if you want to publish your app to a store, but we won't dive into that._\n\nDelete `splash.png`, `icon.png`, `adaptive-icon.png` and `favicon.png`.\n\nTo simplify and save some time, we will use the same image for all of them.\n\nSome requirements for the icon:\n\n- It must be 1:1 aspect ratio, so you might need to crop\n- Expo wants PNG-files, so if you find a JPG that you really want to use, you can convert it with [JPGtoPNG](https://jpg2png.com/)\n\nYou can copy [my icon](https://pixabay.com/vectors/kitten-head-kitty-feline-domestic-576502/), or find a new one on [PixaBay](https://pixabay.com/) (the vector search is probably your best bet there).\n\nPut the image in the 📁 `assets`-folder, and call it `logo.png`.\n\nOpen up the file `app.json`, so we can tell Expo we have a new image for everything. Change every image from 📁 `assets` to our new image.\n\n```json\n{\n  \"expo\": {\n    \"name\": \"catculator\",\n    \"slug\": \"catculator\",\n    \"version\": \"1.0.0\",\n    \"orientation\": \"portrait\",\n    \"icon\": \"./assets/logo.png\",\n    \"splash\": {\n      \"image\": \"./assets/logo.png\",\n      \"resizeMode\": \"contain\",\n      \"backgroundColor\": \"#ffffff\"\n    },\n    \"updates\": {\n      \"fallbackToCacheTimeout\": 0\n    },\n    \"assetBundlePatterns\": [\"**/*\"],\n    \"ios\": {\n      \"supportsTablet\": true\n    },\n    \"android\": {\n      \"adaptiveIcon\": {\n        \"foregroundImage\": \"./assets/logo.png\",\n        \"backgroundColor\": \"#FFFFFF\"\n      }\n    },\n    \"web\": {\n      \"favicon\": \"./assets/logo.png\"\n    },\n    \"description\": \"\"\n  }\n}\n```\n\nHere you can also add information about your app. Almost everything I want is here, except for a description - so I'll add that.\n\n```json\n{\n  \"expo\": {\n    \"name\": \"catculator\",\n    \"slug\": \"catculator\",\n    \"version\": \"1.0.0\",\n    \"orientation\": \"portrait\",\n    \"icon\": \"./assets/logo.png\",\n    \"splash\": {\n      \"image\": \"./assets/logo.png\",\n      \"resizeMode\": \"contain\",\n      \"backgroundColor\": \"#ffffff\"\n    },\n    \"updates\": {\n      \"fallbackToCacheTimeout\": 0\n    },\n    \"assetBundlePatterns\": [\"**/*\"],\n    \"ios\": {\n      \"supportsTablet\": true\n    },\n    \"android\": {\n      \"adaptiveIcon\": {\n        \"foregroundImage\": \"./assets/logo.png\",\n        \"backgroundColor\": \"#FFFFFF\"\n      }\n    },\n    \"web\": {\n      \"favicon\": \"./assets/logo.png\"\n    },\n    \"description\": \"A kitty love calculator for educational purposes\"\n  }\n}\n```\n\n## 🌐 Publish to web *- free!*\n\nConnect your GitHub-user to [Vercel](https://vercel.com/login?next=%2Fdashboard)\n\nInstall [Vercel CLI](https://vercel.com/download) (using the terminal)\n\n```shell\nyarn global add vercel\n```\n\nOptimize assets\n\n```shell\nyarn global add sharp-cli\nnpx expo-optimize\n```\n\nBuild the web application\n\n```shell\nexpo build:web\n```\n\nGo into the web build\n\n```shell\ncd web-build\n```\n\nDeploy to Vercel\n\n```shell\nvercel\n```\n\nFollow the instructions. If it's the first time you use Vercel, you'll have to run the command `vercel` again after you're logged in.\n\nPress \u003ckbd\u003eenter\u003c/kbd\u003e for *all* prompts. You don't have to input anything.\n\nThe final command should give you the url to visit your webpage when it's done.\n\nIf it doesn't work or you want to adjust hosting settings, visit your [Vercel dashboard](https://vercel.com/dashboard). You'll find everything you need to administer your web page there.\n\n\n## 📲 Publish app for testing *- free!*\n\n[Create an Expo account](https://expo.io/signup).\n\nRun the following in the terminal:\n\n```shell\nexpo publish\n```\n\nLogin when prompted\n\nGo to [Expo](https://expo.io/)\n\nLogin (if you haven't already)\n\nGo to your projects\n\n\u003cimg src=\"images/e8ec7155af89eda06b1e82cfa44bb1e50342a6f7c402ad23cc229814e37da9be.png\" /\u003e  \n\nClick on your project name\n\n\u003cimg src=\"images/45a20c4a5ec03202a3b4783b0bbaa07a3088b582b4011f018345cdd6a04c0368.png\" /\u003e  \n\nThere you should be presented with the information needed to test your app on mobile. Send the link in the address bar to your testers.\n\n## 💲 Publish to app stores *- not free...*\n\nThis is outside the scope of this tutorial, as we are only creating a prototype.\n\nExpo offers [documentation on how you can upload apps to the official app stores](https://docs.expo.io/distribution/uploading-apps/), when you and your app is ready.\n\n## 💾 Save and push changes to GitHub\n\nGreat work! Now you should make sure everything is saved and push the changes to your repository.\n\nEnter the source control tab\n\n\u003cimg src=\"images/ad3c04dd3f1f83e3a3652f662910f364dda3fdf981cff164b27ff67ce7108fd3.png\" /\u003e  \n\nEnter a *short* description of what you did\n\n\u003cimg src=\"images/703ad19eb58f302c3f3d2baf52de18a32bd139588ffc405d50f53c431702f61c.png\" /\u003e  \n\nStage all your changes\n\n\u003cimg src=\"images/d2fa2ba7107cf529e3109b146c6b824c1eaa402c81d4185f21ea577990a0800e.png\" /\u003e  \n\nCommit all your staged changes\n\n\u003cimg src=\"images/bc4b857b48c946e077662034024d7447f86a2c5f2aca021c57b7dc2eaf779d55.png\" /\u003e  \n\nPush your changes\n\n\u003cimg src=\"images/0c7f73d6644416994d00cce55d4286970b6644764ef74145be3da59e25d53650.png\" /\u003e  \n\nThere are shortcuts for doing all of this, but as there are so many different ways and operating systems, I leave it up to you to figure out faster ways of doing this.\n\n## 🤔 What's next?\n\nIf you liked this and want to learn more about web development, check out the [Zero to Fullstack Hero](https://www.youtube.com/playlist?list=PLzWjrc7MKKxyffsM7YTBnogYpBh_QUIO0).\n\nOther than that, you can go ahead and make an app. Remember that Google is your friend, as am I, so ask either one of us if you need any help.\n\nIf you need some more advanced functionality, like users and data storage, you might want to check out Google's [Firebase](https://firebase.google.com/). It's by far the most powerful backend tool for small startups in my opinion, and will scale like a singing reptile on a diet.\n\n[I'm available for help at Facebook](https://www.facebook.com/kristian.kramas).\n\nGood luck! 🎉\n\n## 💡 Tips and Tricks\n\nWe did web first in this example to make it easier to follow along, but when you're developing, it may be a good idea to have a live version of your app open on iOS or Android (both preferably), so that you catch any errors and special cases as they pop up.\n\nAn emulator is great, if you want to set that up for [Android](https://docs.expo.io/workflow/android-studio-emulator/) or [iOS](https://docs.expo.io/workflow/android-studio-emulator/) (Mac only 💔), but it's not the same as having a device in your hand.\n\nIf something technically works on mobile and looks good, it will usually work on the web (except native features obviously) and scale great up to a bigger screen. If you want to save time, it's often a good idea to design your app [mobile first](https://medium.com/@Vincentxia77/what-is-mobile-first-design-why-its-important-how-to-make-it-7d3cf2e29d00).\n\nIf you want to clone this repo, this is how to do so:\n   1. Copy the GitHub-repo URL (the HTTPS one)\n\n      \u003cimg src=\"images/4f3e2d6e482dfd2039f427134abfedde069bfd236c233297665782cbb5942d07.png\" width=350 /\u003e  \n\n   2. Open the command palette (\u003ckbd\u003eCtrl\u003c/kbd\u003e + \u003ckbd\u003eShift\u003c/kbd\u003e + \u003ckbd\u003eP\u003c/kbd\u003e or \u003ckbd\u003eF1\u003c/kbd\u003e) and use the command `Git: Clone`\n   3. Paste the URL\n   4. Choose where you want to store it\n      _Note: Cloning it will create a new folder with the project name where you choose to place it, so there is no need to make a new dedicated folder for it manually._\n   5. Say yes to open the project in its own workspace\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvidundergunder%2Fexpo-prototype-tutorial","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvidundergunder%2Fexpo-prototype-tutorial","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvidundergunder%2Fexpo-prototype-tutorial/lists"}