KA26 Mobile App — Features & Architecture
Overview
React Native (Expo SDK 54) mobile application that mirrors the KA26 web app. Uses Expo Router for file-based navigation, consumes the same production API (https://ka26.shop), and shares JWT authentication with the web platform.
Architecture
| Layer | Technology |
|---|---|
| Framework | React Native + Expo SDK 54 |
| Navigation | Expo Router (file-based) |
| Auth | JWT stored in SecureStore (ka26_consumer_token) |
| API Client | Custom ApiClient class (src/lib/api.ts) |
| State | React hooks + AsyncStorage for persistence |
| Translations | 6-language i18n system (src/contexts/LanguageContext.tsx) |
| Testing | Jest + React Native Testing Library (unit/integration), Vitest (code integrity) |
Directory Structure
mobile/
├── app/ # Screens (Expo Router file-based routing)
│ ├── (tabs)/ # Bottom tab screens
│ │ ├── shop.tsx # Shop: stores + ads marketplace
│ │ ├── requests.tsx # Community requests feed
│ │ ├── reels.tsx # Video reels feed + upload
│ │ ├── eats.tsx # Restaurant ordering
│ │ └── profile.tsx # User profile + account
│ ├── restaurant/[id].tsx # Restaurant detail + checkout
│ ├── store/[id].tsx # Store detail page
│ ├── product/[id].tsx # Product detail page
│ ├── order/[id].tsx # Order tracking
│ ├── auth.tsx # Login / signup
│ ├── settings.tsx # App settings
│ ├── edit-profile.tsx # Edit profile + services
│ ├── language.tsx # Language selection
│ ├── feedback.tsx # Bug/feature feedback form
│ └── ... (15 more screens)
├── src/
│ ├── contexts/ # React contexts
│ │ ├── AuthContext.tsx # JWT auth + user state
│ │ └── LanguageContext.tsx # i18n translations
│ ├── lib/ # Utilities
│ │ ├── api.ts # API client with auth headers
│ │ ├── constants.ts # Colors, API URL
│ │ └── notifications.ts # Push notification setup
│ └── locales/ # Translation JSON files (6 languages)
├── __tests__/ # Jest tests (unit + integration)
└── tests/ # Vitest code integrity tests
Modules & Features
1. Shop (shop.tsx)
- Stores Tab: Horizontal card layout with store image (110x110), name, category badge, open/closed status, address, product count, delivery info, smart signals
- Ads Tab: 2-column clean card grid with shadow, tappable cards, image (4:3 aspect ratio), seller avatar, category badge, FOR RENT overlay, image count badge
- Filters — Two rows matching web:
- Row 1: "All Ads" / "My Ads" toggle (authenticated users only)
- Row 2: Category chips (All, Electronics, Household, Books, Vehicles, Property Buy, Property Rent) — only shown in "All Ads" mode
- My Ads: Fetches user's own listings from
/api/ads - Search: Global search across products and stores
- Branding: Logo — KA (red) 26 (black) + "Shop"
2. Eats — ARCHIVED 2026-04-17
Eats vertical removed from mobile launch scope. Source code preserved in
src/_archived/eats-mobile/eats.tsx. To restore: copy back tomobile/app/(tabs)/eats.tsx, re-add the<Tabs.Screen name="eats">entry in_layout.tsx, and bump tab count test from 4 to 5.
2-original. Eats (eats.tsx + restaurant/[id].tsx) — pre-archive description
- Restaurant Listing: Cards with image, cuisine badge, open/closed status, delivery fee, ratings, hours, "orders today" count
- Location Management: City picker (Gadag, Hubli, Dharwad, Belgaum, Bangalore) with AsyncStorage persistence, coordinates passed to intelligence feed API
- Cuisine Filters: Chip-based filtering (All, South Indian, North Indian, Chinese, Fast Food, Biryani, Sweets, Bakery)
- Restaurant Detail: Full menu with sections, popular items (deduplicated — shown only in "🔥 Popular" section, not repeated in category), category filter tabs below restaurant info that scroll to sections on tap
- Checkout: Customer info, delivery address (with saved addresses from API), special instructions
- Payment: Cash on Delivery + UPI payment (PhonePe, GPay, Paytm deep links, 5-minute timer, UTR confirmation)
- Keyboard handling: All modals (checkout, UPI) wrapped with
KeyboardAvoidingView+keyboardShouldPersistTapsso inputs aren't hidden by keyboard - Order Success: Order number display, 60-second edit window for address/instructions changes, cancel option
- Location Coordinates: Passed with orders for delivery radius validation
3. Reels (reels.tsx + reels-profile.tsx)
- Feed: Vertical swipe video feed with play/pause, likes, comments, share
- Referral Gate: Upload requires 2+ referrals; shows progress bar and share button for referral code
- Comments: Real-time comment feed with post/delete
- Report System: Flag button with 5 predefined reasons + details field
- Creator Profile: Grid of user's reels, follower stats
- Reel Management: Long-press menu on own reels for hide/unhide and delete with confirmation
Post Reel Flow (Instagram-Style) — LOCKED UI ⚠️
DO NOT modify the post reel UI layout, step flow, or component structure. This design was user-approved on 2026-04-08 and is protected by 25+ code integrity tests.
Flow: select-video → details ("New reel") → post (with optional edit-video via "Trim video" row)
Step 1 — Select Video (full-screen playback):
- Video plays instantly full-screen after selection (expo-av
<Video>, NOT VideoThumbnails) - Close (✕) button top-left, duration badge top-right
- Drafts banner overlaid at top when drafts exist (Resume / Delete per draft)
- Bottom bar: "Change" (re-pick) | "Next →" (pink CTA)
Step 2 — New Reel (Instagram-style details page):
- Header: ← arrow + "New reel" title
- Centered video thumbnail (55% screen width, 9:16 aspect ratio, rounded 16px) with "Edit cover" overlay
- Borderless caption input (500 char limit, character counter appears after typing)
- Horizontal chips row:
# Hashtagstoggle + emoji quick-picks (🔥 ❤️ 😍 🎉 👀 💯) - Hashtag suggestions panel (expandable): #KA26, #Gadag, #LocalBusiness, #FoodReview, etc.
- Clean action rows (icon + label + chevron):
- Tag products → navigates to tag-type step (store products or restaurant menu items, max 5 tags)
- Add location → Alert picker with city list (Gadag, Hubli, Dharwad, Belgaum, Bangalore, Haveri) + quick-pick chips inline
- Visibility → toggle Public (globe icon) / Followers only (people icon) with badge
- Trim video → navigates to edit-video step (shows current duration)
- Tagged items shown as horizontal scrollable chips with remove (✕) button
- Earnings info banner (green): "Earn 1% on every order from your tagged products within 24h of viewing" (shown when items tagged)
- Bottom bar: "Save Draft" (gray) | "Post Reel" (pink CTA) — upload progress shown inline
Draft System:
- Saves to AsyncStorage key
ka26_reel_drafts(max 5 drafts) - Draft includes: videoUri, caption, taggedItems, coverFrameUri, trimStartMs/EndMs, videoDurationMs, visibility, location, savedAt
- Resume draft restores all state; delete draft with confirmation
- Discard dialog offers "Save Draft" option
Trim Video (edit-video step):
- Video info card: filename, duration, size estimate
- Start/End time controls with ±1s increment/decrement buttons
- Duration display, reset button, tip about server-side thumbnails
- Back navigates to details (not select-video)
Crash Prevention Architecture:
VideoThumbnails.getThumbnailAsync()(native FFmpeg) is NEVER called in the post flow- Background feed thumbnail generation pauses when
postStep !== null - Video playback uses expo-av
<Video>component which is safe (different from VideoThumbnails) - All native decoder-intensive operations have 200ms+ delays between calls
Creator Economy (Redirect Tracking):
- "Shop Now" floating pill on reels with tagged items (pulsing animation)
- Tap tracks redirect via
POST /api/reels/{id}/redirectwith fingerprint + productId/menuItemId - Orders within 24hr attribution window earn creator 1% commission
- Earnings: pending → confirmed (on delivery) → credited to wallet
- Cancellations reverse earnings atomically
- Self-purchase prevention built in
4. Requests (requests.tsx)
- Feed: Community request cards with title, description, category, location
- Filters: All / My Requests / I Helped tabs
- Sorting: Newest / Nearest with location awareness
- Support Flow: "I Can Help" compact pill button (not full-width), chat threads with message limits
- Post Request: Title, details, category, location, phone (optional)
- Provider Notifications: Auto-notifies matching service providers
5. Profile (profile.tsx)
- Authenticated View: User photo, name, alias, stats (orders, stores, requests)
- Account Activity: Quick links to Orders, My Requests, Subscribed Stores, Health Records
- Guest View: Sign-in prompt with feature overview
- Navigation: Settings, Edit Profile, My QR, Contributions, Invite, My Ads
6. Edit Profile (edit-profile.tsx)
- Personal Info: Name, phone, bio with character limit
- Photo Upload: Image picker with crop, upload to API
- Service Categories: 32 categories organized in 6 groups (Transport, Home & Building, Appliance Repair, Agriculture, Personal Services, Health & General), multi-select picker modal
- Service Area: Text input for service coverage
- Email Verification: 6-digit code flow
- Password Change: Current + new password form
7. Language System (language.tsx + LanguageContext.tsx)
- 6 Languages: English, Kannada, Hindi, Telugu, Tamil, Sanskrit
- Full Translation: 330+ keys covering all UI text
- Real-time Switching: Language changes instantly update all screens
- Persistent: Saved to AsyncStorage, restored on app launch
- Template Parameters: Support for dynamic values (e.g.,
{km},{count}) - Fallback Chain: Selected language -> English -> key itself
8. Settings (settings.tsx)
- Edit Profile, My QR Code, Language, Feedback, Notifications toggle
- Seller dashboard link, logout
9. Authentication (auth.tsx + AuthContext.tsx)
- Login / Signup with email + password
- JWT token stored in SecureStore
- Auto-refresh on app launch
- Guest mode for browsing
10. Orders (orders.tsx + order/[id].tsx)
- Order history list with status badges
- Order detail with items, totals, status timeline
- Real-time status tracking
11. Other Screens
- My QR (
my-qr.tsx): Personal QR code for doctor prescriptions - Feedback (
feedback.tsx): Bug report / feature request / general feedback with screenshot attachment - Health Records (
health-records.tsx): Prescription history linked via QR - Subscribed Stores (
subscribed-stores.tsx): Managed store subscriptions - My Ads (
my-ads.tsx): Consumer's resale/rental listings - Invite (
invite.tsx): Referral code sharing - Contributions (
contributions.tsx): Community contribution history
Testing — 544 tests across 15 suites
Jest + React Native Testing Library (103 tests, 8 suites)
- Unit tests: API client, helper functions
- Integration tests: Auth flow (login, register, token refresh), eats ordering (COD + UPI), store ordering (COD + UPI, subscriptions), reels (referral gate, likes, comments, report, management), post-reel flow (video upload, cover frame, tags, drafts, redirects), profile (contributions, health records, requests, feedback, QR)
- Run:
npx jest --forceExit --detectOpenHandles
Vitest — Code Integrity + API (441 tests, 7 suites)
- screen-completeness.test.ts (84 tests): All 28 screens exist, default exports, tab nav, feature presence per screen
- ui-consistency.test.ts (61 tests): CTA color uniformity (blue #2563EB), SafeAreaView, filter chip visibility, ad card layout
- mobile-code-integrity.test.ts (164 tests): API endpoints, auth handling, routing, UPI flow, settings, features, Post Reel UI Lock (20 tests) — prevents any modification to the approved Instagram-style post reel layout
- api-integration.test.ts (31 tests): Live API tests against production
- api-response-shapes.test.ts (32 tests): Response shape validation for all endpoints
- api-endpoints-auth.test.ts (35 tests): Auth-required endpoints return 401
- post-deploy-smoke.test.ts (34 tests): Post-deployment health + data verification
- Run:
npx vitest run
CI/CD Integration
- Mobile tests run in GitHub Actions before every deployment
- Both web (1334 tests) and mobile (482 tests) must pass before build proceeds
- Pipeline:
test (web) + test-mobile → build → staging → smoke test → production
Build
Local APK (no EAS credits needed)
cd mobile
npx expo prebuild --platform android --clean
cd android && ./gradlew assembleRelease
# Output: android/app/build/outputs/apk/release/app-release.apk
Development
npx expo start # Start dev server
npx expo run:android # Run on connected device