{"id":17312154,"url":"https://github.com/robincsl/build-standalone-expo-app","last_synced_at":"2025-04-14T14:43:39.569Z","repository":{"id":41781952,"uuid":"175307052","full_name":"RobinCsl/build-standalone-expo-app","owner":"RobinCsl","description":"Accompanying repo for my article \"Build Standalone Expo .apk and .ipa with Turtle CLI\"","archived":false,"fork":false,"pushed_at":"2023-03-04T04:14:06.000Z","size":1032,"stargazers_count":11,"open_issues_count":7,"forks_count":4,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-28T03:41:24.814Z","etag":null,"topics":["apk","article","expo","ipa","turtle-cli","tutorial"],"latest_commit_sha":null,"homepage":"https://www.robincussol.com/build-standalone-expo-apk-ipa-with-turtle-cli/","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/RobinCsl.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":"2019-03-12T22:41:05.000Z","updated_at":"2023-06-09T04:14:46.000Z","dependencies_parsed_at":"2024-10-15T12:42:39.833Z","dependency_job_id":"df37ca23-ec3a-4e5a-9929-eded76d96aa5","html_url":"https://github.com/RobinCsl/build-standalone-expo-app","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobinCsl%2Fbuild-standalone-expo-app","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobinCsl%2Fbuild-standalone-expo-app/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobinCsl%2Fbuild-standalone-expo-app/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobinCsl%2Fbuild-standalone-expo-app/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RobinCsl","download_url":"https://codeload.github.com/RobinCsl/build-standalone-expo-app/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248898744,"owners_count":21179832,"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":["apk","article","expo","ipa","turtle-cli","tutorial"],"created_at":"2024-10-15T12:42:35.428Z","updated_at":"2025-04-14T14:43:39.540Z","avatar_url":"https://github.com/RobinCsl.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Build Standalone Expo .apk and .ipa with Turtle CLI\n\n_This is a condensed version which only shows the commands for each section._\n\nWe will go through the following steps:\n\n1. [Install Turtle CLI](#1-turtle-cli)\n2. [Create a dummy application](#2-create-a-dummy-application)\n3. [Publish Expo app on local server](#3-publish-expo-app-on-local-server)\n4. [Create APK file -- Android](#4-create-apk-file----android)\n5. [Create IPA file -- iOS](#5-create-ipa-file----ios)\n6. [Distribute and install](#6-distribute-and-install)\n\n## 1. [Turtle CLI](https://www.robincussol.com/build-standalone-expo-apk-ipa-with-turtle-cli/#1-turtle-cli)\n\nTo install Turtle CLI, run\n\n```bash\n$ npm install -g turtle-cli\n```\n\n## 2. [Create a dummy application](https://www.robincussol.com/build-standalone-expo-apk-ipa-with-turtle-cli/#2-create-a-dummy-application)\n\nLet's create a dummy application using Expo CLI. In your terminal, run\n\n```bash\n$ npx expo init ExampleApplication\n```\n\nAdd the keys `\"bundleIdentifier\"` under `\"ios\"`, and `\"package\"` under `\"android\"` in your `app.json` file:\n\n```json\n...\n    \"ios\": {\n      ...\n      \"bundleIdentifier\": \"com.example.exampleApplication\",\n      ...\n    },\n    \"android\": {\n      ...\n      \"package\": \"com.example.example_application\",\n      ...\n    }\n...\n```\n\n## 3. [Publish Expo app on local server](https://www.robincussol.com/build-standalone-expo-apk-ipa-with-turtle-cli/#3-publish-expo-app-on-local-server)\n\nAssuming that your local web server will be running on `http://127.0.0.1:8000`, export the app with\n\n```bash\n$ expo export --dev --public-url http://127.0.0.1:8000\n...\nExport was successful. Your exported files can be found in dist\n```\n\n\nServe the `dist` directory on your web server (and make sure it's available at the same URL that you chose for the flag `--public-url` above). For example, run\n\n```bash\n$ npx http-server -p 8000 dist\n```\n\nNote: if for some reason you need to re-export your application (because you modified your `app.json` file since the last export, for instance), you must first remove the `dist` directory:\n\n```bash\n# assuming you are at the root of the project\n$ rm -rf dist\n$ expo export --dev --public-url http://127.0.0.1:8000\n```\n\n## 4. [Create APK file -- Android](https://www.robincussol.com/build-standalone-expo-apk-ipa-with-turtle-cli/#4-create-apk-file----android)\n\nVerify that your local server is running, e.g.\n\n```bash\n$ curl http://127.0.0.1:8000/android-index.json\n{\"name\":\"ExampleApplication\",\"slug\":\"ExampleApplication\",\"version\":\"1.0.0\",\"orientation\":\"portrait\",\"icon\":\"./assets/icon.png\",\"splash\":{\"image\":\"./assets/splash.png\",\"resizeMode\":\"contain\",\"backgroundColor\":\"#ffffff\",\"imageUrl\":\"http://127.0.0.1:8000/assets/201a91bd1740bb1d6a1dbad049310724\"}...\n```\n\nIf you know which Expo SDK version you are going to use, you can run\n\n```bash\n$ turtle setup:android --sdk-version \u003cSDK-VERSION\u003e\n```\n\n### Create Keystore\n\nYou can generate a keystore file with the following command\n```bash\n$ keytool -genkeypair -v -keystore keystore.jks -alias keyalias -keyalg RSA -keysize 2048 -validity 9125\n```\n\n### Build APK\n\nMake sure that you are serving the `dist` directory on http://127.0.0.1:8000 as explained above in **Run a local server**, and run\n\n```bash\nEXPO_ANDROID_KEYSTORE_PASSWORD=\u003cKEYSTORE_PASSWORD\u003e \\\nEXPO_ANDROID_KEY_PASSWORD=\u003cKEY_PASSWORD\u003e \\\nturtle build:android \\\n  --type apk \\\n  --keystore-path \u003cKEYSTORE_PATH\u003e \\\n  --keystore-alias \u003cKEYSTORE_ALIAS\u003e \\\n  --allow-non-https-public-url \\\n  --public-url http://127.0.0.1:8000/android-index.json\n```\n\nOnce the build finishes, take note of the location of your build `.apk` file. For example,\n\n```bash\nFeb 5 08:34:22 turtle[11626] INFO:  copied build to ~/expo-apps/@anonymous__ExampleApplication-6d7e1749c5b64bd0851525b0c7eec780-signed.apk\n  platform: \"android\"\n  buildPhase: \"copying build artifact\"\n```\n\n\n## 5. [Create IPA file -- iOS](https://www.robincussol.com/build-standalone-expo-apk-ipa-with-turtle-cli/#5-create-ipa-file----ios)\n\n\nFirst, verify that your local server is running, e.g.\n\n```bash\n$ curl http://127.0.0.1:8000/ios-index.json\n{\"name\":\"ExampleApplication\",\"slug\":\"ExampleApplication\",\"version\":\"1.0.0\",\"orientation\":\"portrait\",\"icon\":\"./assets/icon.png\",\"splash\":{\"image\":\"./assets/splash.png\",\"resizeMode\":\"contain\",\"backgroundColor\":\"#ffffff\",\"imageUrl\":\"http://127.0.0.1:8000/assets/201a91bd1740bb1d6a1dbad049310724\"...\n```\n\nIf you know which Expo SDK version you are going to use, you can run\n\n```bash\n$ turtle setup:ios --sdk-version \u003cSDK-VERSION\u003e\n```\n\n### Create Signing keys\n\nSee this [section](https://www.robincussol.com/build-standalone-expo-apk-ipa-with-turtle-cli/#52-create-signing-keys) in the article.\n\n\n### Build IPA\n\nMake sure that you are serving the `dist` directory on http://127.0.0.1:8000 as explained **Run a local server**, and run\n\n```bash\nEXPO_IOS_DIST_P12_PASSWORD=\u003cPASSWORD HERE\u003e \\\nturtle build:ios \\\n  --team-id \u003cYOUR_TEAM_ID\u003e \\\n  --dist-p12-path \u003c/path/to/your/dist/cert.p12\u003e \\\n  --provisioning-profile-path \u003c/path/to/your/provisioning/profile.mobileprovision\u003e \\\n  --allow-non-https-public-url \\\n  --public-url http://127.0.0.1:8000/ios-index.json\n```\n\nOnce the build finishes successfully, you should get the path to your `.ipa` file.\n\n## 6. [Distribute and install](https://www.robincussol.com/build-standalone-expo-apk-ipa-with-turtle-cli/#6-distribute-and-install)\n\n### on Android\n\nIf you connect an Android device to your computer, you should be able to run:\n\n```bash\n$ adb devices\nemulator-5554\tdevice\n```\n\nto list all your connected Android devices and emulators. (In my case, only the emulator is \"connected\".)\n\nIt is then possible to install the `.apk` file by running:\n\n```bash\n$ adb -s emulator-5554 install \u003cPATH_TO_YOUR_APK_FILE\u003e\nPerforming Streamed Install\nSuccess\n```\n\n### on iOS\n\n_Caveat: I could not fully test this section, so my apologies if this does not work as intended._\n\nSince you should have Xcode, the most promising solution is in this [guide](https://codeburst.io/latest-itunes-12-7-removed-the-apps-option-how-to-install-ipa-on-the-device-3c7d4a2bc788). It also mentions other ways to install the `.ipa` file.\n\n---\n\nI hope this was helpful. If you have any questions or comments, please drop me a line on [Twitter](https://www.twitter.com/RobinCsl) or create an issue in this repository. I shall reply as soon as possible.\n\n## Resources\n\n- Expo: https://expo.dev\n- Turtle CLI: https://github.com/expo/turtle#readme\n- Expo's guide to Building Standalone apps: https://docs.expo.dev/classic/building-standalone-apps/\n- Configuring `app.json`: https://docs.expo.dev/workflow/configuration/\n- Expo docs to configure CI with Turtle CLI: https://docs.expo.dev/classic/turtle-cli/\n- Expo docs to host application on your own servers: https://docs.expo.dev/distribution/hosting-your-app/\n- How to create a keystore for Android: https://developer.android.com/studio/publish/app-signing#generate-key\n- Supporting GitHub repository: https://github.com/RobinCsl/build-standalone-expo-app/\n\n[1]: https://expo.dev\n[2]: https://github.com/expo/turtle#readme\n[3]: https://developer.android.com/studio/publish/app-signing#generate-key\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobincsl%2Fbuild-standalone-expo-app","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frobincsl%2Fbuild-standalone-expo-app","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobincsl%2Fbuild-standalone-expo-app/lists"}