HandL is a daily reflection application that allows users to track their daily experiences by recording a high point and a low point each day, along with a numerical score. It helps users build a habit of daily reflection and provides insights into their emotional patterns over time.
This repository consists of two main parts:
- Frontend: React-based web application
- Backend: Node.js/Express REST API
- User authentication (register, login)
- Daily entry creation and tracking
- Social features (connect with friends, view their entries)
- Stats and visualizations (streaks, weekly averages)
- Profile management with image uploads
- Mobile-responsive design
- Optional SMS reminders
- Optional weekly email recaps
- React
- React Router
- Styled Components
- Axios
- React Icons
- Node.js & Express
- MongoDB & Mongoose
- JWT Authentication
- Cloudinary (image uploads)
- Twilio (optional SMS)
- SendGrid (optional emails)
- OpenAI (optional recap generation)
The backend is already deployed on Vercel as a serverless API at https://handl-backend.vercel.app/. You can check the API status at https://handl-backend.vercel.app/api/health.
The frontend is configured to use the production API URL. The production domain is www.handl.club.
If you want to run the backend locally for development:
- Navigate to the backend directory:
cd backend - Install dependencies:
npm install - Create a
.envfile based on.env.example - Start the development server:
npm run dev - The local backend will be available at
http://localhost:5000
- Install dependencies:
npm install - Start the development server:
npm start - The application will be available at
http://localhost:3000 - The frontend is configured to connect to the deployed backend API at
https://handl-backend.vercel.app/api
- Fork the repository
- Create a feature branch:
git checkout -b feature-name - Commit your changes:
git commit -m 'Add some feature' - Push to the branch:
git push origin feature-name - Open a pull request
This project is licensed under the MIT License.
Dhruv Gupta
Project Proposal
I would like to develop a project that allows people to track their day through a quick few things. The project is named HighsAndLows. Every day, they should be able to enter in a score from 1-10, a daily high, and a daily low.
They should be able to friend other users of the app and view their daily highs and lows, as well as charts/analytics about how they are doing generally. People should also be able to backtrack/fill out days they missed in a later time.
People will get formatted emails which recap their week (after they have used the platform for a whole week at least). These recaps should be generated with the help of LLMs.
Proposed Technical Stack
- MongoDB + Express + Node: We will intend to use MongoDB for storage of zips, agencies, locations, and partners.
- Vercel: Both the backend and frontend will be deployed on Vercel (in different deployments of course)
- Up to you: Some package that allows us to send texts every day around 10:30 PM to users to remind them to fill out for that day
- MailJS: For sending out emails that recap a person's week
- OpenAI API: We should use ChatGPT 4o-mini to generate these recaps above (given quite a lot of structure)
- Cloudinary: For image hosting
- React: The frontend will be all react. The app has been created using npx create-react-app to begin with.
Backend Setup
We have begun by creating a new react project. In the root of that, we have created a new folder called "backend". In the backend, we have run npm init -y
User Model
Username (String)
Name (String)
Phone Number (String)
Email (String)
Profile_Picture_URL (String)
Friends[] (Foreign Key)
Days[] (Foreign Key)
Day Model
Date (Date)
Score (Number)
High (String)
Low (String)
Backend Development Steps
These steps are to be followed by Cursor Agent running Claude 3.7 Sonnet. Each step should only be completed one at a time, and after each step is completed, the readme file should be updated accordingly. Do NOT go ahead at all and do not set up extra steps in advance
- ✅ Set up the file directory and all necessary introductory files for the project. Install any necessary components.
- ✅ Create and define our different file models
- ✅ Build out authentication and sign up/login framework. Authentication should last for 1 year when done, and rely on email. Phone number is also required.
- ✅ Build the controllers and routes needed to add and remove each of our models. Then, create routes to query the lists of them.
- ✅ Build out framework and middleware necessary for sending texts, adding friends, viewing friends, etc
- ✅ Build out framework and middleware necessary for uploading pictures to Cloudinary and then receiving back the link.
- ✅ Build out framework for summarizing weeks and sending out emails about them using SendGrid
Frontend Development Steps
- Create a file directory with images, components, data and pages. Create a global API variable that is set and can be edited for where the server is hosted
- Develop a header, footer, and landing page which explain what this project is about and how it works generally.
- Develop a sign up/log in page which follows the authentication guidelines laid out above
- Develop a dashboard from which users can view their own stats, fill out days they've missed and view previous days through a calendar feature and/or fill out the current day
- Develop a tab on the dashboard through which users can manage friend requests or search for new friends
- Develop a public view for each user which will show some aggregated stats as well as their 5 most recent days
- Build a feed feature which will display the person's friend's "Days", with the most recent ones at the top. You should be able to view their profiles from there as well
Frontend Considerations
- We want the frontend to be as clean and modern as possible, considering our target audience is 16-24 year olds. Take heavy inspiration from the UI of Notion
- We want the frontend to feel responsive and provide micro feedback
- This web application will most likely be used predominantly on mobile devices. Mobile compatibility is a top priority for this project.
Cloudinary Example File
const express = require('express');
const router = express.Router();
const upload = require('../middleware/upload');
const { uploadImage } = require('../utils/cloudinary');
const { auth } = require('../middleware/auth');
// Handle image uploads
router.post('/image', auth, upload.single('image'), async (req, res) => {
try {
if (!req.file) {
return res.status(400).json({
success: false,
error: 'No image file provided'
});
}
// Validate file type
const allowedTypes \= \['image/jpeg', 'image/png', 'image/jpg', 'image/webp'\];
if (\!allowedTypes.includes(req.file.mimetype)) {
return res.status(400).json({
success: false,
error: 'Invalid file type. Only JPEG, PNG, and WebP images are allowed.'
});
}
// Convert buffer to base64
const b64 \= Buffer.from(req.file.buffer).toString('base64');
const dataURI \= \`data:${req.file.mimetype};base64,${b64}\`;
// Determine folder based on route or query param
const folder \= req.query.type \=== 'profile' ? 'profiles' : 'articles';
console.log(\`Uploading image to ${folder} folder\`);
// Upload to Cloudinary using our utility
const imageUrl \= await uploadImage(dataURI, folder);
res.json({
success: true,
data: {
url: imageUrl
}
});
} catch (error) {
console.error('Image upload error:', error);
res.status(500).json({
success: false,
error: 'Failed to upload image. Please try again.'
});
}
});
module.exports = router;
Completed Steps
-
Backend Setup (Complete)
- Created directory structure: config, controllers, middleware, models, routes, utils
- Set up essential files: server.js, .env
- Created database connection utility
- Set up Cloudinary and file upload middleware
- Created authentication middleware structure
- Added error handling utilities
- Installed necessary packages
- Added .gitignore file
-
Data Models (Complete)
- Created User model with:
- Basic fields (username, name, phone, email, password)
- Profile picture URL
- Friend relationships and friend requests
- Authentication methods (JWT generation, password hashing)
- Virtual field for days
- Created Day model with:
- Date, score, high and low fields
- Relationship to User model
- Helper methods for formatting and analytics
- Indexed to ensure one entry per user per day
- Added utility methods for streaks and weekly averages
- Created User model with:
-
Authentication Framework (Complete)
- Implemented user registration with validation
- Implemented user login with JWT authentication
- Set up token expiry for 1 year as required
- Created protected routes with authentication middleware
- Added input validation using express-validator
- Implemented profile update functionality
- Created global error handling middleware
- Ensured email and phone number requirements are enforced
-
CRUD Operations (Complete)
- Implemented controllers for User and Day models
- Created routes for adding, retrieving, updating, and deleting entries
- Added validation for all routes
- Implemented secure data access controls
- Added query capabilities for listing days and users
- Set up proper error handling for all operations
-
Friend System and SMS Framework (Complete)
- Implemented friend request sending, accepting, and rejecting
- Added friend list retrieval functionality
- Set up Twilio integration for SMS
- Created scheduled daily reminder feature
- Added manual reminder triggering for admins
- Implemented notification preferences
- Created middleware to secure friend-related operations
-
Cloudinary Integration (Complete)
- Set up Cloudinary configuration
- Created file upload middleware using Multer
- Implemented image upload route
- Added secure authentication for uploads
- Created utility functions for cloud storage
- Configured different storage folders (profiles, general)
- Added proper error handling for uploads
-
Email Weekly Recap System (Complete)
- Implemented SendGrid integration for emails
- Created OpenAI-powered recap generation
- Added weekly scheduled emails
- Built admin routes for manual recap sending
- Created streak and average score calculations
- Implemented personalized email content
- Added fallback template for reliability
- Set up proper error handling for the email service