DEV Community

Cover image for How I Built JMServices: Challenges, Strengths, and Lessons from My SaaS Journey
Maxim King
Maxim King

Posted on

How I Built JMServices: Challenges, Strengths, and Lessons from My SaaS Journey

JMServices began as a little side project of mine, born out of necessity. My family runs a locksmith business, and I was overwhelmed by the endless stacks of paperwork piling up everywhere in our house, it wasn’t hard to miss. It was clear there had to be a better way to streamline the operations—and that’s when the idea for JMServices took root.

Initially, I set out to create a simple backend system, which quickly evolved into the foundation of what would become JMServices today. Back then, I hadn’t even settled on a name—it was just my attempt to solve a pressing problem. As a backend developer at heart, I focused on building a robust core system first. Gradually, I crafted the frontend using TailwindCSS, which has grown into the platform you see today. With over 1,500 commits to the project, I’m excited to share the journey through the tools and technologies I’ve used along the way.

The first tool I embraced was Nest.js, which laid the groundwork for the backend of JMServices and shaped the first two versions of the API. One of my main focuses was on building the authentication section, as securing user data was crucial. I started by creating the authentication routes and integrated Prisma ORM with a MongoDB database for seamless data storage. Adding my first user was a huge milestone, marking the beginning of what would soon become a more comprehensive solution. As I continued refining the platform, I experimented with various design tools but ultimately settled on TailwindCSS because of its user-friendly nature and my long-standing desire to learn it. This choice allowed me to effectively craft the initial login and signup routes. Initially, the system was designed for just one company, so the signup route only accepted authorized company email addresses. However, as I envisioned a commercial version of JMServices, I implemented features that allowed multiple companies to sign up and manage payments—a topic I’ll dive into shortly.

When I first designed the interface using TailwindCSS, I kept it simple, focusing on three main menus: Jobs, Customers, and Inventory. These served as the foundational building blocks of JMServices. Each menu featured straightforward DataTables, allowing users to interact with their data easily. The minimalist design focused on functionality and usability, which enabled me to gather valuable feedback as I continued developing the platform. This simplicity laid the groundwork for future enhancements while ensuring that users could navigate the system effortlessly from the start.

Initially, I integrated Stripe as our payment solution to handle transactions smoothly and securely. However, as JMServices evolved, I recognised the need for a more customisable billing solution. That’s when I began exploring Lago, an open-source billing platform. This shift will allow me to tailor the payment process to better suit the needs of our growing user base, offering more flexibility and control over subscription management and billing features. I’m excited about the potential that Lago brings and how it will enhance our service offerings moving forward.

What began as a solution tailored for one company quickly evolved as I recognized the potential for a much broader application. The vision for JMServices shifted toward a multi-tenant architecture, allowing multiple companies to benefit from the platform simultaneously. This transition was driven by my desire to create a scalable service model that could cater to diverse businesses, providing them with a tailored experience while optimising resource utilisation. By developing a multi-tenant framework, we could offer features like customised dashboards and user management for each company, paving the way for a more dynamic and collaborative service. This strategic pivot not only expanded our target market but also positioned JMServices as a versatile tool that could adapt to the unique needs of various industries.

Throughout this journey, my father has been an invaluable partner. With his experience running the family locksmith business, he provided insights into the practical challenges faced by small companies, helping me understand how JMServices could address those needs effectively. Our collaboration has been pivotal in shaping the platform’s direction, especially as we transitioned to a multi-tenant model. Together, we brainstormed features and enhancements that would not only streamline operations for our users but also align with our vision of creating a scalable service model.

Now, let’s dive back into some technical details. After reaching version 3, we made a significant decision to transition our entire codebase from TailwindCSS to a new design system called Chakra UI. This shift not only enhanced our design consistency but also improved the overall user experience with its modular and accessible components. Chakra UI allowed us to create a more cohesive and visually appealing interface, leading us to the polished solution we see today. Alongside this transition, we also started using Redis to implement caching between the frontend and backend. This addition significantly improved our application’s performance by reducing response times and easing the load on our databases. The combination of Chakra UI for design and Redis for caching was a crucial step in refining JMServices, ensuring that our platform remains user-friendly and adaptable to future updates.

Integrating Docker into my workflow was a game-changer for speeding up development. As a solo developer, I often found myself battling the frustrating “it works on my machine” problem. Docker allowed me to create consistent and reproducible environments that made this issue a thing of the past. I loved how it simplified managing dependencies and setting up my application across different stages of development. This not only saved me time but also gave me peace of mind, knowing that I could quickly share my environment with any collaborators without worrying about compatibility. Overall, Docker has become an essential tool in my arsenal, freeing me to focus more on building features and less on troubleshooting environment-related headaches

The Version 3/4 Dashboard

Once the groundwork was laid, we turned our attention to building out additional features that would enhance the platform. We integrated AWS S3 buckets to facilitate image uploads, allowing users to store and manage their visuals efficiently. To improve user engagement, we also implemented Intercom, enabling real-time chat support and fostering better communication with our users. As our user base grew, so did our business, and the platform evolved into the comprehensive solution you see today. Remarkably, I’m still the solo developer behind this project, continuing to build upon the foundation I established over two years ago, driven by the same passion and vision that sparked the creation of JMServices.

As I navigated the development of JMServices, I faced numerous challenges as a solo developer. With no team to rely on, I leaned heavily on the support of colleagues I’ve met along the way and the vast resources available on platforms like Stack Overflow. While many issues were easily resolved with a bit of research and experimentation, some presented significant obstacles that tested my problem-solving skills. However, being a solo developer doesn't mean success is impossible; instead, it has taught me to be more independent and resourceful when tackling complex problems. Each challenge has strengthened my ability to navigate the ups and downs of development, ultimately fostering a deeper sense of confidence in my skills and capabilities.

As I reflect on this journey, I want to encourage anyone considering embarking on a solo venture to embrace the challenge. While it can be daunting to go it alone, the rewards are immense. You have the power to bring your vision to life, learn invaluable skills, and discover your resilience in the face of obstacles. There’s so much you can achieve on your own, and the satisfaction of seeing your ideas materialise is truly unparalleled. Remember, every great project starts with a single step—take it, and you might surprise yourself with what you can accomplish.

Top comments (0)