Couple of months ago I started building a mini project called ToolDeck. It's basically a launchpad for little tools developers and designers use. As its backbone; it uses Next.js for frontend, and Apollo Server for backend. MongoDB was also my choice of storing data. On top of that, everything is written in TypeScript, and I used SASS with modules for styling. I also made a mistake of using React Spring for some animations. I'll get to that in a bit... Now it's time for me to dive into the clusterfuck I created. Let's get started!
Next.js
I like the routing API of Next.js, and I certainly don't like creating a webpack project with bunch of external packages like SASS and TypeScript. Since it handles all of that, I'm happy with my decision. I made sure to waste all the time it saved me on other parts of the project with completely unnecessary details.
SASS
I used SASS with a header file that contains all the variables like colors, paddings, etc. And since I hate naming classes, I used it with modules. It's very easy to get SASS modules running in Next.js. This setup, in my opinion, is a very comfortable way of working with CSS.
React Spring
Oh boy... Don't get me wrong; React Spring is a very powerful tool for animations, and it currently powers the animated grid in the deck page of ToolDeck. Also it's fun to work with too, unless.. Unless you use it with TypeScipt. In VSCode, with every single code you wrote in a TypeScript file you import React Spring, IntelliSense loses its mind. And whole editor keeps lagging. I don't know what, but something is wrong with its type package. If you're going to use it with JavaScript, go ahead. It's a great library, but it's an awful experience with TypeScript.
Apollo React Client
Querying your GraphQL requests is effortless with Apollo React Client. It also takes care of most of the caching you'd normally do with Redux or other state management options. However, when it comes to altering that cache, it lacks simplicity. It isn't as easy as React Query's mutation function for instance. If you are aiming for creating an optimistic UI as I do, it'll fire back.
Apollo
I mentioned I used TypeScript across the project right? Well... This is a day in ToolDeckLand:
1) Write types for mongoose models
2) Write types for resolvers with TypeScript
3) Write types for GraphQL schema
4) Write Apollo Client queries
5) Write types for Apollo Client queries with TypeScript
Yes, I should have used codegen. But this is a small project and it shouldn't have that kind of complexity. Of course I knew this stack would be an overkill for a project in this scale, but I thought it would be fun. Turns out it's not... Writing same queries and same types over and over again takes away all the fun of adding new features. And I always miss something with either query fields or types. It easily becomes another debug adventure.
MongoDB
MongoDB was a good choice for this project. And MongoDB Atlas made it even easier to implement. You might need to do some configurations for Mongoose to work with findById or etc., but I had no serious problems while working with Mongoose.
Conclusion
Personal take; use REST API with React Query next time for a project with this scale. I also could have written my API with Next.js too, but I didn't want a monolith structure. And I'll be moving on to Framer Motion in the furute. I like React Spring, but I like TypeScript more. It's also worth mentioning that I deployed both frontend and backend to Vercel. But that's a story for another post, since I used TypeScript with path aliases and I had to compile my backend to JavaScript to be able to deploy. Maybe you should follow...
This project lives here if you're curious: tooldeckhq.com.
I hope this was useful, you can also follow me on Twitter for future content:
Top comments (2)
Nice overview, Ozan!
I'd be also interested in learning the deploy process: why did you choose vercel over other options and what challenges you've faced.
Looking forward your next article!
Thanks!
Thank you! I'll mention all of that in the next post.