A modern, production-grade social media application built with React 19, TypeScript, Vite, and Firebase.
What's buzzing right now.
Buzz is a fully functional social media frontend with real-time-ready architecture, feature-based code organization, and Firebase-backed authentication, data persistence, and media storage via Cloudinary.
- Email/password sign up & sign in
- Google OAuth via Firebase popup flow
- Persistent auth state via
onAuthStateChanged - Protected routes β redirects to
/authif unauthenticated,/onboardingif no username set - Username onboarding step with uniqueness validation
- Logout from navbar
- Create posts with optional image or video media (uploaded via Cloudinary)
- Caption with 2200-character limit and live counter
- Like / unlike posts with Firestore persistence (
arrayUnion/arrayRemove) - Double-tap media or double-click caption to like (heart burst animation)
- Single-click media opens full-screen
MediaViewerModal - Paginated feed β 10 posts per page with "Load More"
- Remove file preview before posting
- Add comments on any post (persisted to Firestore)
- Emoji reactions on individual comments via
emoji-picker-react - Floating emoji picker with smart viewport-aware positioning
- Toggle reactions β clicking an existing reaction removes it
- Comment count visible on feed cards
- Full comments view in a split-panel modal (media left, comments right on desktop)
- Notification modal showing like, comment, and follow events
- Notifications stored per-user in Firestore subcollection (
users/{uid}/notifications) - Unread badge count in left sidebar and mobile bottom nav
- Mark all as read on modal open
- Follow / unfollow users from profile pages, Explore, and Search results
- Follower and following counts on profile
- "Following" feed tab on Home β filters posts to people you follow (includes your own posts)
- Suggested users in right sidebar (desktop)
- Follow state persisted to Firestore subcollections (
users/{uid}/following,users/{uid}/followers)
- Debounced (400ms) combined search β users and posts in one query
- User results matched by username prefix via Firestore range query
- Post results matched by caption or author username (client-side filter on recent 20 posts)
- Highlighted matched text in results
- Filter pills β All / People / Posts
- Loading skeletons and empty states
- Trending tab β posts ranked by time-decay score (Hacker News gravity algorithm)
- Hashtag topic extraction from captions with click-to-filter
- People tab β paginated user directory with follow actions, lazy-loaded on tab open
- Media tab β 3-column photo/video grid with a lightbox viewer (keyboard arrow navigation, prev/next buttons)
- Tab state persisted in
sessionStorage
- Dedicated
/post/:idroute - Falls back to Firestore fetch if post not in context cache
- Light / dark mode toggle with system preference detection on first load
- Theme persisted via
localStorage - CSS variable-based theming with smooth 0.15s transitions
- Toast notification system (success, error, info) with enter/exit animations
- Skeleton shimmer loading states throughout
- Responsive layout β left sidebar + right sidebar on desktop, bottom nav on mobile
- Scroll position restoration per route via
localStorage - Animated tab indicator using Framer Motion spring physics
- Heart burst overlay animation on double-tap like
| Layer | Technology |
|---|---|
| Framework | React 19 |
| Language | TypeScript 5.9 |
| Bundler | Vite 7 |
| Routing | React Router DOM v7 |
| Styling | Tailwind CSS v4 |
| Animation | Framer Motion 12 |
| Icons | FontAwesome 7 (free solid, regular, brands) |
| Emoji Picker | emoji-picker-react v4 |
| Auth & DB | Firebase 12 (Auth + Firestore) |
| Media Uploads | Cloudinary (unsigned upload preset) |
| State | React Context API |
src/
βββ app/
β βββ App.tsx # RouterProvider root
β βββ router.tsx # Route definitions + ProtectedRoute wrappers
βββ components/
β βββ layout/
β β βββ AppLayout.tsx # Main shell: sidebar + main + modals
β β βββ Navbar.tsx # Logo, theme toggle, user avatar, logout
β β βββ LeftSidebar.tsx # Desktop nav links + notification badge
β β βββ RightSidebar.tsx # Suggested users (desktop only)
β β βββ BottomNav.tsx # Mobile tab bar
β βββ ui/
β βββ Avatar.tsx # Initials fallback avatar
β βββ Tabs.tsx # Animated tab bar (Framer Motion)
βββ contexts/
β βββ UIContext.tsx # Active modal, theme, emoji picker position
β βββ ToastContext.tsx # Global toast queue with animations
βββ features/
β βββ auth/
β β βββ AuthContext.tsx # Firebase user state, profile, follow helpers
β β βββ authService.ts # Google OAuth, email/password, signOut
β β βββ ProtectedRoute.tsx # Auth + onboarding guard
β βββ follow/
β β βββ FollowContext.tsx # Follow/unfollow, follower counts (Firestore subcollections)
β βββ navigation/
β β βββ ScrollRestoration.tsx # Per-route scroll position save/restore
β βββ notifications/
β β βββ NotificationContext.tsx
β β βββ notifications.types.ts
β β βββ components/
β β βββ NotificationModal.tsx
β βββ posts/
β βββ PostContext.tsx # Posts array, pagination, like/comment/reaction mutations
β βββ posts.types.ts # Post, Comment, Reaction interfaces
β βββ components/
β βββ PostCard.tsx
β βββ CommentItem.tsx
β βββ CommentInput.tsx
β βββ CommentsModal.tsx
β βββ CreatePostModal.tsx
β βββ EmojiPickerPortal.tsx
β βββ MediaViewerModal.tsx
βββ hooks/
β βββ useDebounce.ts
βββ lib/
β βββ firebase.ts # App, Auth, Firestore instances
β βββ cloudinary.ts # Unsigned upload helper
βββ pages/
β βββ Home.tsx # Feed + Following tabs
β βββ Explore.tsx # Trending / People / Media tabs
β βββ Search.tsx # Debounced combined search
β βββ Profile.tsx # User profile + post grid
β βββ PostDetail.tsx # Single post view
β βββ Auth.tsx # Login / Sign up
β βββ Onboarding.tsx # Username setup
β βββ NotFound.tsx
βββ utils/
β βββ formatRelativeTime.ts # just now / 5m / 2h / 3d / 1w
βββ styles/
β βββ index.css # CSS variables, Tailwind import, animations
βββ main.tsx # Entry point β provider tree
- Node.js β₯ 20
- A Firebase project with Authentication and Firestore enabled
- A Cloudinary account for media uploads
git clone https://github.com/armansinghh/buzz-social.git
cd buzz-social
npm install
npm run dev- Create a project at console.firebase.google.com
- Enable Email/Password and Google sign-in providers
- Create a Firestore database (start in test mode for development)
- Replace the config in
src/lib/firebase.tswith your own project credentials
- Create a free account at cloudinary.com
- Create an unsigned upload preset
- Add the following to a
.envfile in the project root:
VITE_CLOUDINARY_CLOUD_NAME=your_cloud_name
VITE_CLOUDINARY_UPLOAD_PRESET=your_upload_preset| Provider | Responsibility |
|---|---|
AuthProvider |
Firebase user state, profile fetch, login/signup/logout, follow helpers |
UIProvider |
Active modal state, light/dark theme, emoji picker position |
PostProvider |
Posts array, cursor-based pagination, like/comment/reaction Firestore mutations |
FollowProvider |
Follow/unfollow actions, follower & following counts, lazy-loaded per uid |
NotificationProvider |
Notification list (Firestore-backed), unread count, mark-as-read |
ToastProvider |
Global toast queue with timed dismiss and enter/exit animations |
Provider order in main.tsx:
AuthProvider
ββ UIProvider
ββ ToastProvider
ββ NotificationProvider
ββ PostProvider
ββ FollowProvider
| Path | Component | Guard |
|---|---|---|
/ |
Home (feed + following tabs) | β Protected |
/explore |
Explore (trending, people, media) | β Protected |
/search |
Search | β Protected |
/profile/:id |
Profile (by username or uid) | β Protected |
/post/:id |
Post detail | β Protected |
/auth |
Login / Sign Up | Public |
/onboarding |
Username setup | Public |
* |
404 Not Found | Public |
Protected routes redirect to /auth if unauthenticated, or to /onboarding if the user has no username set yet.
users/{uid}
βββ uid, username, name, email, avatar, createdAt
βββ following/{targetUid} β { followedAt: ISO string }
βββ followers/{followerUid} β { followedAt: ISO string }
βββ notifications/{notifId}
βββ recipientId, senderId, senderName, senderAvatar
βββ type: "like" | "comment" | "follow"
βββ postId? (for like/comment)
βββ isRead: boolean
βββ createdAt: ISO string
posts/{postId}
βββ authorId, authorUsername, authorAvatar
βββ caption, createdAt
βββ likes: string[] (array of user UIDs)
βββ media?: { url, type: "image" | "video" }
βββ comments: Comment[]
βββ id, authorId, authorUsername, authorAvatar
βββ text, createdAt
βββ reactions: { emoji: string, users: string[] }[]
- Real-time feed updates via Firestore
onSnapshot - Push / in-app notifications persisted and live
- Firestore security rules β lock down read/write per user
- Error boundaries β graceful fallback UI on Firestore/component errors
- Shared
UserProfiletype extracted tosrc/types/ - Deduplicate
PersonCard/PeopleCardacross Search and Explore - Extract
EmptyStateand skeleton components tosrc/components/ui/ - Post deletion (author only)
- Edit profile (bio, avatar upload)
-
AnimatePresenceon modals for exit animations (Framer Motion) - Explore page β hashtag detail page at
/tag/:name - Story / ephemeral posts
- Repost / quote post
- Direct messaging
- Full-text search with Algolia or Typesense
- Rate limiting & spam protection on notifications
- PWA support (offline, installable)
This project is licensed under the MIT License.
Made with β€οΈ by Arman Singh