A modern, full-stack social media application inspired by Instagram, built with React, TypeScript, Express, and MongoDB. Vistagram allows users to share photos, like and share posts, and interact with a personalized timeline.
- User Authentication: Secure login and signup with JWT
- Photo Sharing: Capture or upload images directly from the camera
- Interactive Posts: Like and share functionality with real-time counters
- Responsive Design: Mobile-first UI with touch-friendly controls
- Cloud Storage: Images automatically uploaded to Cloudinary
- Persistent Sessions: Auto-login with valid JWT tokens
- Default Avatars: Random user avatars from Randomuser API
Frontend
- React 18
- TypeScript
- React Router
- Tailwind CSS
- React Icons
Backend
- Node.js
- Express
- MongoDB with Mongoose
- JSON Web Tokens (JWT)
- Cloudinary (image storage)
Development
- Vite (build tool)
- ESLint & Prettier
- Git
- Node.js v16+
- React/Vite
- MongoDB Atlas or local MongoDB instance
- Cloudinary account
- Environment variables configured
- Clone the repository:
git clone https://github.com/<your_username>/vistagram.git
- Install dependencies:
// For client:
cd client
npm i
// For server
cd server
npm i
- Create secrets file in the client and server directory:
- Inside client directory create
.env.developmentfile and paste the following line:
VITE_API_URL=http://localhost:8080
- Inside server directory create
.envfile and paste the following credentials
MONGODB_URI=your_mongodb_connection_string
JWT_SECRET=your_jwt_secret_key
CLOUDINARY_CLOUD_NAME=your_cloudinary_cloud_name
CLOUDINARY_API_KEY=your_cloudinary_api_key
CLOUDINARY_API_SECRET=your_cloudinary_api_secret
- Start the development server:
// Inside client directory:
npm run dev
// Inside server directory:
npm start
npm run populateSeedDatasetFeeds
Directory structure:
└── vistagram/
├── README.md
├── client/
│ ├── README.md
│ ├── eslint.config.js
│ ├── index.html
│ ├── package.json
│ ├── tsconfig.app.json
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ ├── vite.config.ts
│ └── src/
│ ├── App.css
│ ├── App.tsx
│ ├── index.css
│ ├── main.tsx
│ ├── components/
│ │ ├── Footer.tsx
│ │ ├── LoadingSpinner.tsx
│ │ ├── Navbar.tsx
│ │ ├── PostPage.tsx
│ │ ├── Timeline.tsx
│ │ ├── auth/
│ │ │ ├── AuthBanner.tsx
│ │ │ ├── AuthForm.tsx
│ │ │ ├── AuthGuard.tsx
│ │ │ ├── LoginPage.tsx
│ │ │ └── SignUpPage.tsx
│ │ ├── camera/
│ │ │ ├── CameraCaptureControls.tsx
│ │ │ ├── cameraContainer.tsx
│ │ │ ├── CameraPreview.tsx
│ │ │ └── ImageAndCaptionUploadControls.tsx
│ │ ├── fallback/
│ │ │ ├── EmptyFeed.tsx
│ │ │ ├── ErrorMessage.tsx
│ │ │ └── OfflinePage.tsx
│ │ ├── modal/
│ │ │ └── ShareModal.tsx
│ │ └── postcard/
│ │ ├── PostActions.tsx
│ │ ├── PostCaption.tsx
│ │ ├── PostCard.tsx
│ │ ├── PostHeader.tsx
│ │ └── PostImage.tsx
│ ├── constants/
│ │ └── api.ts
│ └── types/
│ └── index.ts
└── server/
├── package.json
├── tsconfig.build.json
├── tsconfig.json
└── src/
├── db.ts
├── index.ts
├── controllers/
│ ├── authController.ts
│ └── postController.ts
├── jobs/
│ └── populateSeedDatasetFeedsJob.ts
├── middleware/
│ ├── auth.ts
│ └── cloudinary.ts
├── models/
│ ├── Post.ts
│ └── User.ts
├── routes/
│ ├── authRoutes.ts
│ └── postRoutes.ts
└── services/
├── authService.ts
└── postService.ts
- User signs up or logs in
- Server validates credentials and returns JWT
- JWT stored in localStorage
- Subsequent requests include JWT in Authorization header
- AuthGuard protects routes requiring authentication
- Auto-login on page refresh if valid token exists
- Fixed bottom navigation on mobile devices
- Camera integration for photo capture
- Touch-optimized UI elements
- Responsive grid layout for posts
- Smooth transitions and animations
- Images captured from camera or uploaded
- Base64 encoded and sent to server
- Uploaded to Cloudinary with transformations:
- Resized to 1080×1080
- Quality optimized
- Converted to JPG format
- Cloudinary URL stored in database
POST /api/v1/auth/signup- Create new userPOST /api/v1/auth/login- User loginGET /api/v1/auth/profile- Get user
GET /api/v1/post/- Get all postsGET /api/v1/posts/:id/post- Get one postPOST /api/v1/posts- Create new postPATCH /api/v1/posts/:id/like- Toggle likePATCH /api/v1posts/:id/share- Increment share count