My Stack.

Published on December 23, 2023

Table of contents

I have talked about the languages, frameworks, databases etc. I use and why I use them from time to time on Twitter but never in a structured way, this article will be a somewhat complete answer to questions around my ‘stack’, and we will be talking about everything; language, framework, ORM, monitors, headphones etc. You do not have to agree with my reasons for picking these things, that is fine, it’s subjective. I spent a larger part of 2023 exploring different areas to figure out what else was out there, what I liked, what I didn’t like, what works for me, what doesn’t etc.

My Stack

When I started writing this article, I was still away from social media trying to survive my school assessments and by the end, I may still be, which means this article might be up for weeks before we get to discuss about it but I would still love to have a discussion around it if you want.

Yes, I am still behind on that planned website redesign too

I have mostly been interested in developer tooling, databases and real-time systems lately so a lot of my choices and preferences may lean towards that.

I may get some things wrong here from my experience with these things but I will try as much as possible to provide accurate information, objective corrections are welcome!

I haven’t really been able to take the time to review this thoroughly and I did not want to keep it in my drafts for too long so, I will be updating this article as I go along - mainly typos and stuff - I will try to keep the updates to a minimum though.

Before we get into all that though, I think it’s only fair I give you a bit more context around what I need, what I think software should be like and all that. The more I explored, the more I ran into BROKEN software, not one or two bugs here and there but broken; whether it be bugs that made them unusable or a UX that did not seem like it was made for actual humans (this discussion is for another article), I started to see a pattern, even in Apple’s software that used to feel very polished, it felt like no one cared about software anymore, everyone wants to ‘ship’ as they call it, no one seems to be willing to put it the work to make their software an experience they’d want to use or they have a really low bar for quality? I don’t know but from most discussions I have had with most of these shippers people on Twitter, it seems to be both.

Yes, I am judging you, I am judging us, I wish we would adopt the work ethics of game developers; IMO, game dev is so hard and requires a lot of discipline, no one is going to buy a game with “This production version works but you know, x just doesn’t work yet, don’t press y because it may delete your save data”, “it isn’t so bad, you just have to do x and y, and x works most times…” or any of such narratives around it. I am guilty of this too, I have written bad software that I am ashamed of, I have written horrible code I would never want to see the light of day so, before I get to write an article on the state of software and how everyone should do better, I need to do better too. I know most of you reading this might have been born in the era of Microsoft Windows where everything was already slow by default (I am not blaming Microsoft, I am saying most of us got “used” to software being slow because the thing we used to run software was MS Windows which was and still is notoriously slow when doing things like just using the file explorer, without using search that is, it is even worse with search), but I have seen fast software, I have used fast software, I know it is possible to make fast software and we should make fast software.

Oh dear, that was… uh, quite the rant, but I promise we are actually getting into this section’s purpose now. To do better, I have decided that for both software meant to be delivered into the hands of users and ones that would never be seen by the user:

These are just summaries, there are a lot more to do and I know they may not make sense to you now, you will understand as we go deeper but a lot of the choices I have made are geared more towards these goals.

Languages

Let’s start with languages; the ones I intend to write often over the next few years. Most people say the choice of language doesn’t matter, same people probably write backends in Javascript so… cough cough… That’s all I will say about that, I think it does for some people and some cases so, I will explain why I have chosen these languages and where I intend to use them.

PHP

”Heavens no, why would anyone write PHP? It’s the worst thing in the universe"

"Okay, maybe it’s Laravel, I think it’s a nice framework that makes PHP usable, I will let it go”

NO, I do not write Laravel, I do not like Laravel, I will never (re-)learn Laravel (or Django, or Rails, or any other meta framework; good for you if you love, live and breathe them), the “why” could be its own article, but not today.

NO, I am also not in denial, PHP has its quirks, a lot of them in fact that calling them just “quirks” is an understatement. I started with PHP 5.2 so believe me, I know, they are only just trying to fix most of them and improve the language now. It was a language born with no design in mind, a loud echo of its C origin, a great example of what happens when you make thinking (as in design considerations) and performance afterthoughts; although thankfully, there are people willing to work full-time to improve it - Thank you!.

As I mentioned, PHP was the first language (proper language, not markup language; I did pick up HTML first but you know we don’t talk about that) I ever picked up, I remember looking at PHP code back in Junior secondary school and thinking I was never going to know that thing, it looked cursed, it looked complex, I wasn’t sure I was smart enough for it. I had to learn a lot through trial and error; I had 25MB plans few times to look up how to do the basics and just ran from there, 00webhost for hosting (by uploading files from an iPod touch I had been gifted, use internet on my computer? are you crazy? - there was so much going on with Microsoft XP - or was it Vista? I cannot remember - and the $hitty network that I was out of mobile data - via USB tethering - before the page even loaded; if the desktop didn’t just freeze that is) and dot.tk for domains, Twitter and Youtube were not in the picture either. I grew to like the language, it allowed me build things I thought of, it earned me my first income (eventually, I could use FileZilla like the rest of you) and still does (Yes, I still write PHP, I still deal with XML from cursed integrations at work that we have to maintain, sigh).

Enough with the sentimental crap, PHP is still a part of my stack because it is still useful to me, I mean, it is not the poster child for performance or consistency but I know it, dare I say, inside-out and it only keeps getting better. I wish the deployment story was a bit smoother in this Docker age but it isn’t and to be honest, it does make me want to write it less for my personal projects since I use Docker a lot. If I needed to build a web app quickly and did not care about over-engineering things as I usually would with my personal projects, I would still go with PHP anyway. Although, I eventually might do something like write a bloody ORM while telling myself “I am not over-engineering, I am just writing utility functions in a class clearly named BaseModel”, you’ve been there, don’t judge me, and that is majorly why I like and use PHP (not only because I am paid to write it), I barely ever need to reach outside the language to get things done in the way I want.

We are able to work on a codebase half as old as I am without a single composer install or even a composer.json file (yes, I am aware composer adds a certain DX, I am telling you it is possible to do without it and we do), the only build system we have is for… you guessed it, the Javascript[1] and CSS (minification and other things) and tailwind is the only reason we have had to even deal with Node recently.

”Well, that only works because you are building toy products, I can do that with Next.js and Prisma, and the thousand other dependencies that come with it too” - Uhm, no, we manage about 8 different codebases that have to integrate with other systems and with our multiple mobile apps, it hasn’t been without its issues like every other legacy system either. And, thank you, our performance is fine :)

[1] because we mainly use jQuery; a remnant of the past which I believe we are slowly migrating from since browsers and modern Javascript are good enough now

Typescript

”Hypocrite, you just bashed Node.js and Javascript”

Calm down, I can explain.

See, Javascript also has a plethora of birth issues like PHP, but unlike PHP, some of these “behaviors” can no longer be fixed because of the way Javascript (the actual thing in the browser, not the… questionable ways to kill your server and maybe a few brain cells) is distributed. Javascript isn’t something you can really install, your browser engine “maker” decides what you get, and when you get it, I can’t go into details on how Javascript/ECMAScript works in this article but think of it this way; it is like your phone’s chip, you are stuck with whatever the manufacturer put in your phone, you do not have a choice (unless you’ve spent too much time on XDA forum and were willing to do things that would make people keep their devices away from you, is it even still around?) and developer also do not have a choice so in some cases they have to ship this thing called a polyfill just to deal with the insanity. This, in turn means, when ECMAScript gets a new release, you have to often consider those new features untouchable for at least the next 5 years unless you:

This also means, making changes to behaviors that developers have either had to work around or depend on for years now would break a large percentage of websites and web apps on the internet today and we will see more screens like this often without Next.js feeding it to us for no reason, beautiful, isn’t it?

Uhm, vercel?

What was I talking about? Oh yeah, the facade.. sorry, language; Typescript. These days, I tend to keep to using Javascript and by extension; Typescript, where it was meant to live - in the browser since it is the only sane (I know, I feel it too, “sane” and “Javascript” in one sentence, oof) way to write interactive front-ends these days and since I like type safety types (better believe we will come back here), choosing Typescript is a no-brainer, it serves as some sort of contract (there are a lot of ifs here but we will skip it).

Okay, right back to the type-safety part, you see, Typescript is just syntactical sugar over Javascript, it simply helps you know what a contract may be, the types do not really have an effect during runtime, you are not getting any special performance benefit from smaller allocations by having more distinct integer types and whatnot. In fact, you could choose to lie to Typescript and in turn blow things up yourself with that lie, so Typescript strongly depends on both sides keeping the contract, but to be fair, not even Rust/Go is immune to something like an API response schema changing right under your feet, it is only worse with TS because you end up exposing that glorious undefined to the user (although some may consider it better than Go’s decision to use defaults and whatever Rust does, I don’t). I am sticking with Typescript because it is better than nothing, that’s it, I want my IDE to help me write less hit-or-miss Javascript where possible; trusting Typescript entirely would be like believing the weather forecast in England and failing to prepare for the opposite, you are most certainly going to regret it.

Go

You probably saw this one coming anyway. I don’t want to spend much time here, you probably already know how I feel about Go too; I hate it and I love it too. Go was the first compiled language I learned and stuck with. Go is just… fine. I have an article coming on why I will be writing less Go and more Rust so, I will try to be concise here.

I have my issues with Go; mainly the fact that the compiler is stupid, tries to make up for it in speed and ends up giving you a program that is most likely to blow up AKA Go is NOT safe and doesn’t try to help you be safe either, but if I ever had to ship a performant API fast, do some networking experiment, make something that had to be self-contained and didn’t need the extra performance Rust might give or work on something for someone, I would use Go. I like a lot about Go and hate a lot about Go but again, not for this article, I care deeply about the things most people don’t care about like image size, and Go’s ability to make self-contained, fast programs is a big plus here (you could argue other languages offer same) especially if it is something I expect people to run themselves, I can shove it in an alpine image or a distroless image depending on the context and have it all be less than 25MB and require no external dependencies.

Go is simple enough to let you pick it up and move fast, you may pay for that later (as you will in any other language if you make poor choices) but it is generally, honestly, a good choice if you can put up with some of its weirdness and be okay with the fact that the makers will/may not give you those convenient things you want or fix any of that weirdness because it doesn’t need fixing to them and that is fine, but I have used other things, I have seen things can be better and I am not fine with it.

Most Go fans will tell you the complains are all due to skill issues, so will fans of any other language, so la la la la la la la la, not listening, fix your $hit, you deserve better, the compiler can and should tell you “oh hey, this might go wrong” because it will always know better than you, your type system shouldn’t force you to reinvent things, you shouldn’t need to use a pointer and a silly nil check to figure out if your user actually sent false or not because your language gave you no choice with the defaults… I will stop here before I step on more toes.

I also do really like Go, it’s allowed me to build things that are fast in a fairly short amount of time and I did not have to learn “too much”, the concurrency model is so good too! I am learning Rust at the moment and if I had to do most of the things I have done in Go in Rust, I would probably find it a tad more difficult to be honest.

Also, my next job may require me to use Go since that is popular for backends these days, and thanks to school, I know I want nothing to do with Java, so yeah, I will write Go from time to time, I still have projects in Go and will continue to write projects in Go when it fits. I do not intend to leave my current part-time/full-time (depending on when you are reading this) job anytime soon, apart from the fact that they took a bet on me (it is very difficult to even get interviews as a student here for dev jobs), I work with genuinely nice people, it is a perhaps more than average pay for the UK, but overall, I still have so much to learn from my boss, a bit more beard hair (and grey ones) and he may fit into that graybeard stereotype, I learn SO much from a 20-minute discussion about everything ranging from servers to networking to LINUX to you-name-it than I would sitting in a uni class for 4 hours every week. And apart from all that, it has had a great impact on my social life going in to an office to work with people, I have been pulled to multiple outings and parties in my short time here and out of my natural habitat; a computer workspace, and honestly it has been a great experience, I have spent and still spend a lot of my time indoors working; I spend way more time talking in my head and on Twitter than in the real world.

Gleam

Gleam is a language that runs on the BEAM VM (yes, same one used by Erlang, it does actually compile down to Erlang, it is sort of like the Typescript of BEAM world but better), it can also run in a Javascript runtime, but I don’t really care about that so I will be pretending that part doesn’t exist. You can read more on why I ran with Gleam instead of Erlang itself or Elixir here, but to keep this short, I like Gleam, I like the community, functional programming has been awesome to explore and I like it too, I will be using Gleam for real-time backends and APIs for my personal projects (I doubt I will get to use it anywhere else for a long while), that is what it shines at (although Elixir getting real types might make me have a second look at it).

Yes, I could also use Go for realtime stuff, in fact, you could use almost anything for a realtime backend, I mean, see this, people will do anything given the chance to and don’t get me wrong, it is good that people explore other possibilities. But, Erlang and its VM were made for this very purpose, they were made to be fault tolerant and handle tons of concurrent connections and tasks, of course, they are not suitable for memory or performance-intensive tasks but they can easily be augmented, and Elixir has clearly served Discord well, a few issues here and there but thanks to the fact that the VM play nice with other lower level languages via NIFs, they could be fixed without even thinking about a rewrite.

Gleam is still in its early stages but since it stands on the shoulders of giants and plays nice with those giants, I can always reach into Erlang for missing functionalities and I do in fact enjoy it. I currently maintain a few libraries in the Gleam ecosystem and intend to spend a long time writing Gleam for years to come even if it is scoped to my own personal explorations and projects, I also like a lot of the decisions they have made around the syntax, type system and error handling; the similarity to Rust is a big plus for some people like myself.

Gleam code sample

You can have an HTTP server right next to your CRON job runner and Websocket server and be confident that one of them crashing will not bring the others down with it, in fact, you do not need to care about that crash (unless when you need to), the processes will be restarted as necessary, the whole VM is designed to chug along, one process dying will not cause your entire system to crash (in a language like Go, a panic in what’s essentially the equivalence of a BEAM process; a goroutine, would take down the whole service if recover() isn’t used for that specific goroutine and even that is nuanced). A process in this context is not a real OS process, making it even cheaper to spawn and kill processes as needed! Need to send messages from one process to another? You’ve got it! Want to spawn a task and “await” the result in the calling process? Easy. Dare I say Go’s concurrency model was inspired by the BEAM, they are similar and both a joy to use.

”But you can just crash the whole thing and let Docker restart them for you” - sigh, please no, and you clearly do not see the value here.

I may leave Gleam behind in the nearest future since Elixir appears to be getting types too and it isn’t held back by its desire to compile to WASM or Javascript which in turn means it can do more things native to the BEAM VM out of the box (like you can literally type Erlang in Elixir fine), but for now, I am sticking with Gleam.

Rust

Rust is definitely hard to learn right but I also understand a lot of the problems it is trying to solve (no thanks to the several nil dereference panics in Go). Rust is not perfect either and I will talk about some of its issues in the article where I explain why I will be writing less Go and more Rust. For starters, Rust is less flexible in a way, so it is out of the question for most web backends I would work on; Gleam, Go or PHP would do fine there depending on the context. I am picking up and sticking with Rust for more lower level things that I intend to explore and do more; majorly dev tools and database explorations. Rust’s Tauri is also really good and a good option for me to write desktop apps when I need to.

I have some C++ experience from uni but since I probably write worse C++ than your Javascript and can’t (and don’t) want to use CMake, Rust is a perfect choice for me (V language in theory was but they keep dropping the ball hard, the syntax is almost unrecognizable the last time I checked, there are now multiple versions of if and other things like $if, the syntax for macros or whatever they are is just [stuff, "another stuff"] and they are too busy building things into and around the language to sell it instead of focusing on stability etc.), I like the ergonomics, I know most people find it cumbersome, and I may in the future but for now, I am pleased with it and its helpful compiler (Go, feel free to pick some inspiration here) that would most certainly produce a binary that doesn’t crash because of something that could have been fixed before it ever made it in past compilation. Rust being without a garbage collector makes it suitable for more things that Go isn’t, like making high-performance databases, other languages etc, the type system behaves as a real part of the language, the meta programming features are really nice too, it allows you to do cool and convenient things like Axum’s route extractor, rspc (the developer experience you get here makes me want to use Rust for APIs even, haha), or Serde etc. significantly better than having to use struct tags and weird reflection stuff in Go.

Rust is lacking some things in its standard library unlike Go and you often have to choose between multiple options even when it comes to things like what async runtime to use but I am willing to cope with these, the benefits outweigh the nuances for me. Pattern matching is also a joy to use in any language, it feels like it should be in every language but sadly it is not, I have tasted it in Rust, Gleam and Elixir and I cannot go back now (Go, take more notes here).

Frameworks and libraries

There isn’t much to talk about here, the language matters more for me but here you go.

Solid.js (Typescript)

“Wait, are you nuts? not React?”

Nope, not react. React has a very rich ecosystem that it is tempting to just stay there but I strive for simplicity and performance, React is neither. Hell, there is a YC-backed startup dedicated to helping you fix React issues (how long till we get one for Go too? they belong in the same basket, haha). React got me my start with modern frontend stuff but lately I have been okay with just using Astro for static stuff with a bit of interactivity; like this website and Solid.js for other things. Apart from the frequent drama in the React, Next.js and Vercel “ecosystem” that is enough to put anyone off, Solid genuinely does have enough appeal on its own for me.

It’s done away with the virtual DOM, not that I care much about that, what I do care about is the effect this has on the framework itself; Solid.js, as I understand it, is able to be more performant since it doesn’t need to keep a version of the current DOM in memory to diff on state changes, that combined with its choice to use signals (and their obvious dedication to performance-first) has made Solid.js pretty fast by default!

To be fair, React opened the door for a lot of newer frameworks and I am thankful for that, JSX is quite nice to work with, I like it, happy for you or sorry it happened if you don’t.

Solid.js also has a lot of first-party libraries and components that are guaranteed to retain that performance and also reduce the package choice fatigue, it is also similar to React enough that it is not that hard for any React user like myself to pick up.

Remember I am not trying to convince you to use Solid.js, I know people get defensive about their frameworks, I am also aware there are a lot of frameworks out here, explore and make your own decisions, this is mine.

Axum (Rust)

I don’t have much to say now, it looks nice, it is made by the same folks that made the most popular Rust async runtime, performance should not be a problem. Extractors are really nice too, but I haven’t used it enough to say a lot about it, I also don’t intend to do a lot of APIs in Rust anyway.

Wisp (Gleam)

This is less of a framework and more of a collection of convenient functions, nice to have, it is also maintained by the creator of Gleam.

Chi router (Go)

Nice APIs, good performance, no opinions.

Echo framework (Go)

Also, nice APIs, good performance, great for real projects where I don’t want to roll a lot of my own stuff.

There you go, I don’t have much opinions about libraries or frameworks, I try to do my own stuff when I can anyway.

ORMs/Database access stuff

Just like the previous section, I don’t have a lot of opinions here too (unless you mention Prisma, I have plenty of opinions like: USE SOMETHING ELSE)

Databases

Now, this part is also pretty generic, but it also depends on what the application needs.

SQLite

SQLite is just a good fit for smaller side projects and things like desktop and mobile apps that I have had to do recently, and thanks to LiteFS and Litestream, accessing it outside one instance and backups are not really an issue anymore.

MySQL & PostgreSQL

I have very limited experience with Postgres but I have worked with MySQL for years now but to be honest, I have only really dug into both more recently. MySQL has gotten a lot of updates in recent years and performance boost but Postgres objectively can do more since it is more of a hybrid too (object-relational like Oracle12c) which is really nice but I am not picking one over the other because again, it depends on whatever the application needs (more reads? more writes? etc.). Although, it appears most people may not have to make that choice anyway since most managed services are for Postgres these days.

I think that is it for the code part, ping me if there is anything I should have included

Editor

You have probably noticed by now, I use Neovim mainly. I say mainly because, from time to time, I have to shell out to VS Code when I am testing an unsupported language (most languages try to support VS Code first) like V and, initially, Gleam, and at work, I use PHPStorm, not because everyone else uses PHPStorm but because Windows is so cursed that setting up my Neovim setup on it was a hassle and I only have Vim on there instead, this would have been okay and I could just use some FTP stuff later but it is so slow (the Windows terminal) that I don’t bother to use it and I found no way to get Wezterm to use bash on Windows instead of whatever the hell it was using. I still use it from time to time when PHPStorm decides to take the whole day (obviously an hyperbole, but truly a long time) just to index stuff because I simply switched branches and prevents me from working.

My preferred terminal is Wezterm since it supports everything I use right now, I like that it is customizable and the key bindings + panes are a blessing (nice that it uses lua too). I am still waiting to try out Ghostty, I will see if I will switch them but this setup has served me nicely for over a year now. I did try Alacritty, it had some weirdness going on and I did not bother with it, I used iTerm2 for a while but again, it also had some weirdness going on that I just didn’t like, they both broke my fonts and looked odd in full screen.

EDIT: I got access to Ghostty a couple of days ago and I may switch, I still need to set it up to match my current Wezterm setup but I haven’t had the time to do that yet since I have to dig through the source code to figure out how to do some things in the config file (which is plain text, not Lua).

Monitor(s), Keyboard and other stuff

My Setup

There are links to some of the things I mention here

I use a dual 24” Huawei monitor setup and for over 2 years, it’s been fine, I have looked at other monitors and even considered an ultrawide but this feels just right to me. I prefer a dual monitor setup because I prefer having two distinct “desktops”, I know you can get close to this with something like Rectangle but I like full screen as you can see, hitting Option + B (via Zap) to go to my browser affects nothing else, my terminal doesn’t suddenly move or get minimized, other things like Discord, Arc, Spotify etc that are not for writing code live in the left monitor.

I use a 2021 14” MacBook Pro (M1 Pro) and that’s also been… fine, except for storage (my next laptop, perhaps in 2025?, would certainly not be 512GB). I have to run a Windows emulator sometimes for things like the Braid game because it won’t run on my Mac natively (via Steam) or for accessing the Oracle Database server from home (I also don’t know why this is broken on my Mac at home only but it works in the VM so…)

Oh, I own an Apple HomePod mini that works like 30% of the time - great job Apple, I thought you could do better than the Google Nest, at least that one had Bluetooth

I have a pretty unpopular dock from Anker that supports DisplayLink because that is the only way to run both monitors with one cable on newer MacBooks - again, great job Apple, now I can’t use Amazon Prime on my laptop because it thinks I am screen-sharing.

I have a Raspberry Pi 4 (8GB RAM) with a case from DeskPi and a 512GB SSD from SanDisk that serves as a tiny home server to test things on and also media storage.

My keyboard of choice is the Keychron K2 V2; aluminum build, full RGB and hot-swappable with Brown switches, I did not even know I got the highest spec until it arrived but whatever, it is a nice keyboard! I pair that with a Logitech MX Master 3 (I believe).

The reMarkable 2 is my recent attempt at getting into more reading and writing, quite pricey and has lesser features and storage than the Amazon Kindle Scribe so to be honest, this was purely based on design, it just looks and feels so good, not sure I would recommend it to other people over the Scribe though, the Kindle store integration alone is better than having to buy books on ebooks.com.

I also use the AirPods Max as my preferred headphones at work and AirPods Pro (2nd generation) when I am not at work; so, not often. Most people say it sounds like crap compared to Sony’s headphones but I don’t know, I tried about 2-3 Sony headphones and I couldn’t quite stick with them (last was the XM3 I believe), they didn’t sound bad but these also do not sound bad to me.

Apps

Dock

I use certain apps often on my computer and phone, here’s a short list:

I will probably update this article with edits if I change my mind on any of these things

Edit this page on Github

Disclaimer: This article represents my own opinions and experiences at the time of writing this articles. These opinions may change over time and my experiences could be different from yours, if you find anything that is objectively incorrect or that you need to discuss further, please contact me via any of the links in the header section of this website's homepage.