Production-ready starter
Alright β hereβs a complete, production-ready starter repo structure you can literally copy-paste and run for:
- Expo + Bun
- NativeWind (UI)
- Zustand (state)
- TanStack Query (API)
- JWT Auth (secure + refresh-ready)
- Scalable architecture
π 1. Project Setup (Run First)
Section titled βπ 1. Project Setup (Run First)βbun create expo myApp --template blank-typescriptcd myApp
bun add nativewind zustand axios @tanstack/react-querybun add react-native-safe-area-context react-native-screensbun add expo-secure-storebun add -d tailwindcss
bunx tailwindcss initπ 2. Final Folder Structure
Section titled βπ 2. Final Folder StructureβmyApp/βββ app/β βββ (auth)/β β βββ login.tsxβ βββ (tabs)/β β βββ home.tsxβ βββ _layout.tsxββββ src/β βββ components/β β βββ Button.tsxββ βββ features/β β βββ auth/β β βββ api.tsβ β βββ store.tsβ β βββ hooks.tsβ β βββ persist.tsββ βββ services/β β βββ api/β β β βββ client.tsβ β β βββ refresh.tsβ β βββ storage/β β β βββ secure.tsβ ββ βββ lib/β β βββ react-query.tsββ βββ utils/β β βββ logger.tsββββ tailwind.config.jsβββ babel.config.jsβββ tsconfig.jsonβοΈ 3. Core Config Files
Section titled ββοΈ 3. Core Config Filesββ
tailwind.config.js
Section titled ββ
tailwind.config.jsβmodule.exports = { content: ["./app/**/*.{ts,tsx}", "./src/**/*.{ts,tsx}"], theme: { extend: {} }, plugins: [],};β
babel.config.js
Section titled ββ
babel.config.jsβmodule.exports = function (api) { api.cache(true); return { presets: ["babel-preset-expo"], plugins: ["nativewind/babel"], };};β
tsconfig.json (important)
Section titled ββ
tsconfig.json (important)β{ "compilerOptions": { "strict": true, "baseUrl": ".", "paths": { "@/*": ["src/*"] } }}β‘ 4. React Query Setup
Section titled ββ‘ 4. React Query Setupβsrc/lib/react-query.ts
Section titled βsrc/lib/react-query.tsβimport { QueryClient } from "@tanstack/react-query";
export const queryClient = new QueryClient({ defaultOptions: { queries: { staleTime: 1000 * 60 * 5, retry: 2, }, },});π 5. API Client + Auth Injection
Section titled βπ 5. API Client + Auth Injectionβsrc/services/api/client.ts
Section titled βsrc/services/api/client.tsβimport axios from "axios";import { useAuthStore } from "@/features/auth/store";
export const apiClient = axios.create({ baseURL: "https://api.example.com",});
apiClient.interceptors.request.use((config) => { const token = useAuthStore.getState().accessToken; if (token) config.headers.Authorization = `Bearer ${token}`; return config;});π 6. Auth Store (Zustand)
Section titled βπ 6. Auth Store (Zustand)βsrc/features/auth/store.ts
Section titled βsrc/features/auth/store.tsβimport { create } from "zustand";
type AuthState = { accessToken: string | null; setTokens: (token: string) => void; logout: () => void;};
export const useAuthStore = create<AuthState>((set) => ({ accessToken: null, setTokens: (token) => set({ accessToken: token }), logout: () => set({ accessToken: null }),}));π 7. Secure Storage
Section titled βπ 7. Secure Storageβsrc/services/storage/secure.ts
Section titled βsrc/services/storage/secure.tsβimport * as SecureStore from "expo-secure-store";
export const storage = { set: (k: string, v: string) => SecureStore.setItemAsync(k, v), get: (k: string) => SecureStore.getItemAsync(k), remove: (k: string) => SecureStore.deleteItemAsync(k),};π 8. Auth API + Hook
Section titled βπ 8. Auth API + Hookβsrc/features/auth/api.ts
Section titled βsrc/features/auth/api.tsβimport { apiClient } from "@/services/api/client";
export const login = async (email: string, password: string) => { const { data } = await apiClient.post("/auth/login", { email, password, }); return data;};src/features/auth/hooks.ts
Section titled βsrc/features/auth/hooks.tsβimport { useMutation } from "@tanstack/react-query";import { login } from "./api";import { useAuthStore } from "./store";import { storage } from "@/services/storage/secure";
export const useLogin = () => { const setToken = useAuthStore((s) => s.setTokens);
return useMutation({ mutationFn: login, onSuccess: async (data) => { setToken(data.accessToken); await storage.set("token", data.accessToken); }, });};π§± 9. Root Layout (Providers)
Section titled βπ§± 9. Root Layout (Providers)βapp/_layout.tsx
Section titled βapp/_layout.tsxβimport { Stack } from "expo-router";import { QueryClientProvider } from "@tanstack/react-query";import { queryClient } from "@/lib/react-query";
export default function Layout() { return ( <QueryClientProvider client={queryClient}> <Stack /> </QueryClientProvider> );}π 10. Login Screen
Section titled βπ 10. Login Screenβapp/(auth)/login.tsx
Section titled βapp/(auth)/login.tsxβimport { View, TextInput, Button } from "react-native";import { useState } from "react";import { useLogin } from "@/features/auth/hooks";
export default function Login() { const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const { mutate } = useLogin();
return ( <View className="flex-1 justify-center p-4"> <TextInput placeholder="Email" onChangeText={setEmail} className="border p-2 mb-2" /> <TextInput placeholder="Password" secureTextEntry onChangeText={setPassword} className="border p-2 mb-2" /> <Button title="Login" onPress={() => mutate({ email, password })} /> </View> );}π 11. Home Screen
Section titled βπ 11. Home Screenβapp/(tabs)/home.tsx
Section titled βapp/(tabs)/home.tsxβimport { View, Text } from "react-native";import { useAuthStore } from "@/features/auth/store";
export default function Home() { const token = useAuthStore((s) => s.accessToken);
return ( <View className="flex-1 items-center justify-center"> <Text>Logged in β
</Text> <Text>{token}</Text> </View> );}π 12. Run the App
Section titled βπ 12. Run the Appβbun installbunx expo startπ₯ What You Get (Out of the Box)
Section titled βπ₯ What You Get (Out of the Box)ββ Clean scalable architecture β Auth system (JWT ready) β API layer (Axios + interceptors) β State management (Zustand) β Server state (React Query) β Styling (NativeWind) β Secure storage
β‘ Next Steps (Upgrade to Enterprise)
Section titled ββ‘ Next Steps (Upgrade to Enterprise)βIf you want to evolve this into a real production system, next upgrades would be:
- π Refresh token system (I showed earlier)
- π¦ Offline cache persistence
- π§ Global error boundary
- π Sentry logging integration
- π Biometric auth (FaceID/Fingerprint)
- π CI/CD with EAS
If you want, I can convert this into: π a GitHub-ready repo (with README, scripts, env, CI/CD) π or a WhatsApp-style / fintech-grade app starter (aligned with your SaaS idea WhatsProp)