Portfolio Tracker
Features
- Search and add stocks to holding
- Edit stock holding
- Summary of total cost, value, and profit/loss
- Change the currency on the summary
- Stock allocation compared to total stock held
- Fetch international news and Indonesia news
- Automatically add currency option when user add a stock from that region to their holding
Why I made it
I am using multiple apps to track my investment. One for Indonesia stocks, and one for US stocks. It works fine, but I want to get a unified view of everything I own. I also want to see news of the day when I check my holdings. Another thing that bothers me is that the apps I use to track stocks use different currencies for stock holding summary. This app exists so that I can have everything I need in one dashboard.
The Structure
- Database: MongoDB (hosted on Atlas)
- Backend: Express.js, handling API endpoints using routers
- Frontend: React.js, server state (stock data, fetching, caching) is managed with React Query with a one-hour stale time to avoid unnecessary re-fetches. Client state (currency toggle, auth) is handled with Zustand.
- Authentication: jwt, tokens are issued on login and verified via middleware on every protected route. Passwords are hashed with bcrypt before storage. Route protection follows ownership verification to prevent IDOR vulnerabilities. Auth flow stores the JWT in localStorage and rehydrates on page load, so sessions persist across refreshes.
Mistakes
- Not working on authentication first Working on the authentication after setting up the express routers forces me to rewrite the routers again
- Working on the frontend too much before setting up the database I use Zustand stores to hold the user's holding for the first frontend prototype. I work too much on the business logic on the frontend before actually setting up the database. When I started integrating database to my system, I have to rewrite every business logic meant to accommodate Zustand store structure into fitting it to React Query model
- Not breaking the react elements optimally at first
Images