The Complete Toolset to Build a Website
Posted on February 4, 2023 • 7 minutes • 1384 words
Table of contents
All the Moving Parts of a Website
There is a lot that goes into making a full-stack website and deploying it so that it can be used by the intended audience. This goes beyond just the choice of programming languages on the frontend and on the backend. There are other questions that must be answered as well: Which database should I use? Where should I host my backend? Where should I host the frontend?
I’ve made a handful of full-stack applications, and these are projects that cost me nothing (or very little) to keep up and running, and they are what I use from project to project so that I get up and running quickly. I’ll go through the tools starting from the backend, then going all the way to the frontend. Keep in mind that some tools really are more suited to some tasks better than others, and this list is just my “defaults” that I go to if I don’t need to accommodate any weirder-than-usual use-cases.
Git Repository Host: GitLab
- Choice: GitLab
- Website: https://gitlab.com/
- Cost: 0$ for your projects and access to shared CI/CD runners
To start off, let’s decide on where to put the code when you start writing it. GitLab would be where I would host my code. The main reason being the CI/CD offering. I find it very easy to work with their setup, and I find it to be very powerful. It’s also free to start experimenting with it for all your small scale projects. While GitHub is also good, I find their CI/CD offering, GitHub Actions, to be less intuitive for me, and so here I’ll stick with GitLab.
Database: MongoDB
- Choice: MongoDB
- Website: https://www.mongodb.com/atlas
- Cost: 0$ for the first 500mb
Now, let’s decide on the database. I’ll go for MongoDB Atlas. I’ve grown to like non-relational databases for applications that have the “usual” CRUD operations. Document databases are simple to think about and are sufficient for almost all the use-cases I usually need. If I had an analytics heavy product, I would consider a relational DB, but otherwise I would stick to non-relational.
Backend Language: Go
- Choice: Go
- Website: https://go.dev/
Let’s move on to the choice of the backend language. I’ll pickup Go for a couple of reasons. Having the language be typed is a must for me. I particularly enjoy a structurally typed style (if you’re familiar with TypeScript, that is a structurally typed language), and while Go is not exactly structurally typed, it does have a handful of elements that are, so that’s a plus. Go also compiles to a single binary that can run anywhere, which makes deployments a bit easier than what I would have got if I used TypeScript via NodeJS. There are also the performance arguments when compared to NodeJS. For me, a good compilation process, a rich ecosystem for programming servers, a great type system that’s not too complicated, and support from cloud vendors is enough for me to pick up Go over the alternatives.
Server Hosting: AWS Lambda
- Choice: AWS Lambda
- Website: https://aws.amazon.com/lambda/
- Cost: 0$ for a good free tier
I choose to go serverless with AWS Lambda. The backend code remains a monolith, though. There is a danger of over complicating things when doing serverless, so here’s my setup. I architect my project following the clean architecture methodology. This keeps all my business logic in one place, and the whole app is still in the same codebase. By doing it this way, I can now expose each use-case in my application as a separate endpoint. When done right, the compiled code for each endpoint will still be small regardless of the size of the codebase since Go only compiles the code that is used, and does not include anything that isn’t used in the final build. This will result in a small binary file per endpoint, which can then be deployed to AWS Lambda.
This has a handful of benefits. First, the code itself is not more complex due to serverless. The codebase is still a monolith and it’s all in one place, and methods can call each other in the code, not via a network call. Second, we can leverage AWS Lambda’s free tier, meaning if this project is not getting any traffic, it will cost nothing. Third, if this project does get traction and becomes popular, AWS Lambda scales easily, so no need to panic when that happens.
Here is where GitLab’s CI/CD also comes into place. The number of endpoints will quickly grow, and they definitely should not be managed manually. It is imperative to setup a way to automatically deploy these functions. For this, you can make use of the Serverless Framework to deploy all your functions when you push a new branch.
I’m still experimenting with server hosting and serverless, but so far, AWS Lambda works nicely. From what I’m seeing, AWS, GCP, and Azure are at the top for a reason, they’re just too mature compared to other vendors when it comes to serverless, and I’ll likely be sticking to one of them.
Web Framework: React
- Choice: React (in TypeScript)
- Website: https://reactjs.org/
Ah the web landscape. There really is a number of choices here, and all are pretty good. I’ll stick with React because I know it well, but feel free to just search “best frontend web frameworks” and pick any from the top ones you find. Make sure to choose a modern one that’s being updated regularly and has a good ecosystem of developers working with it. For me, I usually kick-off the project with Vite
and I use the react-ts
variant. This quickly gets me started with a React app in TypeScript that’s just ready to go.
The usual packages that come along from project to project are React Query , and a design system library. The design system library will take care of theming the usual UI components, and it will allow for easy theme customizations. I usually go for Chakra or Ant Design .
Website Hosting: CloudFlare Pages
- Choice: CloudFlare Pages
- Website: https://pages.cloudflare.com/
- Cost: 0$ free tier
You’re almost there! Now we need to expose the frontend to the world. I like to do this with CloudFlare Pages. There are a bunch of reasons. It integrates with GitLab very nicely and you can start seeing your website quickly by just configuring on CloudFlare which branch in GitLab is your main branch. You can also have URLs for the non-main branches, and this way you can see previews of your changes while you’re developing. Overall this is really awesome, really fast, and works really well.
Mobile Framework: Flutter
- Choice: Flutter
- Website: https://flutter.dev/
As a bonus section, this is what I use if I wanted to make a mobile app as well. I find Flutter to be a very clean framework. It’s pretty feature rich, and most importantly for me, it compiles cross platform. Say what you will about the performance of a native application and how it is better than an application built with a cross-platform framework, when you are small scale, you do not want to develop anything twice. In my experience, the performance of modern cross-platform frameworks is sufficient, and I do not fuss about this aspect of it. The benefit of not having to develop the app twice far exceeds any performance argument in my book. Of course, this is assuming the app is not making heavy use of specific platform functionalities that need performance (like a VR app, for example).
Mobile App Hosting
Ok, I’m just kidding. There’s not much of a choice here. You pretty much have to be on the Google Play Store and the Apple App Store .
Conclusion
So that was a lot of choices, and these will get you set up nicely for most digital products. Now I do have to mention that these are not all of them either. At every step of the way, you might need something extra. For example, what about caching on the backend before querying MongoDB? Or what about analytics for visibility on the various systems? These questions also have their own choice of tools, but these tools should come down the line as the needs arise. For now, the tools mentioned above are enough to get most digital products off the ground.