Skip to content

armansinghh/buzz-social

Repository files navigation

Buzz

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.


✨ Features

πŸ” Authentication

  • Email/password sign up & sign in
  • Google OAuth via Firebase popup flow
  • Persistent auth state via onAuthStateChanged
  • Protected routes β€” redirects to /auth if unauthenticated, /onboarding if no username set
  • Username onboarding step with uniqueness validation
  • Logout from navbar

πŸ“ Posts

  • 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

πŸ’¬ Comments & Reactions

  • 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)

πŸ”” Notifications

  • 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 System

  • 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)

πŸ” Search

  • 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

🌐 Explore

  • 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

πŸ“„ Post Detail

  • Dedicated /post/:id route
  • Falls back to Firestore fetch if post not in context cache

🎨 UI & Theming

  • 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

πŸ›  Tech Stack

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

πŸ“ Project Structure

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

πŸš€ Getting Started

Prerequisites

  • Node.js β‰₯ 20
  • A Firebase project with Authentication and Firestore enabled
  • A Cloudinary account for media uploads

Installation

git clone https://github.com/armansinghh/buzz-social.git
cd buzz-social
npm install
npm run dev

Firebase Setup

  1. Create a project at console.firebase.google.com
  2. Enable Email/Password and Google sign-in providers
  3. Create a Firestore database (start in test mode for development)
  4. Replace the config in src/lib/firebase.ts with your own project credentials

Cloudinary Setup

  1. Create a free account at cloudinary.com
  2. Create an unsigned upload preset
  3. Add the following to a .env file in the project root:
VITE_CLOUDINARY_CLOUD_NAME=your_cloud_name
VITE_CLOUDINARY_UPLOAD_PRESET=your_upload_preset

πŸ—‚ Context Architecture

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

🧭 Routing

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.


πŸ”’ Firestore Data Model

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[] }[]

πŸ—ΊοΈ Roadmap

  • 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 UserProfile type extracted to src/types/
  • Deduplicate PersonCard / PeopleCard across Search and Explore
  • Extract EmptyState and skeleton components to src/components/ui/
  • Post deletion (author only)
  • Edit profile (bio, avatar upload)
  • AnimatePresence on 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)

πŸ“œ License

This project is licensed under the MIT License.


Made with ❀️ by Arman Singh

About

Buzz is a scalable social platform built with React+TypeScript, featuring structured media posts, modal based UX, context driven state management, and clean feature based architecture.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages