RORK LABJP
BUILD — Rork Max runs real Macs in the cloud loaded with Xcode and the iOS SDK, writing SwiftUI, compiling, reading the errors and building again. That loop, not the code generation, is what lifts the outputNATIVE — What comes out is pure Swift and SwiftUI, not React Native. Reaching AR, Metal graphics and widgets that React Native cannot touch is the real gap between this and other buildersPLATFORMS — Coverage spans iPhone, iPad, Apple Watch, Apple TV and Vision Pro, plus iMessage. Worth a look if you want to start from a watch app or an extension rather than a phone screenCOMPANION — The Rork Companion app lets you check a generated build on a real iPhone without a paid Apple Developer account, lowering the bar for trying a first project end to endPRICING — Free to start, paid plans from $25 a month, and Rork Max on the $200 Max plan. Worth working out up front how many projects it takes to earn that backDEADLINE — From August 31, 2026, Google Play requires target API level 36 or higher for new apps and updates alike. Ten days out, and the targetSdkVersion of what you generate is yours to verifyBUILD — Rork Max runs real Macs in the cloud loaded with Xcode and the iOS SDK, writing SwiftUI, compiling, reading the errors and building again. That loop, not the code generation, is what lifts the outputNATIVE — What comes out is pure Swift and SwiftUI, not React Native. Reaching AR, Metal graphics and widgets that React Native cannot touch is the real gap between this and other buildersPLATFORMS — Coverage spans iPhone, iPad, Apple Watch, Apple TV and Vision Pro, plus iMessage. Worth a look if you want to start from a watch app or an extension rather than a phone screenCOMPANION — The Rork Companion app lets you check a generated build on a real iPhone without a paid Apple Developer account, lowering the bar for trying a first project end to endPRICING — Free to start, paid plans from $25 a month, and Rork Max on the $200 Max plan. Worth working out up front how many projects it takes to earn that backDEADLINE — From August 31, 2026, Google Play requires target API level 36 or higher for new apps and updates alike. Ten days out, and the targetSdkVersion of what you generate is yours to verify
Articles/Getting Started
Getting Started/2026-08-17Beginner

Write .gitignore Before You Run git init on an Exported Rork Project

Running git init on a freshly exported Rork project puts your signing keys and .env straight into history. I measured what gets committed when the ignore file comes first versus last, and which exclusion patterns actually work.

Rork539GitHubgitignoreExpo175exportbeginner21

You have exported your Rork app, unzipped it on your machine, and you are ready to put it in your own GitHub repository.

Most people open the folder and immediately type git init. That single ordering choice costs more than anything else in this workflow.

The exported folder ships with files that should never leave your machine. And Git does not forget: once something lands in a commit, deleting it later does not remove it from history.

So I set up the two orderings side by side and measured what actually gets committed in each case. Three commands, and the difference is stark.

The exported folder mixes your app with things that must stay local

Unpack a Rork export and you get a mix of files you wrote and files you have never seen before.

File or folder What it is Push to GitHub?
app/ assets/ app.json Your actual app Yes
package.json package-lock.json Your dependency list and its pinned versions Yes
node_modules/ The dependencies themselves, rebuilt any time by npm install No
.env .env.production API keys and endpoints Never
*.p8 *.jks *.keystore Signing credentials for App Store and Google Play submissions Never
google-services.json GoogleService-Info.plist Firebase connection details No
ios/ android/ Native projects generated by expo prebuild It depends (see below)
.expo/ Local dev server cache No

Skipping node_modules/ is a size question. Skipping .env and your signing keys is a different category of problem.

If those reach a public repository even once, deleting them does not undo it. Your only real remedy is to issue new credentials.

With the ignore file first, only nine files were staged

Here is the "ignore file first" run.

I recreated the shape of a fresh export, then wrote .gitignore before touching git init:

node_modules/
.expo/
dist/
web-build/
ios/
android/
*.p8
*.p12
*.jks
*.keystore
*.mobileprovision
google-services.json
GoogleService-Info.plist
.env
.env.*
!.env.example
npm-debug.log*
yarn-error.log*
.DS_Store

.gitignore is a plain text file that tells Git "anything matching these names does not need to be tracked." It lives at the top level of your project, spelled exactly like that.

Then git init, git add -A, and a look at what made it in:

$ git status --porcelain | sed 's/^A  //' | sort
.gitignore
app.json
app/(tabs)/index.tsx
assets/images/icon.png
eas.json
expo-env.d.ts
package-lock.json
package.json
tsconfig.json

Nine files. No .env, no keys, no node_modules/.

If you want to know which line stopped which file, git check-ignore -v reports it:

$ git check-ignore -v .env node_modules/expo/package.json AuthKey_ABC123.p8
.gitignore:14:.env              .env
.gitignore:1:node_modules/      node_modules/expo/package.json
.gitignore:7:*.p8               AuthKey_ABC123.p8

The left side is the line number in .gitignore, the right side is the file it caught. Useful whenever you add a rule and want to confirm it bites.

Reverse the order and the ignore file arrives too late

Now the other run, which is the one worth internalizing.

I committed first and thought about .gitignore afterwards. Six files were tracked:

$ git ls-files
.env
.expo/devices.json
AuthKey_ABC.p8
app.json
node_modules/expo/package.json
package.json

Your .env and your .p8 are now part of the repository.

Noticing the mistake, I wrote a proper .gitignore and committed again. Nothing changed:

$ git ls-files | grep -E '\.env|node_modules|\.expo|p8'
.env
.expo/devices.json
AuthKey_ABC.p8
node_modules/expo/package.json

All four still tracked. .gitignore only governs files Git is not yet tracking. Once tracking begins, the rules no longer reach them.

Untracking has to be explicit:

git rm -r --cached node_modules .expo .env AuthKey_ABC.p8
git commit -m "Stop tracking local-only files"

--cached leaves the files on disk and removes them from Git's index only. That dropped the tracked set to three files.

But here is the part that matters. Earlier commits still hold everything:

$ git cat-file -p HEAD~2:.env
(the contents of the .env you "deleted", printed back at you)

So a key that has been pushed to a public repository should be treated as compromised, no matter how carefully you clean up afterwards. At that point I rotate the credential before doing anything else. As an indie developer you are the only holder of that key, so nobody else is going to catch it for you. Every Key You Ship Is Public: Secret Boundaries and Rotation for Rork-Generated Apps walks through where to draw the boundary and how to rotate.

Get the order right and none of this cleanup exists. It is a three-minute difference.

Negation works on file patterns and fails under ignored directories

A line starting with ! in .gitignore means "this one is an exception, track it anyway."

It is handy, but it works in one situation and silently does nothing in another. I ran both.

The working case: block every .env.* variant, then let the shareable template through.

.env
.env.*
!.env.example

After git add -A:

$ git diff --cached --name-only
.env.example
.gitignore
app.json

.env.example is in. .env.local and .env.production are not. Exactly as intended.

The failing case: ignore ios/ wholesale, then try to keep ios/Podfile.

ios/
!ios/Podfile
$ git diff --cached --name-only
.gitignore
app.json

No ios/Podfile. The syntax is fine, and Git simply skips it.

Pattern How the block is written Outcome
.env.* plus !.env.example Blocked by filename pattern Exception applies
ios/ plus !ios/Podfile Blocked as a whole directory Exception ignored

The reason is that once Git excludes a directory, it stops descending into it. Never having looked inside, it never reads your exception for a file within.

To keep one file out of an otherwise unwanted folder, block the contents rather than the folder: ios/build/ and ios/Pods/ instead of ios/.

One more caution: do not judge this by git check-ignore -v alone. When a ! line matches, the tool reports that match, which reads as if the file were being handled. The reliable check is git add -A followed by git diff --cached --name-only.

Whether to commit ios/ and android/ depends on how you build

This is the "it depends" row from the first table, and the answer genuinely varies.

One question settles it: are you hand-editing anything on the native side?

Your situation ios/ and android/
You let Rork and EAS Build handle everything and have never opened Xcode or Android Studio Ignore them; they are regenerated each time
You configure everything through app.json and config plugins Ignore them
You edited Info.plist or build.gradle directly Commit them; those edits cannot be reproduced otherwise

When unsure, start by ignoring them. Changing your mind later means deleting two lines from .gitignore. Going the other direction, as we just saw, is the expensive one.

Related: running expo prebuild --clean over hand-edited native files discards those edits, which is covered in Find the native edits expo prebuild will erase before you upgrade to SDK 57.

The one-time sequence

Three steps, once per project:

# 1. Enter the exported folder and write .gitignore first
cd my-rork-app
cat > .gitignore <<'EOF'
node_modules/
.expo/
dist/
web-build/
ios/
android/
*.p8
*.p12
*.jks
*.keystore
*.mobileprovision
google-services.json
GoogleService-Info.plist
.env
.env.*
!.env.example
npm-debug.log*
yarn-error.log*
.DS_Store
EOF
 
# 2. Then initialize, and look at what is about to be recorded
git init
git add -A
git diff --cached --name-only
 
# 3. Commit only after confirming no .env and no keys in that list
git commit -m "Initial commit"

Step 2 is the whole article. A few seconds of reading that list, and anything unfamiliar becomes one more line in .gitignore instead of a permanent entry in your history.

Once the repository is up, wiring EAS Build to GitHub Actions is the natural next move; Setting Up CI/CD for Rork Apps with GitHub Actions and EAS Build covers that setup.

For now, run git add -A and git diff --cached --name-only against your own project and see whether anything unexpected shows up. That check alone is enough.

Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

Getting Started2026-05-05
Native App or PWA? Three Questions to Answer Before Building with Rork
Should you build a native app with Rork or go with a PWA? This guide breaks down the real functional differences — push notifications, camera, App Store distribution — and gives you a clear decision framework.
Getting Started2026-05-04
Build a Plant Care Diary App with Rork — Photos, Watering Logs, and Reminders in One Tutorial
Learn how to build a plant care diary app with Rork — covering photo capture, local data storage, and push notification reminders. A hands-on tutorial for the three core features every app needs.
Getting Started2026-05-04
Telling Rork to Make It Feel Like a Quiet Museum — Translating a Creator's Vocabulary Into Implementation
What happens when you hand Rork the mood of your work instead of a spec? A record of prompting from emotion, pinning the returned spacing and timing into design tokens, and the places where fonts and regeneration stopped me.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →