-
Notifications
You must be signed in to change notification settings - Fork 0
Architecture
App Type: Mobile app
Description
This will be a React Native app developed with Expo. It uses Firebase for authentication for user accounts, notifications, one-time phone passcodes, and messaging. We will store any other data related to the user/user account in MongoDB. We will use GitHub Actions for the deployment pipeline. We plan on eventually integrating Steam API's as well to draw user data about their played games instead of having users manually input data, saving time. React Native also has a vast array of libraries to draw from. We will use its Firebase libraries for authentication, its Maps libraries for location-based features and services, navigation and stack libraries for page navigation, Elements/Papers libraries for UI design, etc.
Languages
Our app will be written primarily in TypeScript for type safety, as well as JavaScript for other app functionalities. Both are interchangeable with each other and fully supported by React Native + Expo.
Frameworks
React Native is an open-source framework used for developing cross-platform mobile apps using React. Expo simplifies the development process with built-in tools for debugging, live testing, asset management, and deployment.
IDE
We are using VS Code for our IDE as it is ideal for JavaScript-based projects. It has a lightweight interface, a large array of React Native extensions, GitHub integration, and a built-in terminal with debugging tools.
Libraries
| Library | Description |
|---|---|
| expo | Provides React Native development tools, build configurations, and simplified deployments |
| react-navigation | Handles stack and tab navigation between app screens |
| react-native-maps | integrates map functionality for displaying locations and user positions |
| react-native-paper | Provides cross-platform UI components that follow Material Design guidelines |
| react-native=elements | Provides cross-platform UI components that follow Material Design guidelines |
| firebase | Handles authentication, cloud messaging (notifications), and real-time updates |
| react-native-firebase | Firebases React Native SDK wrapper that helps integrate services like Firestore, Authentication, and Cloud messaging |
| axios/fetch API | Used for making HTTP requests to API's (Steam, Firebase, MongoDB backend) |
| mongoose/express | For handling database operations and connecting the mobile app to MongoDB via backend endpoints |
Services and API's
Firebase We will use Firebase Authentication for managing user accounts/logins, Cloud Messaging for notifications, and Firestore for lightweight storage and real-time updates.
MongoDB User-related and persistent data will be stored and hosted through MongoDB and its free "MongoDB Atlas" for simplicity and scalability.
Steam Web API We plan to integrate the Steam Web API to fetch user game statistics and activity data automatically.
Optional Custom REST API, like Node.js or Express, to bridge the gap between MongoDB and our app.
Package/Build Managers
| Tool | Purpose |
|---|---|
| npm/yarn | Used for managing React Native dependencies |
| Expo CLI | Handles building, testing, publishing for our app (both Android and IOS) |
Release: We will use Expo to create and distribute app binaries, specifically generating an .apk file and uploading it to GitHub Releases for testing.
Each release will be built using the Expo CI/CD process and distributed for easy installation.
Virtual Machines/Containers We are not using anything for our app development. Our workflow does not require Docker or any other Virtual Machines since Expo's local development environment is cross-platform and uses device simulators like:
- Android Emulator (Pixel 7) via Android Studio
- iOS Simulator (iPhone 13) via Xcode for Mac users
We will also test the app on physical devices and web browsers using the Expo Go app and web functionality, allowing for real time testing and debugging through a QR code.
Github Actions
We will use GitHub Actions for continuous integration and deployment automation. Our pipeline is as follows:
1. Run linting and tests on every push
2. Build the Expo project
3. Optionally trigger a release upload to Expo or GitHub Releases
Maintaining State
We will maintain states in memory through the above-mentioned navigation stack library that comes with React Native. This will track the current state of the user. Our database is simply for storing and retrieving information in said state.
It has features like "useState" and "useContext" for state hooks that are locally managed. This provides instant updates to the UI when the user navigates between screens.
However, if the data is persistent (user accounts, saved preferences, game activity, messages, etc), it will be stored in the Firebase Firestore and MongoDB Atlas.
- Firebase will handle the authentication and message notifications
- Mongo will store structured gameplay data (like user-linked stats) from Steam integration data, and other various profile information.
Essentially, Firebase manages the "who", MongoDB manages the "what".
MongoDB Atlas
MongoDB Atlas is our cloud-hosted database solution that stores collections for users, matches, messages, and preferences. Its flexibility allows us to store dynamic user data such as interests, favorite games, and experience levels without strict schema constraints. The database will interact with the backend via Mongoose models for easy querying and validation.
Example Collections:
- Users: profile info, trust rating, game preferences
- Matches: user IDs, compatibility score, match status
- Messages: sender, receiver, timestamp, and message body
Description: Stores user information for authentication.
| Attribute | Type | Description |
|---|---|---|
_id |
ObjectID | unique identifier for each user (Primary key) |
phone_number |
String | user’s phone number for one-time passcode authentication |
otp |
String | one-time passcode for authentication (expires after a certain duration) |
email |
String | user’s email for app recovery and notifications (optional) |
isVerified |
Boolean | status of whether the user's phone number is verified with the otp for their most recent session |
lastLogin |
Date | date and time of the last login on their device |
sessionToken |
String | unique identifier generated by a server to confirm a user's identity after they log in |
created_at |
Date | date and time when the user account was created |
Description: Stores all user information for the user profile and matching.
| Attribute | Type | Description |
|---|---|---|
_id |
ObjectID | unique identifier for each user (Primary key) |
display_name |
String | the user’s chosen display name |
profile_picture_url |
String | link to the user’s profile picture |
bio |
String | short description for the user’s profile |
age |
Int32 | the user’s age |
gender |
String | the user’s gender |
updated_at |
Date | date and time of the last update to the user’s profile |
Description: Contains information about all the games available for matching.
| Attribute | Type | Description |
|---|---|---|
_id |
ObjectID | unique identifier for each game (Primary Key) |
title |
String | the name of the game |
genre |
String | the game's genre |
platform |
String | the platforms the game is available on |
Description: Stores which games each user plays and their specific in-game details.
| Attribute | Type | Description |
|---|---|---|
_id |
ObjectID | unique identifier for each user game (Primary Key) |
user_id |
ObjectID | ID of the user |
game_id |
ObjectID | ID of the game |
Description: Contains user-specified criteria for finding a match.
| Attribute | Type | Description |
|---|---|---|
_id |
ObjectID | unique identifier for each user preference (Primary key) |
user_id |
ObjectID | ID of the user |
favorite_games |
String | the user's favorite games to play |
play_style |
String | the user’s preferred playstyles (e.g., ”Competitive,” “Relaxed”) |
genre |
String | the user’s preferred gaming genres |
platform |
String | the user’s preferred gaming platforms |
Description: Stores when one user expresses interest in another.
| Attribute | Type | Description |
|---|---|---|
_id |
ObjectID | unique identifier for each request (Primary key) |
requester_id |
ObjectID | ID of the requester |
receiver_id |
ObjectID | ID of the receiver |
requested_game_id |
ObjectID | the game for which the match was proposed |
request_status |
Boolean | the state of the request (e.g., “Pending,” “Accepted,” “Rejected”) |
requested_at |
Date | date and time when the request was made |
Description: Stores confirmed matches.
| Attribute | Type | Description |
|---|---|---|
_id |
ObjectID | unique identifier for each confirmed match (Primary key) |
user1_id |
ObjectID | ID of user 1 |
user2_id |
ObjectID | ID of user 2 |
game_id |
ObjectID | ID of the game |
match_score |
Int32 | the user’s calculated match compatibility score |
matched_at |
Date | date and time when the match was confirmed |
Description: Stores communication between matched users.
| Attribute | Type | Description |
|---|---|---|
_id |
ObjectID | unique identifier for each chat (Primary key) |
match_id |
ObjectID | ID of match |
user_id |
ObjectID | ID of the user who sent the message |
message_text |
String | the content of the message |
sent_at |
Date | date and time when the message was sent |
Description: Stores blocked users.
| Attribute | Type | Description |
|---|---|---|
_id |
ObjectID | unique identifier of each block (Primary key) |
user_id |
ObjectID | ID of the user performing the block |
blocked_user_id |
ObjectID | ID of the user being blocked |
blocked_at |
Date | date and time of the block |
Description: Stores the title of each prompt.
| Attribute | Type | Description |
|---|---|---|
_id |
ObjectID | unique identifier for each prompt title (Primary key) |
prompt_title |
String | title of the prompt (e.g., “Favorite Game”) |
prompt_type |
String | the type (e.g., the prompt requires a text or image response only) |
Description: Stores the responses provided by users to specific prompts.
| Attribute | Type | Description |
|---|---|---|
_id |
ObjectID | unique identifier for each prompt response (Primary key) |
user_id |
ObjectID | ID of the user |
prompt_id |
ObjectID | ID of the prompt |
response_type |
Array | categorizes the response (e.g., “text,” ”image”) |
response_text |
String | stores the text response if the response_type is ‘text’ |
response_image_url |
String | stores the URL to the image if response_type is ‘image’ |
responded_at |
Date | date and time when the response was recorded |
Description: Stores notifications for users about matches or messages.
| Attribute | Type | Description |
|---|---|---|
_id |
ObjectID | unique identifier for each notification (Primary key) |
user_id |
ObjectID | ID of the user |
notif_type |
Array | type of notification (e.g., “match,” “message”) |
notif_text |
String | content of the notification message |
read_status |
Boolean | status indicating if the notification has been read |
created_at |
Date | date and time when the notification was created |
- Example Query:
db.users.findOne({ phoneNumber: “+15551234567” });
- Example Query:
db.users.insertOne({
phoneNumber: “+15551234567”,
isVerified: false,
createdAt: new Date()
});
- Example Query:
db.users.updateOne(
{phoneNumber: "+15551234567"},
{$set:{otp:{code:"123456",expiresAt: new Date(Date.now() + 5 * 60000)}}}
);
- Example Query:
Example: db.users.findOne({
phoneNumber: "+15551234567",
"otp.code": "123456",
"otp.expiresAt": { $gt: new Date() }
});
- Example Query:
db.profiles.updateOne(
{ userId: ObjectId("USER_ID") },
{
$set: {
name: "Luna",
bio: "Casual gamer exploring co-op worlds.",
reasonForJoining: "Looking for co-op partners",
photoUrl: "https://cdn.app/profile123.jpg",
updatedAt: new Date()
}
},
{ upsert: true }
);
- Example Query:
db.chats.find({match_id: ObjectID(abcd1234) }).sort({sent_at: -1});
- Example Query:
db.matches.find({
$or: [
{ user1_id: ObjectID(abcd1234)},
{user2_id: ObjectID(efgh5678)} ]
});
- Example Query:
db.preferences.find({
platform: “PC”,
play_style: "Competitive",
genre: “FPS”,
});
Dummy/Placeholder Documents
Similar to Firestore's best practices, if a collection risks becoming empty, we will insert dummy document(s) to prevent automatic cleanup during development testing. This will ensure collections persist even when temporarily empty during account resets or test runs.
Authentication: Firebase Authentication Firebase Authentication will handle secure user signups and logins via email and password, or through social logins (optional). It ensures user identity is verified before allowing access to sensitive features like messaging or profile editing.
Hosting: Firebase Hosting Firebase Hosting will serve both our static assets and backend endpoints, simplifying deployment and ensuring fast global performance through built-in CDN support.
Primary Approach -- Firebase Firestone Messaging
Service: Firebase Firestone
Library: React Native Firebase SDK
Protocol: WebSockets (these are managed internally by Firebase)
We will use Firebase Firestore (FBFS) as our main solution for real-time chats between users. Each conversation will exist as a Firestore document with a nested /messages subcollection to store individual messages. FBFS supports bi-directional chats with low-latency synchronization. This means both users' chat screens should instantly update when a message is sent.
Using FBFS's built-in listeners called "onSnapshot", we can automatically detect and display new messages without needing to manually refresh or poll. Firebase Cloud Messaging will also be integrated to deliver push notifications when there are new messages received (including when the app is closed).
However, if Firestore becomes limiting or cost-prohibitive, we will consider the following alternative approach:
Firebase Realtime Database
This is essentially a simpler, JSON-based alternative to FBFS. Instead of documents, we provide instant data synchronization via WebSockets, which are already optimized for low-latency updates.
We are not going with this approach originally, though, due to less flexible data querying and complexity issues when growing to scale.
