A modern, full-stack social media web application built with React and FastAPI. Pulse enables users to connect, share posts, follow other users, exchange messages, and explore trending content in a clean, minimalistic interface.
- Project Overview
- Key Features
- Tech Stack
- Architecture Overview
- Project Structure
- Setup and Installation
- Environment Variables
- Running the Application
- Key Functional Workflows
- API Documentation
- Known Challenges and Solutions
- Contributing
Pulse is a social media platform designed to provide users with a streamlined experience for sharing content and connecting with others. The application prioritizes simplicity, performance, and a clean user interface while delivering all essential social networking features.
The platform solves the need for a lightweight, modern social networking application that:
- Provides real-time social interactions without unnecessary complexity
- Offers a distraction-free, minimalistic user interface
- Maintains data persistence and synchronization across sessions
- Delivers responsive performance on modern web browsers
- User registration with email validation
- Secure login with JWT-based authentication
- Session persistence across browser refreshes
- Automatic token management and renewal
- Create text posts with optional media attachments
- Image upload support (JPG, PNG, GIF, WebP)
- Hashtag support for content categorization
- Like, comment, and save functionality
- Post deletion for content owners
- Follow and unfollow other users
- Real-time follower and following counts
- Suggested users based on network activity
- Profile-level follow status indicators
- Direct messaging between users
- Conversation history persistence
- Real-time message synchronization
- Unread message indicators
- Customizable user profiles
- Bio and profile information editing
- Post history on profile pages
- Follower and following statistics
- Search functionality for users and content
- Trending hashtags section
- Explore page for content discovery
- User suggestions based on activity
- Bookmark posts for later viewing
- Persistent saved posts collection
- Easy access to saved content
- Activity notifications for interactions
- Mark as read functionality
- Notification filtering options
| Technology | Version | Purpose |
|---|---|---|
| React | 18.2.0 | UI component framework |
| Vite | 5.0.0 | Build tool and dev server |
| React Router DOM | 6.30.2 | Client-side routing |
| Axios | 1.13.2 | HTTP client for API calls |
| Tailwind CSS | 3.4.19 | Utility-first CSS framework |
| Lucide React | 0.263.1 | Icon library |
| Technology | Version | Purpose |
|---|---|---|
| FastAPI | 0.115.5 | Web framework for API |
| SQLAlchemy | 2.0.36 | ORM for database operations |
| PostgreSQL | - | Primary database |
| Pydantic | 2.10.3 | Data validation |
| Python-Jose | 3.3.0 | JWT token handling |
| Passlib | 1.7.4 | Password hashing |
| Uvicorn | 0.32.1 | ASGI server |
- PostgreSQL: Primary relational database for all persistent data
- SQLAlchemy ORM: Object-relational mapping for database interactions
- JWT (JSON Web Tokens): Stateless authentication mechanism
- BCrypt: Password hashing algorithm
- Bearer Token: Authorization header format
Pulse follows a client-server architecture with clear separation between frontend and backend responsibilities.
+------------------+ +------------------+ +------------------+
| | HTTP | | SQL | |
| React Frontend | <-----> | FastAPI Backend | <-----> | PostgreSQL |
| (Vite Dev) | REST | (Uvicorn) | | Database |
| | | | | |
+------------------+ +------------------+ +------------------+
| |
| |
v v
+------------------+ +------------------+
| Local Storage | | Static Files |
| (Token, User) | | (Uploads) |
+------------------+ +------------------+
- Frontend to Backend: All API communication uses REST endpoints over HTTP
- Authentication Flow:
- User submits credentials
- Backend validates and returns JWT token
- Frontend stores token in localStorage
- Subsequent requests include token in Authorization header
- Data Persistence:
- Database serves as the single source of truth
- Frontend fetches fresh data on component mount
- State updates are synchronized through API calls
User Action -> React Component -> API Service (axios) -> FastAPI Router ->
SQLAlchemy ORM -> PostgreSQL -> Response -> Component State Update -> UI Re-render
pulse/
├── frontend/ # React frontend application
│ ├── src/
│ │ ├── components/ # Reusable UI components
│ │ ├── pages/ # Page-level components
│ │ ├── services/ # API service layer
│ │ ├── App.jsx # Root component
│ │ ├── main.jsx # Application entry point
│ │ └── index.css # Global styles
│ ├── package.json # Frontend dependencies
│ ├── tailwind.config.js # Tailwind configuration
│ └── vite.config.js # Vite configuration
│
├── backend/ # FastAPI backend application
│ ├── app/
│ │ ├── models/ # SQLAlchemy database models
│ │ ├── routers/ # API route handlers
│ │ ├── schemas/ # Pydantic validation schemas
│ │ ├── utils/ # Utility functions
│ │ ├── config.py # Application configuration
│ │ ├── database.py # Database connection setup
│ │ └── main.py # FastAPI application entry
│ ├── uploads/ # Uploaded media files
│ ├── requirements.txt # Python dependencies
│ └── .env # Environment variables
│
└── README.md # This file
The frontend handles:
- User interface rendering and interactions
- Client-side routing and navigation
- Form validation and user feedback
- API communication and response handling
- Local state management
- Authentication token storage
The backend handles:
- API endpoint definitions and routing
- Business logic implementation
- Database operations and queries
- Authentication and authorization
- File upload handling
- Data validation and sanitization
- Node.js 18.x or higher
- Python 3.11 or higher
- PostgreSQL 14.x or higher
- Git
git clone https://github.com/yourusername/pulse.git
cd pulse- Create and activate a virtual environment:
cd backend
python -m venv venv
# Windows
venv\Scripts\activate
# macOS/Linux
source venv/bin/activate- Install Python dependencies:
pip install -r requirements.txt-
Create the
.envfile with required environment variables (see below) -
Initialize the database:
python create_tables.py- Navigate to the frontend directory:
cd frontend- Install Node.js dependencies:
npm installCreate a .env file in the backend/ directory:
# Database Configuration
DATABASE_URL=postgresql://username:password@localhost:5432/pulse_db
# JWT Configuration
SECRET_KEY=your-secret-key-here-make-it-long-and-random
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=1440
# CORS Configuration
CORS_ORIGINS=http://localhost:5173
# Application Settings
APP_NAME=Pulse Social Media API
APP_VERSION=1.0.0
DEBUG=True| Variable | Description |
|---|---|
DATABASE_URL |
PostgreSQL connection string |
SECRET_KEY |
Secret key for JWT token signing |
ALGORITHM |
JWT signing algorithm (default: HS256) |
ACCESS_TOKEN_EXPIRE_MINUTES |
Token expiration time in minutes |
CORS_ORIGINS |
Allowed frontend origins (comma-separated) |
DEBUG |
Enable debug mode for development |
cd backend
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000The backend API will be available at http://localhost:8000
API documentation is auto-generated at:
- Swagger UI:
http://localhost:8000/docs - ReDoc:
http://localhost:8000/redoc
cd frontend
npm run devThe frontend application will be available at http://localhost:5173
cd frontend
npm run build
npm run preview- User navigates to login page
- User enters credentials (username/password) or registration details
- Frontend sends POST request to
/auth/loginor/auth/register - Backend validates credentials and returns JWT token with user data
- Frontend stores token in localStorage
- Frontend redirects user to home page
- All subsequent API requests include the token in Authorization header
- User clicks "Create Post" button
- Modal opens with text input and media upload option
- If media is attached, image is uploaded via
/upload/imageendpoint - Post data (text, hashtags, media URL) is sent to
/posts/endpoint - Backend creates post record and returns post data
- Frontend refreshes post feed to show new content
- User views another user's profile or user card
- User clicks "Follow" button
- Frontend checks current follow status via
/follows/check/{userId} - Frontend sends POST to
/follows/(follow) or DELETE to/follows/{userId}(unfollow) - Backend creates/removes follow record in database
- Frontend updates UI and refreshes user statistics
- User navigates to Messages page
- Frontend fetches conversations via
/messages/conversations - User selects a conversation
- Frontend fetches message history via
/messages/conversation/{userId} - User types and sends message
- Frontend sends POST to
/messages/with receiver_id and content - Message appears in conversation view
- User navigates to Settings page
- User modifies profile fields (username, email, bio)
- User clicks "Save Changes"
- Frontend sends PUT request to
/users/me - Backend validates and updates user record
- Frontend updates local state and localStorage with new user data
The backend provides a comprehensive REST API. Full documentation is available at /docs when running the server.
| Method | Endpoint | Description |
|---|---|---|
| POST | /auth/register |
Register new user |
| POST | /auth/login |
Authenticate user |
| GET | /users/me |
Get current user |
| GET | /users/{id} |
Get user profile |
| PUT | /users/me |
Update current user |
| GET | /posts/ |
Get posts feed |
| POST | /posts/ |
Create new post |
| DELETE | /posts/{id} |
Delete post |
| POST | /follows/ |
Follow user |
| DELETE | /follows/{id} |
Unfollow user |
| GET | /messages/conversations |
Get conversations |
| POST | /messages/ |
Send message |
| GET | /notifications/ |
Get notifications |
| POST | /upload/image |
Upload image file |
Problem: User data and statistics were lost when the page was refreshed.
Cause: The application relied too heavily on client-side state without proper synchronization with the backend.
Solution: Implemented a data fetching strategy where components fetch fresh data from the backend on mount. The getCurrentUser function now fetches user data with statistics from the server rather than relying solely on localStorage.
Problem: Following or unfollowing a user did not update the follower counts immediately.
Cause: The frontend was not refreshing user statistics after follow actions.
Solution: Added a refreshUserStats callback that is passed to components and called after follow/unfollow actions to update the sidebar and profile statistics.
Problem: API requests were failing with 401 Unauthorized errors intermittently.
Cause: Token was not being properly attached to requests, or tokens were expiring without proper handling.
Solution:
- Implemented axios interceptors to automatically attach tokens to all requests
- Added proper error handling in the response interceptor
- Ensured tokens are stored immediately after login and cleared on logout
Problem: Media upload showed "coming soon" and images could not be attached to posts.
Cause: The upload endpoint and frontend integration were not implemented.
Solution:
- Created
/upload/imageendpoint in the backend - Implemented
uploadImagefunction in the frontend API service - Added multipart/form-data handling for file uploads
- Configured static file serving for uploaded images
Problem: Frontend components crashed due to unexpected API response formats.
Cause: Backend responses used different field names (e.g., is_following vs isFollowing).
Solution: Standardized API response formats and added fallback handling in the frontend to accept both naming conventions where necessary.
- Fork the repository
- Create a feature branch (
git checkout -b feature/new-feature) - Commit your changes (
git commit -m 'Add new feature') - Push to the branch (
git push origin feature/new-feature) - Open a Pull Request
- Frontend: Follow React best practices and ESLint configuration
- Backend: Follow PEP 8 style guide for Python code
- Commit messages: Use conventional commit format
- Documentation: Update relevant README files for significant changes
Muhammad Abdullah
- GitHub: @abdullahxdev
- LinkedIn: Muhammad Abdullah
- Email: abdullahisdev@gmail.com
This project is licensed under the MIT License. See the LICENSE file for details.
For issues and feature requests, please open an issue on GitHub.
For detailed technical documentation, see: