I planned to build a social media app for our lovely buddies, our dogsšāš¦ŗ. It comes to my mind when I was walking puppy BjĆørn to the dog park for a playdate. I was wondering are there bigger dogs in the park, or is it allowed for off-leash play? I thought it would be cool to have an app where I can check the dog parks, see other dogs, and any useful information related to our friends. Then I thought itās a perfect project for my portfolio so I decided to develop it.
Iāve used Vite, React, TypeScript, and Firebase tech stacks for Auth, database, CDN and hosting. It still needs a lot of work to be done, but Iām happy with the progress so far. Iām planning to add more geo-locations features like places, businesses, and posts location tagging. Iām also thinking about adding different postās types like events and polls, or maybe a marketplace for dog products and services. The possibilities are endless, and Iām excited to see where this project will go.
Why Firebase?
HighPaws is an exciting project that Iām working because I wanted to learn more about Google Firebase platform especially Firestore NoSQL database and learn and adopt my mindset from relational database to noSQL document-oriented database. I think itās a big challenge for relational mindset developers to switch to noSQL.
Firebase also have bunch of other great features that I wanted to give it a shot, like serverless functions, cloud storage, hosting and authentication. Another interesting subject that I learned about was setup CI/CD workflow for this project, using Github Actions, YAML language, to automate the deployment and build process in production whenever I push my commits or merge to main branch.
name: Deploy to Firebase Hosting on merge
'on':
push:
branches:
- main
jobs:
build_and_deploy:
runs-on: ubuntu-latest
environment: production
concurrency: production
steps:
- uses: actions/checkout@v4
- run: npm ci && npm run build
- uses: FirebaseExtended/action-hosting-deploy@v0
with:
repoToken: '${{ secrets.GITHUB_TOKEN }}'
firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_HIGHPAWS_BUDDIES }}'
channelId: live
projectId: highpaws-buddies
About the app
HighPaws is a place where user can sign up, create a profile for their dogs and share their dogās photos, and stories with other dog lovers, they can also follow or un-follow others, check otherās profile and posts, like or dislike posts and photos, and comment on them. Users can also send and receive messages to their friends, and receive notifications about their activities, for example who liked their posts, who followed them, or who commented on their posts.
Here is a video walkthrough of the app functionality:
Firestore Fan-out and data normalization
The most fan part of this project was designing database schema based on Firebase noSQL database, and use data normalization and fan-out technique to store data in Firestore.
To accomplish this I had to write bunch of serverless functions to handle the data normalization and fan-out process. For example to create a feed for each user, I created a collection called feeds
under each user document as a sub-collection, and whenever a user post a photo or a message, a document created in posts
sub-collection of the user document, then my serverless function will trigger and grab the post data and create a copy of the original post in the feeds
sub-collection of all followers of the user.
Here is an example of how I used Firebase serverless functions to handle the fan-out or data normalization in Firestore database:
import {
onDocumentCreated,
onDocumentUpdated,
onDocumentDeleted,
} from "firebase-functions/v2/firestore";
// See a full list of supported triggers at https://firebase.google.com/docs/functions
export const fanoutCreatedNewPost =
onDocumentCreated("profiles/{profileId}/posts/{postId}", (event) => {
const profileId = event.params.profileId;
const postId = event.params.postId;
// TODO: Fan-out logic of newly created post's document
});
export const updateFanoutPost =
onDocumentUpdated(`profiles/{profileId}/posts/{postId}`, (event) => {
const docData = event.data;
if (!docData) return
const beforeData = docData.before.data();
const afterData = docData.after.data();
// TODO: logic related to post's update
});
It was a great learning experience for me to work with noSQL database but still I have a lot of unanswered questions especially about the scalability, performance, database optimization to lower the cost, these are the things I you can only learn by working on a real project with growing data and users.
Responsiveness
Iāve used Tailwind CSS for styling the app, and the app is fully responsive and works great on mobile devices, tablets and desktops.
One thing I dislike about is how others handle navigation or sidebars in mobile devices, I saw many apps that use two versions of the navigation, one for desktop and one for mobile, but I think itās not a good practice, Iād rather use the same navigation for both desktop and mobile, and make it responsive as I did in this project.
The below video shows how the navigation sidebar works and transforms between desktop and mobile devices.
At the end, there are still other great features that I implemented in this project but didnāt mention here, like the authentication, user profile, the private messaging system, and notifications, but I think itās enough for now.
Please checkout the app and let me know what you think about it, any feedback is appreciated. Also feel free to check the source code on Github.