A production-ready React Native template repository: Expo + Expo Router + Zustand + TanStack Query + EAS deployments, with CI, testing, and template automation wired up out of the box.
- Click Use this template → Create a new repository on GitHub.
- Push your first commit to
main— the template-cleanup workflow runs once and automatically renames the app, slug, URL scheme, and bundle identifiers after your new repo, resets this README, and deletes itself. - Follow the checklist it writes into your new README (link EAS, add secrets, etc.).
| Concern | Choice |
|---|---|
| Framework | Expo SDK 57 (React Native 0.86, React 19, TypeScript strict) |
| Routing | Expo Router — file-based, typed routes |
| UI library | gluestack-ui v2 on NativeWind v4 (Tailwind CSS v3) |
| Client state | Zustand (+ AsyncStorage persistence example) |
| Server state | TanStack Query (app-focus refetch + offline handling) |
| Builds & OTA | EAS Build / Submit / Update via GitHub Actions |
| Testing | Jest (jest-expo) + React Native Testing Library |
| Quality | ESLint (eslint-config-expo), Prettier, tsc --noEmit, CI on every PR |
| Repo hygiene | Issue forms, PR template, CODEOWNERS, Dependabot, SECURITY.md |
- Node 22 (see
.nvmrc) —nvm use - EAS CLI for builds/updates —
npm i -g eas-cli - Xcode (iOS) and/or Android Studio (Android) if you want to run on simulators/emulators. Not required for Expo Go or web.
nvm use
npm install
cp .env.example .env
npx expo start # press i / a / w for iOS / Android / webnpm run typecheck
npm run lint
npm run format:check
npm run test:ciAll four should pass cleanly on a fresh npm install — this is exactly what
CI runs on every PR (see CI). If npm install
reports vulnerabilities, check npm audit before acting on it: most flagged
issues live in Expo's own build tooling (transitive uuid deps in
@expo/config-plugins etc.), not runtime app code, and npm audit fix --force will downgrade Expo to an incompatible major version — don't run it
here.
src/
app/ # Screens & navigation (Expo Router file-based routes)
_layout.tsx # Root layout: providers (Query, theme) + root stack
(tabs)/ # Bottom-tab group (Home, Settings)
+not-found.tsx # 404 route
api/ # Server state: fetch client + TanStack Query hooks
stores/ # Client state: Zustand stores (plain + persisted examples)
components/ui/ # gluestack-ui components (box, stack, text, button, provider)
constants/ # Color strings for React Navigation chrome (tab bar, etc.)
hooks/ # Shared hooks (color scheme, theme)
lib/ # App-wide singletons (query client)
global.css # NativeWind/Tailwind entrypoint
Conventions: import via the @/ alias; screens live in src/app/; server data goes in TanStack Query hooks (src/api/), never in Zustand; EXPO_PUBLIC_* env vars are public — keep secrets out of them.
The UI layer is gluestack-ui v2 on
NativeWind v4 — you style with Tailwind
classNames, not StyleSheet:
import { VStack } from '@/components/ui/vstack';
import { Button, ButtonText } from '@/components/ui/button';
<VStack space="md" className="flex-1 bg-background p-4">
<Button action="primary" onPress={onPress}>
<ButtonText>Continue</ButtonText>
</Button>
</VStack>;Colors are semantic tokens (bg-background, text-foreground, bg-primary, …)
defined per light/dark scheme in
src/components/ui/gluestack-ui-provider/config.ts and mapped to Tailwind in
tailwind.config.js — so they adapt to the color scheme automatically. This
template ships a starter set of components (box, hstack, vstack, text, heading,
button). Add more with the gluestack CLI (vendors source into
src/components/ui/):
npx gluestack-ui@2 add input select modal # interactive; needs a TTY + networkSee AGENTS.md for the full UI conventions (tokens, adding
components, the provider). Static checks (typecheck/lint/test) don't
exercise Metro bundling or on-device rendering — after changing styling or the
NativeWind/Tailwind config, run npx expo start once and load the app to
confirm classes actually render on device.
| Script | Purpose |
|---|---|
npm start / ios / android / web |
Run the dev server |
npm run typecheck |
TypeScript, no emit |
npm run lint |
ESLint via expo lint |
npm run format / format:check |
Prettier write / verify |
npm test / test:ci |
Jest watch mode / CI mode with coverage |
npm run prebuild |
Generate native projects (usually unnecessary — EAS does this) |
Three workflows in .github/workflows/:
- CI — lint, format check, typecheck, tests on every PR and push to
main. - EAS Update — every push to
mainships an over-the-air JS update to installed builds (no store review needed). - EAS Build — native builds: run manually from the Actions tab (choose platform/profile), or push a
v*tag for a production build; optionally submits to the app stores.
Release model: JS-only changes ride OTA updates from main; native changes (new native modules, SDK upgrades, app.json changes) need a new store build via tag or manual dispatch. runtimeVersion uses the appVersion policy so OTA updates only reach compatible binaries.
npm i -g eas-cli && eas logineas init— links the project and writesextra.eas.projectIdintoapp.jsoneas update:configure— enables OTA updates (adds theupdates.urlfield toapp.json)- Commit and push the
app.jsonchanges from steps 2–3 — the EAS Build and EAS Update GitHub Actions workflows readextra.eas.projectIdfrom the committedapp.json, so builds/updates triggered from CI will fail (or target the wrong project) until this is pushed. - Create an Expo access token and add it as the
EXPO_TOKENrepository secret (Settings → Secrets and variables → Actions) - For store submission: configure credentials with
eas credentialsand thesubmitprofile ineas.json
Copy .env.example → .env for local dev. EXPO_PUBLIC_* values are inlined into the client bundle at build time; for build-time secrets use EAS environment variables.
- Keep this repo marked as a Template repository (Settings → General → check "Template repository").
- Dependabot updates actions and JS deps weekly; Expo-coupled packages are excluded — upgrade SDKs with
npx expo install expo@latest --fixfollowed bynpx expo-doctor. - Recommended branch protection on
main: require the CI check and one review.
See CONTRIBUTING.md. Security reports: SECURITY.md.