I finally did it! I created a website from scratch and actually hosted it for the world to see! The finished product can be seen here, and the code here. What makes this especially awesome is I already have a monetization strategy in place.
This most definitely marks a turning point in my life. I feel way more confident as a software developer and I now have a basic road map on how to finish project in the future.
However, since this is my first time completing a project, I wanted to reflect on my the process and document the key lessons learned, cool things I did, and what I would do differently. Lets jump right in.
Consistent progress > Death marches
I've learned I'm an all or nothing kinda guy. There are times where I have fixated and hacked away on something as if I had transformed into Gollum from The Lord of the Rings. My laptop had become "my precious". However, because I am not actually possessed, I quickly get burnt out and end up abandoning the project.
Other times I have earmarked a weekend to hack on a project, only to get invited to something fun and exciting by my awesome friends. So I would push working on project to the following weekend. However, by then I had lost motivation or thought of something new to work on and the project died before it really got started.
This lead to unfinished project after unfinished project. In order to prevent this project from ending up like so many before it, I committed myself to making some progress every day, even if it meant only 15 minutes worth.
My goal was to never set the bar so high it was unrealistic to keep up with, which should reduce burnout. I also didn't want to have to "come back" to the project after a week or two had passed. Usually by then I have forgotten what the hell I was doing so I have to waste time relearning stuff.
I must admit, making some progress everyday actually worked! Time for friends was still possible, I spent minimal time relearning I had already done, and constantly seeing progress helped keep me motivated.
Have clearly defined requirements
I don't know about you, but I find it very easy to start planing for outcomes that never come to past. It is also just as easy to get lost dreaming up amazing features and additions that aren't needed for MVP.
As an example, a chess game I worked on earlier this year ended up "needing" a REST API, dashboard for game statistics, an AI so I could play by myself, and for some reason it needed to account for DDOS attacks. Looking back, all I can say is wtf was I thinking?! I wasn't building the next Github, all I needed was a simple chess game that supported multiplayer functionality via websockets.
This time I wrote out what I wanted for the end product and I stuck to it. Every time I thought of some "awesome" new feature, I wrote it down to implement at a later date, but only after my MVP was live.
Create small bite sized todo task
How do you eat an elephant? The typical response is one bite at a time. The same same approach can be applied here. All of my small changes eventually added up to form a finished project.
Breaking down task into small units of work was hugely beneficial. I tried to keep each task under an hour of work time. It wasn't perfect, and some task had hidden sub-task, but I will definitely keep doing this in the future. One thing that really made this work was breaking a task down further if it started to take longer than planned, which usually meant pulling the difficult part into its own task.
Working this way meant I rarely felt overwhelmed by the project as a whole since each task was measured in minutes or hours instead of days or weeks. Secondly, I uncovered potential roadblocks early by thoroughly thinking through most problems.
Have a monetize strategy in place
Surprisingly, this helped more than I thought it would. My mom promised to pay me for every property she sells where the client came from the website. I also have to help manage her mailing list, and do a little bit of marketing on Facebook and Twitter, but that is OK.
Knowing that I can get paid from this project helped motivate me to keep pushing forward on instead of starting something new. I guess you could say there was more to gain from completing this project.
Technical things I learned
CORS, aka Cross Origin Resource Sharing, is one of those things I probably heard of some time ago but never really had to worry about till now. While trying to perform an AJAX request, I ran into an error message similar to this one.
Now I just needed to actually fix the problem in my application. That's where Flask-CORS came in handy. It allowed me to return the necessary headers and list out the origins that are allowed.
I am ashamed to say before now, I didn't even know the basics of cross site scripting. I think I'm starting to see why I had serious impostor syndrome. Any who, I decided to finally learn the basics, and I thought the following video series did a great job teaching me: XSS Tutorials. It talks about persistent scripts vs non-persistent scripts, and how to protect yourself from XSS attacks.
Docker is one of those things that everyone kept telling me about and that I should be using. I started to believe them but was afraid it might be over complicating my life.
In order to find out, I took Dive into Docker by Nick Janetakis. The course was great and I was instantly hooked. However, I needed a project to use all those new docker skills on.
This project ended up being the perfect test bed, and to my surprise, Docker met and exceeded all my expectations! I was able to catch a number of production deployment issues all while running it on my laptop! Secondly, the amount of configuration I had to do was greatly reduced thanks to the nginx and letsencrypt docker images. Once I added docker-gen to the mix, I thought I was on top of the world.
Best of all, docker made it extremely easy to host my mom's new landing page on the same VPS as this blog which meant no additional cost!
Custom Webpack configuration
The create-react-app tool is great for quickly bootstrapping a React project. But personally, tools that automagically do things for me only fuel to my impostor syndrome if I have no clue what they are doing. Plus, Webpack can be used for more than just React apps so I thought it would be a good skill to pick up.
I ended up learning the basics of Webpack from the React Fundamentals course by Tyler Mcginnis, but there are plenty of free resources out there. Here are a couple I thought looked pretty good
The whole point of this site is to work as a lead generation page, which means we need to know where traffic is coming from. This is exactly the kind of thing Google Analytics was made for.
However, the dashboard that greeted me after logging in was pretty overwhelming. Luckily, there are plenty of free resources to help noobs like me. This video provided a decent overview of some basic dashboard functionality: Google Analytics 2018 Beginners Tutorial.
Next I headed over to the developer documentation and went through the Fundamentals section found here. Still lost on how best to add GA to my React site, I ended up using this library: React Google Analytics Module. I figured out after the fact how to add the tracking code without the library but I kinda like what the library provides.
Useful error logs is a developers best friend. However, setting up a logging aggregator did not sound fun.
Turns out it wasn't that bad. A friend of mine recommended a service called Loggly. They have a decent free tier that I am taking advantage of and setup it up was pretty easy thanks to their documentation.
What I would do differently
This post would not be complete if I did not share some of the stranger things I did but won't be doing going forward.
First, I would pull all static content on the site into one file. Currently all the text is sprinkled through out many files which makes it hard to update. It would be waaaay easier to manage and edit if all that text lived in one place.
Secondly, I would have pulled a few more components into their own file. Some component files have 4 components in them. I took this approach because all the supporting components were only used by that primary component. However, it just resulted in really long files and some duplicated code.
Third, I would create a few more folders for organization purposes. Currently all components live in one folder which can make it hard to find the ones with state. Going forward, I will create a
components folder, and a
container folder. Any component with state will go in the
container folder. This leads into my next lesson.
Limit the number of components that contain state. There were a number of times I had trouble finding the component that held state using the react developer tool. I can save a lot of time and frustration if only a handful of components hold the state.
Now that the site is live, I can iterate on it. One improvement I really want to make is using a static site generator. This should reduce the time to load everything on slow networks. I know of a few options but think I will try out React Static.
Secondly, I want to add real time email validation for the contact form. My thought is it should cut down on the number of typos and invalid email submissions. Definitely want to reduce those bounce backs after all!