Building a Notification Center in a Firebase PWA
Managing a sales team requires many tools. My control panel used FCM push notifications, chats, reminders, and a shared calendar.
The problem was these tools lived on separate islands. An operator had to jump between sections to check a leave request or a message. There was no single place to see everything.
I built a notification center. It is a single timeline for every relevant event.
How I Used Firebase
I use both Firestore and Realtime Database (RTDB). Each serves a specific purpose.
• Firestore for history: Use .get() for data that does not change, such as leave requests. This keeps costs low because you do not need a permanent listener. • RTDB for live data: Use .on('value') for chat, reminders, and calendar events. These nodes are small and need to react instantly.
Choosing the wrong one shows up immediately in your Firebase bill.
The Technical Hurdles
Building the UI required solving three main problems:
Mobile Usability I used flex-wrap: wrap for filter chips. My first version used horizontal scrolling. On mobile, users could not see the chips and did not know they could scroll. Wrapping them into two rows fixed this.
CSS Positioning I appended the panel directly to document.body. If you nest a fixed element inside a container with overflow:hidden, the positioning breaks.
The Session Restore Bug In production, users using "remember me" saw an empty panel. The initialization code only ran during manual login. It did not run when the session restored.
I implemented three fallback levels to ensure the center always loads:
- A wrapper on the login function.
- A polling loop that checks for the user every 500ms.
- A MutationObserver that watches for the user profile to appear on the screen.
Instances of Successful Design
- Use localStorage to track read status per user.
- Use composite indexes in Firestore for complex queries.
- Use media queries to move fixed elements on mobile so they do not block the top bar.
Architecture matters. Use Firestore for logs and RTDB for live updates.
