An Expo / React Native app for Urmil Jewellers' Ramnagar branch(es) staff: visitor logging, follow-ups, sales tracking, discount approvals, and staff management, role-gated per account type. Backed by InstantDB with a companion Cloudflare Worker (uj-ramnagar-auth-bridge) handling mobile-number + password login.
Each staff profile has a role that determines which part of the app they land in after login (see app/(app)/):
| Role | Screens |
|---|---|
owner |
branches, staff (all), visitors, dashboard |
branch_manager |
staff (own branch), visitors, follow-ups, dashboard |
receptionist |
add visitor, visitors, follow-ups |
salesperson |
active visits, visitors, discount requests |
accountant |
discount request approvals, history |
Routing is handled by app/index.tsx + the (app)/<role>/ route groups; app/(auth)/ covers login and the "no access" screen for deactivated/unrecognized accounts.
- Client: Expo Router (file-based routing), NativeWind/Tailwind for styling,
@instantdb/react-nativefor data — real-time queries, no separate REST layer for reads/writes that InstantDB permissions already allow. - Auth: staff sign in with mobile number + password. Since InstantDB's client SDK only supports magic-code/email auth, sign-in goes through the auth-bridge Worker, which verifies the password and returns an InstantDB sign-in token that the client exchanges for a session.
- Privileged writes: creating/editing staff, changing another user's data, and sending push notifications also go through the auth-bridge Worker (via
EXPO_PUBLIC_AUTH_BRIDGE_URL), since those actions need server-side authorization beyond what InstantDB permission rules alone can express. - Schema/permissions:
instant.schema.tsandinstant.perms.tsat the project root define InstantDB's data model and access rules. Key entities:profiles(staff),branches,customers,visitorLogs,salesRemarks,discountRequests,offers,salespersonAvailability,salespersonPerformance,devices(push tokens).
bun install
cp .env.example .envFill in .env:
EXPO_PUBLIC_INSTANT_APP_ID=<InstantDB app id>
INSTANT_APP_ADMIN_TOKEN=<InstantDB admin token> # used by local scripts, not shipped in the app
EXPO_PUBLIC_AUTH_BRIDGE_URL=http://localhost:8787
EXPO_PUBLIC_AUTH_BRIDGE_URL must point at a running instance of uj-ramnagar-auth-bridge (npm run dev there, from its own README). The right local URL depends on where the app runs:
- iOS simulator / web:
http://localhost:8787 - Android emulator:
http://10.0.2.2:8787 - Physical device: your machine's LAN IP, e.g.
http://192.168.x.x:8787
bunx expo start # dev server; press i/a/w or scan the QR code
bun run android
bun run ios
bun run web
bun run lintbunx instant-cli push schema --yes # push instant.schema.ts changes
bunx instant-cli push perms --yes # push instant.perms.ts changes
bunx instant-cli pull --yes # pull remote schema/perms into local filesAGENTS.mddocuments InstantDB usage conventions for AI coding agents working in this repo — not user-facing app documentation.- Push notifications use Expo's push service; devices register their push token with the auth-bridge Worker (
PUT /me/push-token) on sign-in/foreground.