Profile image

Uche's Coding Corner

Passionate about software, technology, personal discoveries, and more.

Exploring New Technologies: Creating a Planner App with Vue 3

Fri Jun 30 2023 🍵 0 min read

I believe that to truly master a skill, practical experience is essential. This has always been my advice to aspiring frontend developers. While it's beneficial to explore various technologies and frameworks through small projects or extensive reading, the best way to grow your skills is by building a scalable project that you can continually build upon as you learn new things and discover new use cases.

My favourite side projects are productivity apps. There are numerous productivity apps in the market, such as Todoist, Trello, Google Calendar, and Habitica. However, I thought, why not build one tailored to my needs using frontend technologies I'm less familiar with?

Amidst my work and various other personal projects, I began creating my planner app that is a combination of todo lists and habit tracker. I set five strict criteria for the app:

  • It had to be a Vue 3 app.
  • It had to use at least one JavaScript feature I had no experience with.
  • It needed to be designed with accessibility in mind.
  • It had to be a progressive web app (PWA).
  • It had to be testable.

The technologies I ended up using were Vue 3, Pinia for state management, web workers, IndexedDB for storage, and Vitest for testing.

Ideation

Like anyone, I begin every new project by brainstorming ideas. As the primary user of the application, I wanted it to be straightforward and easy to use. I narrowed down the core use cases to three:

  • A user should be able to create tasks for any future date.
  • A user can create a list and add tasks to it.
  • A user can establish habits.

Based on these use cases, I developed my requirements and defined the user journey.

Next, I moved on to the design phase. I sketched wireframes to determine component positioning, page flow, and the overall user journey. Once satisfied with the initial design, I used Figma to create the pages and components. Tailwind CSS assisted in establishing the colour theme and building the basic reusable components. The final design was simple, clean, and easy to implement.

Learning more about progressive web apps

With the Vite PWA plugin, it's easy to have a basic setup of PWA. I wanted to challenge myself and at least a rudimentary understanding of the setup required to have a PWA compliant application. The Chrome team behind Web.dev have created an excellent course (https://web.dev/learn/pwa) to understand all aspects of progressive web app development. I was able to get a good understanding of the manifest and the standard practices.

IndexDB as client-side storage

For the initial phase of the project, I wanted the app to be completely serverless, so I opted for client-side storage. While I typically use local web storage for smaller web projects and simpler data, the potential complexity and possibility to use a server in the future led me to choose the IndexedDB API, which offers a storage system akin to a relational database.

Setting up a database with IndexedDB was straightforward. It was easy to scan the store, add, and retrieve data. However, combining data from multiple stores proved challenging. The solution I devised required more iterations and comparisons of entries than I would have preferred, impacting overall data retrieval performance. I think my mistake was treating IndexedDB too much like a traditional relational database; a simpler structure would have been more effective.

Additionally, the asynchronous nature of the IndexedDB API required careful consideration of how to use the database across the application.

Leveraging web workers

Web workers were something I had known about for a long time but had little to no experience with. I wanted to change that, so I created a small use case that would allow me to gradually introduce the concept into my project: cleaning up old or expired entries from the app. Web workers operate in the background and do not use the main thread, which keeps it free to handle user interactions without lag.

The implementation of the web worker for this use case is fairly simple. The application only needed to be aware via a message when the cleaning started and ended. Exceptions were handled in such a way that the failure had no impact on functionality. This is a relatively simple use of web workers, but there are many possibilities for further exploration. I would like to introduce proper client-side caching to see how this positively impacts efficiency and performance.

Accessibility

Sometime last year, I took some courses in UX design to gain a better understanding of the field and how I can improve my approach to user experience. One aspect of these courses was accessibility, which made me realize how often people with disabilities are overlooked in daily web development. As someone who has friends and acquaintances with disabilities, accessibility is now a significant focus in all my work. This is the first project where accessibility has been an integral part of the initial phase of development and planning.

Ensuring website accessibility is straightforward with resources like the A11y Project and W3C. Additionally, modern browser DevTools come with accessibility inspectors, making it easier than ever to create inclusive websites.

I found it enlightening to put myself in the shoes of someone with disabilities by navigating the app using only the keyboard and screen readers (ex: macOS VoiceOver). This exercise was invaluable in solidifying my approach to testing web applications for accessibility compliance and enhancing the user experience for everyone.

Testing with Vitest

Since switching from Jest to Vitest for my Vue projects, I've found it to be a game-changer. Vitest seamlessly integrates with Vite, requiring less setup and configuration. Its API closely mirrors Jest's, making the transition smooth with minimal learning curve. I also found Vitest to have a better overall performance in terms of speed.

Test-driven development (TDD) is my preferred testing approach, as it ensures your code is testable, reliable, and has fewer bugs. However, it can be tedious to implement this approach when starting a new project under tight deadlines. I had set a specific timeline for the first phase of this project that I was unwilling to extend, especially due to my full-time job, numerous hobbies, and limited time. Therefore, I opted to compromise and prioritize testing critical components over testing the entire application.

While the test coverage isn't as extensive as I'd like, I have created a strong testing groundwork for future enhancements. Over time, I plan to incrementally expand and improve the test coverage, especially with more focus on component testing (testing integrated components).

Conclusion

The project was enjoyable to build. It was occasionally frustrating, as the planning of the architecture could have been better, and I had to iterate over the implementation of some parts of the application. Most importantly, I learned a lot and identified areas where I could improve. While the app is far from perfect, it serves as a foundation for experimenting with new ideas and honing my skills. I had the opportunity to explore powerful JavaScript features and witness its practical benefits firsthand. There is much to improve, particularly in terms of testing coverage and user experience.

Moving forward, the next steps involve enhancing the app further by adding more animations, perfecting the design and accessibility, and simplifying the data structure.

App demo

static site generation
javascript
vue