
Synthesis: React Native Design System App
2025
Introduction
Synthesis is a React Native application built to streamline the creation, management, and customization of design systems across multiple screens and elements. The project emphasizes seamless data handling, responsive UI updates, and efficient user interaction. The core purpose of this app is to simplify and accelerate a designer's process of creating a design system for any project. Throughout development, I tackled advanced state management patterns, asynchronous data flows, and mobile-specific challenges, resulting in a robust app tailored for creative and technical users.
Overview
The app provides a platform for managing design system elements such as fonts, gradients, components and typography. The goal was to maintain real-time updates, support scalable nested data structures, and ensure smooth navigation across multiple screens while handling asynchronous data from Firestore.
Frameworks
- React Native
- Expo
APIs
- Firestore
- REST API
- AsyncStorage
Database
Firestore (NoSQL, schema-less)
Dependencies
- @sendgrid/mail - for sending emails through SendGrid
- bcrypt - hashing passwords for secure storage
- cors - handling cross-origin requests
- dotenv - managing environment variables
- express - backend server framework
- firebase - client-side Firebase SDK
- firebase-admin - server-side Firebase admin operations
- fs-extra - enhanced file system operations
- jwt-decode - decoding JWT tokens
- xss - sanitizing inputs to prevent XSS attacks
- express-session - session management
- helmet - security headers for Express
- jsonwebtoken - user authentication and token management
- nodemon - automatic server reload during development
- passport - authentication middleware
- node-fetch - server-side fetch requests
Features
- Multi-screen navigation with nested stacks
- Optimistic state updates for immediate UI feedback
- CRUD operations for design system elements
- Toggle selection for elements
- Centralized state via React Context
- Async data fetching with Firestore
- Dynamic rendering of nested design system elements
- Error handling for undefined and asynchronous states
- Convert/Export Json design system data to the users email
Deployment
- EAS (Expo Application Services) - building and submitting the app to app stores
- Docker - containerizing backend services for consistent deployment
- Google Cloud Server - hosting backend services and Firestore database
- Google Cloud Console - managing server infrastructure and app deployment
- Google Play Store - publishing the Android version of the app
- Github
Version Control
Git
Challenges
- Understanding useState Across Screens -
Navigating multiple screens revealed the ephemeral nature of local useState. After deleting a design system, screens did not automatically refresh their local state, resulting in outdated UI data. I learned that screens maintain only their initial state unless explicitly refreshed or re-fetched from context or backend.
- Optimistic State Updates vs. Refetching -
Implementing “optimistic updates” allowed the UI to immediately reflect deletions without waiting for backend confirmation. This improved responsiveness but highlighted the challenge of maintaining a single source of truth across screens and context.
- React Context Integration -
Using React Context for centralized state management was initially confusing because it replaced traditional prop passing. While powerful for shared state, it required explicit syncing with local screen states to avoid stale data.
- State Syncing & Data Shape Complexity -
Managing multiple layers of state (context vs local) and nested data structures introduced subtle bugs. Many of my design system data were array structures that I built myself and were present on the REST API endpoints so they could be fetched and accessed. However, I did not add enough unique IDs or make the structures scalable enough, which caused problems when displaying them as the app grew. Elements with varying properties sometimes caused undefined errors during rendering. Handling asynchronous fetches required careful management of loading states and conditional checks.
- Firestore Data Structure & Async Challenges -
Firestore’s behavior with nested arrays and object keys created additional complexity. Keys are automatically sorted, and deep equality queries are unsupported, forcing me to write conversion and flattening logic to preserve the intended JSON structure. Async fetching led to initial undefined states, requiring safeguards before running array operations like .filter().
- Toggle Selection Logic -
Developing the toggle selection function for design system elements was particularly difficult, as it required managing nested states and ensuring consistent updates across context and local state.
- Scalability & Componentization -
Rendering complex design system elements demanded more reusable components. Implementing a renderItem function with type-based switching simplified the UI and made the app more scalable for future expansions.
- ADB Issues on MacOS -
After updating MacOS and Android Studio, ADB stopped recognizing emulators. Despite extensive troubleshooting, I switched to testing on physical devices. This highlighted platform-specific development challenges when using React Native and Expo on Apple Silicon machines.
Personal Value
- Problem Solving Abilities -
Overcoming React Native state issues, asynchronous data challenges, and Firestore quirks strengthened my problem-solving skills. I learned to break down complex bugs, apply systematic debugging, and implement workarounds while maintaining app stability.
- Collaboration & Communication -
Although primarily working solo, understanding React Context improved my ability to design systems that support team development. Clear and structured state management facilitates collaborative coding and reduces potential conflicts.
- Continuous Learning -
Developing Synthesis reinforced the importance of continuous learning, from advanced React patterns to mobile-specific quirks like ADB on M2 Macs. I became more adept at anticipating pitfalls and designing resilient solutions.
Conclusion
Synthesis represents a deep dive into complex React Native app development, showcasing the integration of context-based state management, asynchronous Firestore interactions, and scalable UI design. The challenges encountered—from state syncing and optimistic updates to nested data handling and platform-specific issues—provided invaluable experience in building robust, user-friendly mobile applications.
Through persistent problem-solving, adaptation, and continuous learning, I strengthened both my technical and strategic development skills. This project demonstrates my capacity to tackle advanced mobile app challenges while maintaining clean, maintainable, and scalable code.
