Enterprise Architect. Hands-on Developer.
CardBundle wasn’t born in a boardroom. It was built by someone who bridges the gap between enterprise architecture and hands-on code — someone who draws system diagrams and then implements them.
With deep expertise across the full technology spectrum, I brought a disciplined, architecture-first approach to what started as a personal itch: too many plastic loyalty cards, not enough pockets.
Loyalty cards deserve better
We all carry them — supermarket cards, coffee shop punch cards, gym memberships. They clutter wallets, get lost, and their barcodes fade. Existing solutions were bloated, privacy-invasive, or locked into specific ecosystems.
I wanted something minimal and universal: scan your card, store it, pull up the barcode at checkout. That’s it. No accounts with retailers, no data harvesting — just your cards, on your phone, always ready.
The build in numbers
From first commit to the App Store
Initial Architecture & Scaffolding
Started with a clear separation: a Sails.js backend serving a RESTful API backed by PostgreSQL, and an Expo-managed React Native frontend. Applied TOGAF principles — defined bounded contexts early (auth, cards, users, subscriptions) and established clean API contracts before writing a line of UI code.
Auth, API & Data Layer
Built JWT-based authentication with Passport.js — access tokens (10min) and refresh tokens (15 days). Implemented a smart token refresh queue on the mobile client that prevents race conditions when multiple API calls fail simultaneously. Designed the LoyaltyCard model with Waterline ORM, supporting image uploads via Multer with automatic cleanup of old files on update/delete.
Scanning, Cards & State Management
Integrated expo-barcode-scanner with custom overlay UI and auto-format detection (CODE128, EAN-13, EAN-8, UPC-A). Built the card management flow with Redux Toolkit — async thunks for CRUD operations, Redux-Persist for offline access, and a card preview with luminance-aware text colors. Added card image flip animations for front/back views.
Home Screen Widgets (iOS & Android)
This was the most challenging phase. Built iOS WidgetKit extensions using Swift with App Groups for data sharing, and Android widgets using react-native-android-widget. Created Redux middleware that intercepts card CRUD actions and automatically syncs data to both widget systems. Added deep linking (cardbundle://) so tapping a widget card opens the app directly to that card.
17-Language Internationalization
Implemented i18n-js with expo-localization for automatic device locale detection. Full translation coverage across English, French, Spanish, Portuguese, German, Italian, Polish, Russian, Ukrainian, Korean, Japanese, Turkish, Hindi, Bengali, Marathi, Telugu, Tamil, and Gujarati. Every screen, button, error message, and placeholder — localized.
Deployment, Monitoring & Store Compliance
Deployed the backend to production, integrated Firebase Analytics and Crashlytics for real-time monitoring. Navigated Apple’s review process — encryption declarations, camera permission descriptions, App Transport Security compliance. Resolved Android Play Store 16KB page size warnings. Configured SMTP via Zoho for transactional emails (password resets, verification).
System design overview
Applying enterprise architecture patterns to a mobile-first product. Clean separation of concerns, stateless API design, and event-driven widget synchronization.
Tools of the trade
Frontend
React Native 0.74 with Expo 51. TypeScript for type safety. TailwindCSS (twrnc) for styling with dark mode support.
React Native + ExpoBackend
Sails.js v1.5 — a convention-over-configuration Node.js MVC framework. Waterline ORM for database abstraction.
Sails.js + PostgreSQLAuthentication
Passport.js with JWT strategy. Dual-token system with transparent refresh. bcrypt password hashing.
JWT + Passport.jsState Management
Redux Toolkit with 4 slices (auth, cards, user, language). Redux-Persist to AsyncStorage for offline support.
Redux ToolkitNative Widgets
iOS WidgetKit via @bittingz/expo-widgets. Android widgets via react-native-android-widget. Redux middleware for sync.
WidgetKit + Android WidgetsObservability
Firebase Analytics for user behavior tracking. Crashlytics for real-time crash monitoring. Custom event logging.
Firebase AnalyticsWhat made it hard
- Token refresh race conditions Multiple API calls failing simultaneously would trigger parallel refresh requests. Solved with a single-queue mechanism — the first 401 triggers a refresh, subsequent failures wait for the same promise, then all retry with the new token.
- Dual-platform native widgets iOS WidgetKit (Swift) and Android widgets (Java/Kotlin) have fundamentally different data-sharing models. Bridged them through Redux middleware that intercepts card state changes and writes to App Groups (iOS) and SharedPreferences (Android) simultaneously.
- Barcode format detection Different loyalty cards use different barcode formats. Built a dynamic detection system that analyzes the scanned number pattern and selects the correct format (CODE128, EAN-13, EAN-8, UPC-A) for accurate rendering.
- Apple review compliance Navigated encryption declarations (HTTPS/TLS), camera permission justifications, and App Transport Security requirements. Each rejection was a lesson in reading Apple’s guidelines more carefully.
- Email delivery in production Went through multiple SMTP port configurations (465, 587) and TLS settings with Zoho before landing on a stable email delivery pipeline for password resets and verification.
What I took away
CardBundle started as a weekend project and evolved into a production application serving users across both major mobile platforms. Building it solo — from database schema design to App Store submission — reinforced something I’ve always believed: the best architects are the ones who still write code.
My enterprise architecture background (TOGAF, AWS) shaped how I approached system boundaries, API contracts, and separation of concerns. My PMP training kept scope creep in check. But it was the hands-on development — debugging a WidgetKit extension at midnight, wrestling with Expo prebuild configs, writing the 17th translation file — that made this product real.
Every loyalty card scanned, every barcode displayed at a checkout counter, every widget glanced at on a home screen — that’s architecture in action.
Leave a Reply