I don’t have much experience in front-end development. When I started working on my web project, I decided to use React with TypeScript. It felt like a natural choice since it’s popular, has a huge ecosystem, and I wanted the type safety that TypeScript offers. Things were fine at first, but as I progressed, I realized there was more to front-end development than just writing code.

Phase 1: Styling from Scratch

Feeling confident, I thought, Why not write all the styles from scratch? I started using plain CSS modules with React, believing it would give me full control over the design. But this decision quickly became a bottleneck. My lack of experience in UI/UX design showed—I couldn’t visualize what the interface should look like or decide:

  • What colors to use?
  • How much padding or margin is appropriate?
  • How should components be aligned and spaced?

I would write some code, look at the result, and feel dissatisfied with the design. It didn’t look good, but I didn’t know how to fix it. This slowed the development process significantly and started to sap my motivation.

Phase 2: Tailwind CSS and the Design Dilemma

Realizing I needed help, I turned to Tailwind CSS. It seemed like an easy way to create decent-looking interfaces without needing to be a design expert. Tailwind’s utility-first approach allowed me to quickly apply styles directly in my JSX, speeding up the development process.

However, I hit another roadblock—I still didn’t have a design vision. Tailwind is a fantastic tool, but it doesn’t provide pre-designed components or templates. I was still stuck deciding:

  • Which utility classes would achieve the look I wanted?
  • How to maintain consistency across different components?

During this time, I restarted my project multiple times, hoping to make progress. I also experimented with Figma to draw my designs before coding. But designing in Figma was challenging—I lacked the skills to create something visually appealing from scratch.

This period was frustrating. The lack of progress in both development and design was stressful, and being in a rush only made things worse. I realized that having powerful tools doesn’t help if you don’t know how to use them effectively.

Phase 3: Shadcn/UI and Next.js

Eventually, I decided to try a UI component library to save myself from the design headache. I considered popular libraries like Material UI and Ant Design, but I wanted something that was:

  • Highly customizable.
  • Integrated well with Tailwind CSS.
  • Lightweight without adding too much bloat.

I discovered shadcn/ui, a collection of accessible and customizable components built with Radix UI and styled with Tailwind CSS. It was a great fit. It provided pre-built components that looked good out of the box, and I could easily extend or override them to suit my needs.

Around this time, I also migrated to Next.js. It was trending, and I thought its features like server-side rendering (SSR) and static site generation (SSG) would be beneficial for my project, especially for performance and SEO.

The Reality Check with Next.js

After some time with Next.js, I realized that most of my components were client-side, and I wasn’t fully utilizing the server-side capabilities. My application was highly interactive but didn’t require SSR or SSG since it was a single-page application (SPA) with dynamic content fetched after load.

Moreover, dealing with Next.js’s routing and the learning curve associated with its file-based routing system added unnecessary complexity. I began to question if Next.js was the right tool for my project.

Phase 4: Back to React (Vite) and Discovering Jotai

Recognizing that I didn’t need the extra features of Next.js, I decided to switch back to React but this time with Vite as my build tool. Vite offered a super-fast development server and a straightforward setup, which improved my development experience.

Revisiting State Management

I also revisited my global state management solution. I had tried tools like Redux and the Context API before, but they felt overly complex or cumbersome for managing the kinds of states my project needed, such as:

  • Chat states (e.g., active rooms, message lists).
  • User authentication and friend management.
  • Real-time notifications.

I discovered Jotai, a primitive and flexible state management library for React. Jotai was intuitive to use and made handling complex state interactions much easier. With Jotai, I could manage my app’s state more cleanly and efficiently without the boilerplate that comes with Redux.

Benefits of Jotai

  • Simplicity: It uses atoms (state units) that are simple to create and manage.
  • Performance: Updates are granular, so re-renders are minimized.
  • Scalability: It’s easy to scale your state management as your app grows.

Phase 5: Embracing Ionic for Mobile Development

For mobile, I initially tried React Native, but it turned out to be too much for my side project. Managing two codebases (web and mobile) and handling platform-specific quirks was time-consuming and impractical given my limited resources.

Instead, I turned to Ionic React. Ionic allowed me to reuse much of my existing React codebase while also supporting mobile platforms through web technologies. This hybrid approach saved time and effort, making it a better fit for my project.

Why Ionic?

  • Code Reusability: Write once, run anywhere. I could use the same codebase for both web and mobile.
  • Easy Learning Curve: Since it’s based on standard web technologies (HTML, CSS, JavaScript), it was easy to pick up.

Current Status

Today, my project is working fine. The code structure is far from ideal—it’s a bit messy, and I know it needs cleaning up. I plan to refactor it and make it more maintainable in the future. For now, I’m focused on functionality and learning along the way.

What I’ve Learned So Far

  • The Importance of Design: Good design is crucial. Tools like Tailwind CSS are powerful, but without a design vision, they can’t compensate for a lack of design skills.
  • Right Tools for the Right Job: Not every popular tool is necessary for every project. Next.js is fantastic, but if you don’t need SSR or SSG, it might be overkill.
  • State Management Matters: Finding a state management solution that fits your project’s needs can greatly simplify development. Jotai was a game-changer for me.
  • Leveraging UI Libraries: Using component libraries like shadcn/ui can accelerate development and improve the overall look and feel of your app.

Conclusion

This journey has taught me a lot about front-end development, from choosing the right tools to balancing design and functionality. I’ve made mistakes, restarted multiple times, and faced countless challenges. But each step has been a learning experience, and I’m confident my project will improve over time.

If you’re just starting out in front-end development:

  • Don’t Be Afraid to Experiment: Try different tools and frameworks to see what works best for you.
  • Focus on Learning: It’s okay if your code isn’t perfect. What’s important is that you’re learning and improving.
  • Use Available Resources: Leverage UI libraries and design systems to overcome design challenges.
  • Keep It Simple: Use the simplest tool that gets the job done. Complexity isn’t always better.

Remember, development is a journey, and every project is an opportunity to grow your skills. Keep coding, keep learning, and enjoy the process!