Offline writes that wait
A write made offline is saved, survives a restart, and is sent in order when the connection returns, each with its own idempotency key. Offline










npx create-bareship AcmeIt checks your tools, asks for the bundle id and display name, then creates the app from the
npm template, installs everything and sets the bundle id. Add
--yes to ask nothing, for CI and AI agents. Then cd Acme and pnpm ios or pnpm android.
npx @react-native-community/cli@20.2.0 init Acme --template bareship --skip-install --install-pods falsecd Acmepnpm installbundle installpnpm bootstrap --bundle-id com.acme.app --display-name "Acme"The steps create-bareship runs. The CLI can’t install with pnpm, so it skips the install. Leave out
--package-name: bootstrap sets the bundle id and keeps dev, staging and prod apart.
Click Use this template on the GitHub repository, clone your copy, then:
pnpm installbundle installpnpm bootstrap --name Acme --bundle-id com.acme.app --display-name "Acme"Your copy also holds the template’s own files (this website, the changelog, the contributing guide). Delete the ones you don’t want.
bootstrap sets the bundle ids and display names of dev, staging and prod and moves the Android package to
match, then runs pod install. In a copy of the repository, --name also renames the Xcode project, schemes
and URL schemes; init does that for you. Start an emulator or simulator, run pnpm android or pnpm ios, and sign in with
demo@example.com / password123.
You don’t need a backend, a Firebase project or an Apple Developer team to build the app, run it or put it on a phone. Development builds serve sample data from a mock backend inside the app, and every service falls back when its account is missing:
When you’re ready, Going live lists what to add and what each step switches on.
Offline writes that wait
A write made offline is saved, survives a restart, and is sent in order when the connection returns, each with its own idempotency key. Offline
Tokens in the Keychain
Access and refresh tokens live in the iOS Keychain and Android Keystore, never in plain storage. One refresh serves every request waiting on it. Session
An architecture the linter enforces
Layers import downward only and features never import each other. ESLint and dependency-cruiser fail the build otherwise. Architecture
Firebase when you want it
Crashlytics, Analytics, Remote Config and push switch on when you add a Firebase file, and fall back without one. Set up Firebase
Three environments
Dev, staging and prod install side by side, each with its own app id, name, icon badge, URL
scheme and .env file. Environments
English and Hindi, right-to-left ready
Typed translation keys, a lint rule against hard-coded text, plural rules on Hermes, and layouts that mirror when you add a right-to-left language. Forms and i18n
Generators
pnpm gen feature orders writes a working screen, its API call, mock data, strings, a deep link
and tests that pass. Generators
Releases with fastlane
Version bumps on both platforms, release builds, match signing, and uploads to TestFlight and Play internal testing. Releasing
A demo you can remove
A feed, likes and a component showroom show every pattern. pnpm strip-examples removes them
and leaves a blank Home tab. Demo code
A supply-chain policy
pnpm refuses packages younger than 3 days and install scripts you haven’t allowed, and Renovate groups updates. Decision 0003
Every write in the app picks one of four behaviours, so users always know what happened to what they did.
| Pattern | What the user sees | Use it for |
|---|---|---|
| A | The change appears at once and syncs in the background | Low-stakes toggles |
| B | The change appears at once, marked “Waiting to sync” until it’s sent | Likes, comments, edits |
| C | The form is disabled while offline, with the reason | Sign-in, payments |
| D | The screen is replaced by an offline message | Account deletion, checkout |
Writes queued with A or B survive closing the app and are sent in order when the connection returns. An offline banner sits under the header while the phone is offline. How to choose and use a pattern
The rules your team follows are written down where coding agents read them, and the linter checks the result.
How agents work with the template
A good fit if you
ios/ and android/ and see every native change - build an app that has to work
offline and keep users’ writes - work in a team, or with AI agents, and want the rules checked -
want to start from working code and remove what you don’t needNot a fit if you
Create the app. It checks your tools first, then installs everything and sets the bundle id (other ways: Create an app):
npx create-bareship AcmeStart an emulator or simulator, then run the app and sign in with demo@example.com / password123:
cd Acmepnpm android # or: pnpm iosWhen you start on your own screens, remove the demo and add your first feature:
pnpm strip-examplespnpm gen feature ordersRead the introduction
No. Development builds use a mock backend inside the app. When your API is ready, set API_URL and
API_MOCKS=false in the environment’s .env file. Use your API
No. Without a Firebase file the app logs crashes and analytics to the console, uses default feature flags and shows notifications locally. Add the file when you want the real services.
iOS 15.1 and later, and Android 7.0 (API 24) and later, on React Native 0.87 with the New Architecture. Version matrix
Every change to ios/ and android/ is listed with its Expo equivalent in
Native changes, and native libraries sit behind small interfaces, so the app code
doesn’t depend on how the native side is built.
Your app owns its copy of the code, so nothing updates on its own. Each version is published to npm and listed in the changelog; copy the changes you want.
Nothing. It’s open source under the MIT license.
Made by Praveen Singh, Senior React Native engineer