Wyvern: If I Could Restart
November 2nd, 2021 represents the day I set out to recreate Discord. March 22nd 2022 represents the first commit to WyvernChat/Wyvern and the publicity of the project. October 4th 2022 represents the day I released alpha v1. I’m gonna cover every mistake made since November 2nd, 2021, and what I would do had I chose to restart.
The first mistake I made was using Material UI. Just wanna say that I have no issues with ui frameworks. They make your app accessible and good looking without too much work. Thing is, most of these apps look very similar. I wasn’t able to get the unique chat app look using MUI, so I moved to bootstrap… when will I ever learn. When I initially designed with Material, it wasn’t too big to change; just a sidebar and chat window. Bootstrap though, that was a change. Bootstrap is a heavily customizable css library and ui framework. That customizability quickly let me create a very powerful ui for Wyvern… then shot me in the foot just as fast. Bootstrap let me write my ui quickly, but didn’t prompt the fine tuned css manipulation that I needed for Wyvern. I’ve spent the last 2 months removing Bootstrap, and only recently succeeded. If I were to restart, I likely would’ve used TailwindCSS, because it just provides a modern and simplified method of styling components.
Next up, class components. I first wrote Wyvern using React Class Components, instead of the far more modern functional components. I did fix this, but only because of React Router. My initial implementation used React Router v6, but only part of it. React made transitioning from class to functional components very easy, by making class and functional usable together. Thing is, that didn’t work for hooks. In case you didn’t come from a React background, React Hooks allow you to make stateful components without needing classes and stuff. So... I didn't know that.
I started trying to use a hook called useParams
inside of a class component, that was a week of my life wasted. After that catastrophe, I learned of functional components from somebody in the Remix-Run Discord. That random person, you saved Wyvern. I'm glad I converted my stuff in that short period of time after starting, because it was only like 10 files to change. A lot, but not the 27 there is now.
Other issue, my entire structure of this system. This hellscape cost me literally 4 months, and almost giving up on the project. The initial way that I designed Wyvern was simple, it was just an ExpressJS server serving static Webpack files. This initial design was definitely Cross Origin Resource Sharing complient, but was hell to develop in. If I were to restart, it would be with NestJS and Vite (I did recently switch to Vite somehow!), so I could have a good developer experience in the backend, and super fast on the frontend.
I did actually find a fix to the Webpack problem though, something called the client server model.
Up until this point, everything was written as 1 big app. Every change restarted nodemon, rebuilt the frontend, and restarted the backend. This worked fine for like 10 components, and like 5 backend routes, but as things got bigger, it faltered. When you think of a falter, you might think errors, but no. It was not errors, but developer experience. See, Webpack is actually really slow. To build my 10 needed components, and some css and stuff, it took on average 11.34 seconds! 11.34 seconds between saving and seeing the results in my browser! I was not going to deal with that, so I took fixing it upon google.
Google led me to webpack dev server, a way to cache files in memory and exponentially improve build time. I saw several methods of integrating it with express, but honestly, I was scared to risk that. I saw some apps had separate domains for api and ui, so I decided that instead (this was stupid). What I did actually wasn’t stupid, it definitely put a separation between server and client, which is wanted for multi platform software. After a short headache, I had moved all of Wyvern to separated client/server directories! This worked perfectly the first time and was great!
Of course that is a writing trick known as sarcasm. It did not work great, and cost me at least 4 months of this project. My restart tip and advice for any fullstack developer: Learn Cross Origin Resource Sharing. Yay. I was stupid to make such a change without knowing what I was doing, but I did. CORS (as I will now refer to it) is basically what keeps requests to your stuff, on coming from your own stuff. CORS allows other domains to access information that is typically same-domain, such as your api. Alas, my api was not the issue, it was socket.io. That thing known as web sockets cost about 2 hours in development, I just allowed the origin, easy! Then I was asked to make a production beta…
My first production beta! If I could’ve restarted, I would’ve consistently tested that the app worked in production instead of just when someone asked. Socket.io did not pass well through Apache2, my web server. The express server of course did, but WebSockets, my realtime communicator, didn’t. That leads me almost directly to today. Start of October, I did get production working. Things broke because of other reasons, but those were general bugs, not production stupidity. I really thank the 4 people who convinced me here, because otherwise this post would be commemorating a simple switch to MongoD. Well thats a convenient transition
See, my initial creation of Wyvern used a custom made "database" known as a JSON (Javascript Object Notation) file. Now, I have known for a while that databases are required even at minor scale, and a plain text file will just not work. I've known that for a while, but not 1 year ago today. Had I known that, Wyvern would be much farther along. Instead, I've spent the last 2 months converting native Javascript maps to mongoose queries. If I were to restart here, I would've used a full database solution instead of a single file. MongoDB is as close to JSON as I could get, because I hate SQL (structured query language, aka how you access table databases, aka large spreadsheets, aka hell). When I initially tried to install MongoDB, I was using Prisma, and Object Relational mapper. These ORM's are systems that allow you to write native code instead of raw database queries. Before mentioned mongoose
is an example of an ORM. Prisma basically allows you to write cross database queries, and have a native typing language. It is really complicated, but cool software. I decided against it because there was too much complicated stuff involved in using it, when I could just convert my existing TypeScript definitions to mongoose models. Would I use Prisma if I had time to learn it? Yes, but I refuse to make the same mistake I made with starting Wyvern.
Oh, the same mistake with starting Wyvern you say? Was this project a mistake? Yes, I definitely shouldn't have started this at the time. See, I did something called "learning on the job", where you learn at the same time as making an important product. Now learning by doing is not a problem at all, it's how I started as a developer. But you should do simple tasks - irrelevant projects - to learn. Writing a full scale recreation of Discord (something I had joked about in Discord for about a month before) is not a beginner project. If I could restart? It would be restarting now! After I have mastered React, it's hooks, and that JANKY useState thing with arrays. My tip for literally anyone learning anything, don't try to use your skills in something important. Do small things, let yourself mess up, and learn from those mistakes where it doesn't matter! If you've just learned how to cook, don't get hired to be a private chef, work at a couple small restaurants first, and build experience!
Afterward:
I really wrote this to say thank you to everyone who has helped with Wyvern along the way. Be it the 1 person who forked this project, to my logo designer, my encourager to use MongoDB, and just the many people who inspired me to keep going. This project has been me for the last year, I have learned so much, and am eternally grateful. I won't say names, but you all know exactly who you are. Seriously, thank you so much. I never saw this day coming, and didn't think that I could progress from someone who barely knew the difference between GET and POST, to a fully operational (most of) Discord, in a year! There is still more to come, and still more to code, expect me to continue pushing updates for as long as I may live... or until I receive a cease and desist from Discord. Whatever may come first, know that you, you, reading this right now, were there during that first year. I have progressed so much as a person from working on this project, and really enjoyed my time with it. Since I need to publish this before 23:59, thank you so much. Until next time, stay healthy folks!
- TKDKid1000, founder of Wyvern
Related Posts
Wyvern Alpha Release Disaster
I recently released the first version of Wyvern! After many production headaches, I sent it out to people... and things went south.
Why I chose to rewrite TKDKid1000's Website with Firebase and Next.js
The 2 older versions of TKDKid1000's website worked, but they had their issues. In this article, I explain the history of these websites, and why and how I'm switching to Next.js and Firebase.
You must be logged in to comment!