Modern Expo starter scaffolded for full-stack, multi-platform apps. It ships with Expo Router, typed tooling, shadcn-inspired primitives, Tailwind + NativeWind styling, Supabase utilities, and bilingual (English/Chinese) translations out of the box.
- Expo SDK 54 with Expo Router 6
- React Native 0.81 & React 19
- TypeScript (strict), ESLint, Prettier, Husky
- NativeWind + Tailwind CSS 3,
tailwindcss-animate, theming via CSS variables - shadcn/ui primitives from
@rn-primitives - i18n with
i18next,react-i18next,expo-localization - Supabase client wrapper (AsyncStorage session persistence)
- Lucide icon set for React Native
- Node.js 18+ (Node 20 LTS recommended)
- npm 9+ (ships with Node). You can substitute
pnpmoryarn, but npm scripts are provided. - Expo tooling:
npm install -g expo-cli(optional but handy) - Android Studio / Xcode for native emulators, or Expo Go on devices
npm installCopy .env.example (if present) or create .env and add your Supabase credentials:
EXPO_PUBLIC_SUPABASE_URL=your-project-url
EXPO_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
These are required at runtime; the Supabase client throws early if they are missing.
npm start # Expo CLI (press i / a / w for iOS / Android / web)
npm run ios # Shortcut: expo start --ios
npm run android # Shortcut: expo start --android
npm run web # Shortcut: expo start --webMetro is configured with inlineRem: 16; use npm start -- --clear if you change Metro settings and need to reset caches.
npm run typecheck– TypeScript project check (tsc --noEmit)npm run lint– ESLint + Prettier consistency checknpm run format– Apply ESLint fixes and Prettier formattingnpm run align–expo install --fixto reconcile native dependenciesnpm run prebuild– Prepare native projectsnpm run shadcn– Invoke@react-native-reusables/clifor additional UI componentsnpm run taze– Upgrade dependencies (skips Tailwind to stay on v3 for NativeWind compatibility)
app/– Expo Router routes (_layout.tsx,index.tsx, etc.), already wired to the theme provider andPortalHost.components/– Shared UI components, including shadcn-inspired primitives incomponents/ui/.components/theme.tsx– Syncs status bar and system background; toggles thedarkclass on web.lib/utils.ts–cnhelper combiningclsx+tailwind-merge.locales/– JSON translation catalogs (en,zh) and i18n initializer.global.css– Tailwind layers plus CSS variable theme tokens (light/dark).tailwind.config.js– Tailwind/NativeWind configuration (colors, radius, animations).utils/supabase.ts– Supabase client configured with AsyncStorage persistence.
- Language detection reads system locale via
expo-localization, normalizes toenorzh. - Add new languages by creating
locales/<lang>.jsonand extendingresourcesinlocales/index.ts. - Use the
useTranslationhook fromreact-i18next(const { t } = useTranslation()).
- Tailwind utilities are available via NativeWind class names (
classNameon React Native views). - Theme tokens pull from CSS variables; adjust hues in
global.css. - shadcn components expect
cnfrom@/lib/utils; keep that helper updated if you extend merging behavior. - Portal-based components (dialogs, hover cards, etc.) rely on
<PortalHost />inapp/_layout.tsx.
- Requires
EXPO_PUBLIC_SUPABASE_URL/EXPO_PUBLIC_SUPABASE_ANON_KEY. - Auth sessions persist in
AsyncStorageand auto-refresh by default. - Extend the client or wrap queries inside your state/store as needed.
- Metro cannot resolve
react-native-css-interop→ ensurenpm installran after pulling. The dependency is pinned at the project root. - Tailwind peer warnings → Template intentionally uses Tailwind 3.x to match NativeWind’s current interop layer.
- Missing environment variables → Supabase client throws during import; double-check your
.env. - shadcn diagnostics → Confirm
global.css,tailwind.config.js, andapp/_layout.tsxmatch the docs (already configured here).
- Keep translations mirrored between
en.jsonandzh.json. - When adding new UI primitives via
npm run shadcn, follow up with type validations (npm run typecheck). - Consider wiring in React Query, Sentry, expo-notifications, etc., depending on product needs.
Happy building!