My Tech Stack...
And why you probably should not use it
Published: 2022-03-19
tl;dr I often utilize Golang, Firebase, Svelte, and Tailwind CSS. But there are significant caveats and good reasons you probably donāt want to follow my lead.
In the developer community, especially amongst āfull-stackā devs, there is a culture of having a curated list of technologies that one uses to build an application from top to bottom. This is particularly true for web applications due to the myriad of options for each stack layer. Some combinations rose in popularity amongst boot camps and self-directed courses, for example, MEAN/MERN/MEVN ā MongoDB, Express, Angular/React/Vue, NodeJS. This acronym conveys that a project uses NodeJS on the backend, with MongoDB as the database, Express as the middleware and API router, and Angular/React as the frontend framework. Just as frontend frameworks and languages by themselves cause spirited debates (read: flame wars), so too does the preference in a stack. I donāt participate in such unending debates (except to troll those who take themselves too seriously), but I figured Iād share what my tech stack looks like and explain some of my reasoning. I do not hope to convince readers to employ my combination of tools ā in fact, for many of my choices, Iāll be arguing that you probably should not make the same decision. If there is one thing I do hope readers will take from this, it would be:
remember that the choice of language, framework, or stack āis not the thingā¦ itās the thing that gets you to the thingā (to paraphrase Joe MacMillan). As software developers, our job is to build and create - to solve problems. Our job is not to bicker endlessly about tools.
Anyway, that is enough preamble. Letās start at the top of my stack and work downwards.
Frontend: Svelte, TypeScript, Tailwind
Svelte?! How? Why?
About eight months ago, I set out to pick a frontend framework. Iām almost exclusively a backend
engineer by profession, but side projects were mounting that needed a web interface which meant I
needed to expand my skillset. As I evaluated frontend frameworks, I had specific criteria. Of paramount
importance was a gentle learning curve. I should be able to get up and running with a framework in
hours. This criterion immediately eliminated Agular from contention. I also wanted a pretty opinionated
framework without feeling too restricted ā I didnāt want to make every nitty-gritty decision.
I would much rather lean on the expertise of the framework builders, at least in the initial stages
of the project. Decision paralysis was a big worry for me, especially with the JS ecosystem having
dozens of third-party libraries for anything you could want. This requirement is best summarized
as āsensible defaults.ā I also didnāt want to feel like I was writing (too much)
JavaScript. I canāt expound on my feelings around this too much, except to say that Svelte
and Vue felt like they met this stipulation, while React did not. I guess you could say I didnāt
want to write JSX? I also cared about bundle size and load times as I knew that some of my projects
would have users in locations with slow internet speeds and data limits. I also needed a framework
with an active community. Note that I said active and not large. This
condition ensures that if I need a library, I can likely find one (no need for a dozen options),
and I can get help if I need it. I came across some of Rich Harrisā talks during the
evaluation, including
Rethinking Reactivity
and
The Return of āWrite Less, Do Moreā. His philosophy resonated with me. Svelte had the quickest learning curve, and the
docs/tutorials are excellent. The community is vibrant; whenever I run into a problem, I simply
hop into the discord. I like the magic add-ons provided in its HTMLX template. It feels
effortless to be productive with less code.
SvelteKit
is in active development and shaping up nicely.
Does this mean Iād recommend anyone else learn/adopt Svelte? Nope. I am not here to give recommendations,
and I donāt know what your situation is. I am privileged not to have my income tied to my choice
of framework. I donāt have to care about the job prospects for a given framework. I also donāt
have to worry about if the framework gels well with a large production team. At most, three people
will work on my web app. You may have some of these (or other) considerations.
Moving on. TypeScript. I donāt think much needs to be said here. Itās 2022. If youāre not using
TypeScript, then why not? I set up my SvelteKit projects with TypeScript by default. The
interesting thing is that there is still JS in my frontend code. Typically, if the logic I am
writing is small and bound to the given svelte component, that will start as JS, and Iāll
convert it to TS if I think Iām doing something interesting in that script. If some logic
is abstracted away from components to a separate file, that will be .ts
instead of
.js
. Iām not saying this is correct. But it gives me a decent balance between
safety and productivity.
Tailwind CSS. A few years back, when I first learned frontend development, I incorporated Bootstrap after learning HTML/CSS/JS. It was suitable for prototyping, but I found it hard to create a site that I would consider beautiful. Worse, I would visit other websites, think, āHey, this site looks like mine,ā and realize they are also using Bootstrap. In search of something new, I found Tailwind CSS. Instead of components, it provides utility classes for CSS, which you can compose however you like. Itās like building with Legos. Especially when combined with hot reload, you can supercharge your productivity. And itās responsive by design. Tailwind is non-negotiable in my stack. If you havenāt tried it, I highly recommend that you do. If you have tried and donāt like it, thatās fine; there are many other options.
Backend: Golang/Python
My default is to use Go (AKA Golang) unless thereās some library I need that is only in Python, or Iām collaborating with others, and they know Python, not Go. Go is well suited for web servers and CLIs. It is fast, (cross) compiles to small binaries, built with concurrency in mind, simple, opinionated, explicit, readable. I often think that if C and Python had a baby, it would be Go. Am I suggesting that you swap whatever you were using in your backend for Go? Nope. I do think you should learn (or at least try) Go. But if you have a web app to build and already know another backend language/framework, like NodeJS or Django, you have to decide if you want to learn a new language for that project and do whatever pros/cons calculus is required.
Infrastructure: Firebase/CloudRun/FaaS/ā¦
Last but certainly not least, we should talk about infrastructure: where/how my projects run.
āWait, you forgot to talk about databases!ā you may be yelling. Relax. I am getting
there. The truth is that I donāt have a strong preference for any particular database.
What I use usually depends on my use-case complexity and where Iām running my app since I
like tight coupling between my database and other areas, like auth. When I was first learning
full-stack development, the default was to use Firebase
as it is the premier BaaS (backend as a Service). It has a comprehensive set of technologies that
allow developers to get up and running quickly. Over time, Firebase appears to have stagnated (or
stabilized, depending on your PoV). In that time, new options, such as
Supabase, have
emerged. However, Firebaseās functionality is so complete that itās still a solid
option today. Given I have built up knowledge in Firebase, I often still turn to it, and they
have great SDKs for each platform. Of course, if Iām using Firebase, my database ends up
being Firestore.
Google Cloud Run
is excellent at running your workloads/business logic. I often pair it with Firebase since they play
well together. You give Cloud Run a container, and it takes care of the rest. It is probably my favorite
product in GCP. Since many of my workloads run in containers, I get to take advantage of Golangās
small build size. For example, an app of ~13 MB in Golang took 100s of MB in other languages (usually
due to the need to ship a runtime).
Sometimes, Iāll use a FaaS (Functions as a Service), especially if using Python. For example,
GCP functions or (more likely) Azure functions. Again, GCP Functions can go with Firebase. There
is also Firebase Functions, but that only supports NodeJS. If Iām using Azure functions, my
database will be
Table Storage. That is, if my use-case isnāt too complex and I donāt anticipate crazy levels or
reads/writes/queries for which Azure Table Storage is not intended (hint: this is never an issue
for a side project). If the use-case warrants something more robust/relational, I may opt for a
MySQL database. Iāll opt for
Azure Container Instances
for some projects, but usually not as the backend for a full-stack app.
Should you be doing any of this? Probably not. I use GCP and Azure because Iām a cloud engineer
and have worked on these products. Given some requirements, I can tell what combination of cloud
infrastructure satisfies those requirements. I like thinking of infra. You probably donāt,
and thereās no need. Firebase is a solid option. So is Supabase. As is
Vercel
and Netlify.
PlanetScale
is an excellent default for a database.
Railway provides great
serverless infrastructure. Try them out if youād like. They all have generous free tiers.
Thanks for reading. Hopefully, you found it intriguing yet non-prescriptive. If I were to use only my preferred defaults, I would call this stack TGFS - Tailwind, Go, Firebase, Svelte. Not particularly catchy, is it? If you like it can also mean āThank God For Svelteā.