My Journey to Programming: Building my first Full-Stack Application
Introduction This application was created as a prerequisite for completing my full-stack development certification program at Code Blossom. What is this app, and why did I choose to build it? I call this app Mondit—a finance tracker web application that allows users to track, manage, and view their finances all in one place. For this full-stack application, I implemented user authentication, deserialization, and data sanitization to ensure secure data handling. I also integrated data fetching using Axios for API calls, enabling users to dynamically retrieve and display their financial data. Beyond authentication, Mondit personalizes the user experience—such as displaying their first name on the dashboard—and automatically calculates total income, expenses, and savings in real-time. These calculations update dynamically, eliminating the need for manual computations. Building this project was both challenging and rewarding. It helped me deepen my understanding of full-stack development, from implementing secure server-side logic and API integrations to structuring an intuitive client-side UI for smooth user interactions. I also gained hands-on experience in configuring the app for seamless performance in a live production environment. Planning Product Features Knowing the required features and functionalities before building an application is crucial. It helps developers prioritize tasks and determine where to focus implementation efforts first. Below are Mondit’s main features: ✅ Secure authentication with session-based user login ✅ Full CRUD functionality for adding, editing, and deleting transactions in real time ✅ Visual data representation with charts, transaction history, and total summary boxes ✅ Automated calculations for total income, total expenses, and remaining savings ✅ Transaction filtering by date and category ✅ Optimized for web browsers with a user-friendly UI ✅ Light / Dark mode for better accessibility User Flow Starting a project of this scale without a guide of how each component will interact with each other is challenging. That’s why I created a user flow to streamline development and provide a clear reference to follow. Design Process The app consists of five main pages: Sign Up Login Dashboard Add Transaction Transaction History For the product design, I followed a common layout frequently used in modern web applications. The structure includes: A side navigation bar for quick access to key sections. A header displaying functional features like the user’s profile, date selection, and interface mode (light/dark). A main content area that showcases the app’s core functionalities. By following established design conventions, the app provides a seamless and intuitive user experience, allowing users to quickly adapt to its interface without unnecessary complexity. How Design Choices Influenced Development When I started this full-stack project, I approached development with a hands-on mindset—building and iterating as I progressed. While I focused on getting core features up and running, it also led to key realizations about structuring applications efficiently. Throughout the process, I discovered best practices in component reusability, identified areas for improvement in state management and API handling, and gained a better understanding of performance optimization in UI design. Component-Based Architecture: To ensure maintainability and avoid redundancy, I designed reusable components like the transaction list, summary box, and chart display. These elements were used across different pages, making it easier to scale and maintain the UI. Keeping a consistent structure across layouts also allowed me to reuse patterns instead of creating new designs from scratch for each section. State Management & API Calls – A Lesson Learned: One of my biggest realizations was the importance of optimizing API calls. Instead of centralizing data fetching, I unintentionally made redundant API requests across multiple components. This led to inefficiencies and unnecessary re-fetching. Moving forward, I plan to structure data flow more effectively to minimize redundant calls and improve overall performance. Styling & Performance Considerations: While my primary focus was on getting the UI functional, I overlooked some aspects of performance optimization. I noticed unnecessary re-renders, loading delays, and some data not reflecting updates in real-time in my Beta version. Additionally, I also did not make the app fully responsive, which limited usability on smaller screens. In future projects, I aim to refine my approach by optimizing dynamic updates and ensuring efficient styling techniques. Takeaway: While the app turned out functional, these experiences taught me the importance of planning and optimization—especially in API handling, state management, and UI performance. This project was a stepping

Introduction
This application was created as a prerequisite for completing my full-stack development certification program at Code Blossom.
What is this app, and why did I choose to build it?
I call this app Mondit—a finance tracker web application that allows users to track, manage, and view their finances all in one place.
For this full-stack application, I implemented user authentication, deserialization, and data sanitization to ensure secure data handling. I also integrated data fetching using Axios for API calls, enabling users to dynamically retrieve and display their financial data.
Beyond authentication, Mondit personalizes the user experience—such as displaying their first name on the dashboard—and automatically calculates total income, expenses, and savings in real-time. These calculations update dynamically, eliminating the need for manual computations.
Building this project was both challenging and rewarding. It helped me deepen my understanding of full-stack development, from implementing secure server-side logic and API integrations to structuring an intuitive client-side UI for smooth user interactions. I also gained hands-on experience in configuring the app for seamless performance in a live production environment.
Planning
Product Features
Knowing the required features and functionalities before building an application is crucial. It helps developers prioritize tasks and determine where to focus implementation efforts first. Below are Mondit’s main features:
✅ Secure authentication with session-based user login
✅ Full CRUD functionality for adding, editing, and deleting transactions in real time
✅ Visual data representation with charts, transaction history, and total summary boxes
✅ Automated calculations for total income, total expenses, and remaining savings
✅ Transaction filtering by date and category
✅ Optimized for web browsers with a user-friendly UI
✅ Light / Dark mode for better accessibility
User Flow
Starting a project of this scale without a guide of how each component will interact with each other is challenging. That’s why I created a user flow to streamline development and provide a clear reference to follow.
Design Process
The app consists of five main pages:
- Sign Up
- Login
- Dashboard
- Add Transaction
- Transaction History
For the product design, I followed a common layout frequently used in modern web applications. The structure includes:
- A side navigation bar for quick access to key sections.
- A header displaying functional features like the user’s profile, date selection, and interface mode (light/dark).
- A main content area that showcases the app’s core functionalities.
By following established design conventions, the app provides a seamless and intuitive user experience, allowing users to quickly adapt to its interface without unnecessary complexity.
How Design Choices Influenced Development
When I started this full-stack project, I approached development with a hands-on mindset—building and iterating as I progressed. While I focused on getting core features up and running, it also led to key realizations about structuring applications efficiently. Throughout the process, I discovered best practices in component reusability, identified areas for improvement in state management and API handling, and gained a better understanding of performance optimization in UI design.
Component-Based Architecture:
- To ensure maintainability and avoid redundancy, I designed reusable components like the transaction list, summary box, and chart display. These elements were used across different pages, making it easier to scale and maintain the UI.
- Keeping a consistent structure across layouts also allowed me to reuse patterns instead of creating new designs from scratch for each section.
State Management & API Calls – A Lesson Learned:
- One of my biggest realizations was the importance of optimizing API calls. Instead of centralizing data fetching, I unintentionally made redundant API requests across multiple components. This led to inefficiencies and unnecessary re-fetching.
- Moving forward, I plan to structure data flow more effectively to minimize redundant calls and improve overall performance.
Styling & Performance Considerations:
- While my primary focus was on getting the UI functional, I overlooked some aspects of performance optimization. I noticed unnecessary re-renders, loading delays, and some data not reflecting updates in real-time in my Beta version.
- Additionally, I also did not make the app fully responsive, which limited usability on smaller screens. In future projects, I aim to refine my approach by optimizing dynamic updates and ensuring efficient styling techniques.
Takeaway:
While the app turned out functional, these experiences taught me the importance of planning and optimization—especially in API handling, state management, and UI performance.
This project was a stepping stone, and I now have a clearer idea of how to approach future full-stack applications more efficiently.
Choosing the Tech Stack
Since I started programming with JavaScript as my core language, using the MERN Stack (MongoDB, Express, React, Node.js) made the most sense.
- Database: MongoDB + Mongoose for flexible database management
- Backend: Node.js & Express for handling RESTful APIs and server-side logic
- Frontend: React for a dynamic, component-based UI
- Authentication: Passport.js for secure, session-based login
- Styling: Styled-Components & MUI for UI design
- Testing: Postman for API testing (GET, POST, PUT, DELETE requests)
- Deployment: Netlify for the frontend, Railway for the backend
Biggest Challenges
Learning Curve
Understanding and implementing the full-stack workflow for the first time—from backend server configurations, session handling, and cookies to securing user data, frontend frameworks, and API integrations—was overwhelming at first.
But that was just the tip of the iceberg. You know you're really learning when you start encountering and troubleshooting errors like 400 Bad Request and 401 Unauthorized, often caused by missing parameters or simple typos. Then there’s 502 Bad Gateway, which, in my case, turned out to be due to an exhausted PaaS. And let’s not forget the hours (or even days) spent debugging a CORS issue after deploying the project live, only to realize that similar errors still occurred—even though everything worked fine during development. One key lesson I learned?
Just because your project runs smoothly in development doesn’t mean it will work seamlessly in production. :)
But these challenges pushed me to sharpen my problem-solving skills and critical thinking.
Imposter Syndrome
One thing I struggled with was the constant pressure to write clean, efficient code, which sometimes left me questioning my skills. I held myself to an unrealistic standard, believing I needed to be flawless at proper code structure—even though I was still new to all of this. I often forgot that learning is a process, and perfection doesn’t exist. Over time, I’ve learned to embrace progress over perfection. One proof of that is this project, which is still in its Beta version.
Integration Woes
Getting the backend and frontend to communicate seamlessly tested my patience more than anything. You know that feeling when your APIs are being stubborn? One moment, everything works fine, and the next, after tweaking one request, nothing works anymore. It was a constant cycle—fix one thing, break another. At that time, it was frustrating. But now that I look back and try to remember the experience, I just laugh at it. LOL.
Deadline
This was another major source of pressure. While I’m new to coding, I’m not new to working environments, and I always make an effort to meet my project deadlines. I initially planned to finish this project in two months, but I underestimated the unexpected roadblocks along the way. At first, I thought I’d just follow a tutorial with similar functionality, but I ended up modifying and adding features, making my development process more unique (and more complex). As a result, I missed my deadline by a month—but in hindsight, it was worth it.
Deployment Pains
Since this was my first time deploying a full-stack project, I had no idea what “exact” configurations I needed. Sure, I read documentation and watched tutorials, but doing it in practice was a different story. I’d say the production stage was the most painful step—navigating an unfamiliar platform like Railway, troubleshooting deployment errors, and dealing with production-specific issues like CORS configurations. It was tough, but in the end, I figured it out, and that’s what matters.
What I Learned
One step at a time
In programming, there’s always a lot to learn and even more to apply. But I’ve realized that you don’t need to accomplish everything at once. Progress—no matter how small—matters when building something. Prioritizing what’s truly important is key because big projects are built through small, consistent improvements. And this requires continuous effort.
The power of Community
The saying "No man is an island" may sound cliché, but in development, it holds true.
As a designer for over five years, I was used to making independent creative decisions. But coding is different—it thrives on shared knowledge, insights, and collaboration.
I learned this firsthand while debugging a persistent 404 error. I had checked my code line by line, yet nothing made sense. The more I tried to solve it alone, the more lost I felt. Overthinking every possible cause of the error became overwhelming, and that’s when I knew I needed guidance. I was fortunate to have my mentor, Sana from Code Blossom, who was always there to help me realign my approach and interpret my ideas into code. I’m also grateful for my other mentors, Carolyne and Raphael, and my co-participant, Yuliia—whenever I reached out for help, they never hesitated to lend a hand.
Unlike design, development demands structured logic, system compatibility, coding standards, and efficiency. That’s why developer-to-developer communication is crucial. While it’s important to seek help when needed, it’s equally vital to balance independent problem-solving with collaboration. Trying to figure everything out alone can drive you insane, but relying too much on others can hinder growth. Finding that balance is key.
Understanding Fundamentals Matters
Learning new technologies can take you far, but a strong grasp of the fundamentals is what ensures long-term growth. Whenever I face a challenge and feel stuck, I always find myself going back to the basics. Fundamentals serve as the foundation upon which everything else is built—they provide clarity when solving complex problems and adaptability in an ever-evolving tech landscape. Trends in programming languages may shift, but core concepts like problem-solving, logic, and software architecture principles remain essential, allowing you to adapt and thrive in any environment.
You Don’t Have to Know Everything
In tech, you don’t need to master every tool or framework—because no one can. Technology evolves rapidly, and the key to keeping up isn’t knowing everything; it’s being adaptable. If you have a strong foundation, you can apply what you know and improve as you go.
Googling, reading documentation, and leveraging LLMs aren’t shortcuts or signs of incompetence—they’re essential skills that even the most experienced developers rely on. Learning is a continuous process, and growth comes from applying knowledge, not just accumulating it.
Growth is in the Struggle
The most frustrating moments teach you the most. Debugging for hours only to realize the issue was a simple typo? Humbling. These moments don’t just test your patience—they sharpen your ability to troubleshoot, adapt, and think critically. Over time, what once felt overwhelming becomes second nature. And when you finally see your app running smoothly in production, it makes all the challenges worth it. Every struggle builds resilience.
Final Thoughts
Building this application was a huge learning experience for me. Initially, full-stack development felt overwhelming, but breaking it down step by step made it manageable. I also learned that good project planning and well-structured code make development much smoother.
And debugging? It always starts with one question: “What exactly does this error mean?”. Instead of overthinking and looking for unnecessary solutions, staying focused on the specific issue at hand makes problem-solving more efficient.
This project not only strengthened my technical skills but also reinforced my passion for full-stack development, making me even more excited to keep improving, learning, and building more complex applications in the future.