this is a personal portfolio in development
maybe come back later :D
this is a personal portfolio in development
maybe come back later :D
TBD
TBD
TBD
TBD
TBD
TBD
TBD
TBD
TBD
TBD
TBD
TBD
TBD
TBD
TBD
TBD
TBD
TBD
TBD
TBD
TBD
TBD
TBD
TBD
TBD
TBD
Hello again, I guess.
TBD
TBD
TBD
TBD
I like python a lot, it has a special place in my heart, even though professionally I haven't had much opportunity to use it.
The first time I came across python, it was at the start of my career when I was developing for this quirky aquatic drone project (I loved this project) and the internal logic of the beast was this messy collection of python scripts, they did a range of things from measuring battery information to controlling the motors, it was a lovely mess really...
For context, this aquatic drone was pretty much a Raspberry Pi board with some extra "stuff".
The control application itself was this unity3d app (don't ask, we don't have time) codded in c# (at the time Mono, not .NET). So you can understand how python felt like a new world to me at the time, going from this static typed boilerplate heavy language like c# to this dynamic typed language like python. I was already starting to get exhausted from C# at the time so it felt refreshing to be able to use python.
Where I've worked extensively with Python is my personal hobbies, here are some examples
A further one of the RCON stuff, I have worked a lot with RCON recently, in fact if you scroll down the valve docs you will see 2 golang projects of mine
I started with python, got a base understanding of TCP and then made the crossing to golang. I don't think I could have learned how RCON works in any other language
First time I heard about Go was when I was working on some data analytics stuff for a hobby project and I remember seeing a recommendation somewhere to use Go instead of Python.
I don't remember the details of this recommendation. But this is where I first heard about it — I was told it was similar to Python but never really touched it at that time, probably because of Google's association with product graveyards...
Then in 2024 I started working at this company and they were pretty heavy on Go for some backend services and all of them ran on Kubernetes clusters. This was great for me as I could use this to expand both my Go proficiency and Kubernetes skills.
The work I did at this company was the usual stuff you find: Go backend services, containerized, running on Kubernetes clusters. Kafka consumers, Sarama, etc. I got comfortable with it all over time. What I'm more interested in writing here though is my personal experience with Go. To start, I dove into the Go website and found their Effective Go page, which I promptly downloaded to my Kobo e-reader. I had a blast reading it, and I'm not one to have a lot of fun reading this type of literature.
I made it a personal rule that I'd only start developing personal Go projects after finishing reading this little book, but to be fair it wasn't that much of a challenge — just 54 pages. I immediately fell in love with the concurrency model and the interface-based design. My first personal project was this CLI tool I use for generating random tokens.
During this initial phase I was also interested in how backend services such as a REST API would look like in Go, so I ported my dotpen-api to Go as gopen-api. I was very happy with the result. Maybe I should have done something custom (like I am in this ufolio) instead of adding go-chi as a dependency.
One thing I was thinking about while reading Effective Go was how good its concurrency model would be for some stuff I had been doing in Python — i.e., the RCON stuff — so I became fixated with writing my own RCON client in Go. But I had to start small because I didn't really know that much about TCP sockets. I knew the peripheral stuff necessary for working with it in Python, but not enough to do it all myself. So I swallowed my pride and took that Primeagen course on boot.dev, which actually taught me what I wanted to know: byte handling, packet building, IO buffering, encoding, etc. In retrospect, none of this was really complicated — easy even — but in my mind it was a blocker I had to clear.
My first personal real deliverable was my tcprcon low-level, zero-dependency RCON client library, which I now have linked on the Valve RCON official docs. After solidifying that, I started working on tcprcon-cli (a CLI app on top of tcprcon), which also got me more familiar with termios and the Go module system. I wanted to write this without dependencies as well, but caved in and installed `golang.org/x/term` and `golang.org/x/sys`, which are Go standard modules, just not part of the standard library itself.
I am very proud of this app, it's one of my personal projects that I use the most frequently. After this, of note, I did use this on a bot I wrote for a game server, that marries RCON events to some custom ELO ranking system and presents them neatly, but that honestly is not as interesting as the library and the cli themselves, as it is just a wrapper around discord api and this library I developed. Please check them out:
aight I've been doing nodejs for like a whole long time, my first "confrontation" was around 2018, when i started doing frontend work with React in parallel with some backend as well, more specifically this backend framework called loopback which at the time was very jarring for me since I came from a dotnet background.
My experience with nodejs has been mostly fullstack development: frontend, backend, some tool development (I do like commander.js) here and there...
Personally tho, these days I don't really enjoy nodejs that much, I do wonder if I ever liked it to be honest. Everytime I think of doing anything in nodejs I start thinking about that disjointed package management system, I start thinking about the type system (or the lack of it), I start thinking so much I start getting a migraine and then ask myself: do I really need nodejs for this? Usually I do to be honest, especially at work, for many reasons, one of which being the overwhelming ecosystem around nodejs. But for personal projects where it's just me my hopes and dreams I stick to golang and python.
I have been looking forward to Deno and Bun, their package management seems more to my liking but I haven't really found the time to get invested.
I have a love-hate relationship with typescript...
When I first encountered it, I was skeptical. It was on this backoffice React app which I had started with plain JS. I'll get more into it in the React section.
Our tech lead one day started talking about typescript I was like "what? why? are you just trying to make it look like C#? You know this is a different language right?", yes young me a professional mountain climber and I had just conquered that Mount Stupid peak.
But I wasn't that dumb, eventually I got it, because when I started migrating the code to typescript I came across a bunch of errors which initially - I'll be honest here - I was very complacent about, I was thinking it was just the type cheker being annoying... And well, it was that, but it had good reasons to be annoying. I don't ever want to go back to the way we used to do React PropTypes. If there's one thing I hate, it's when we reinvent language or runtime features in library scopes.
I feel very confident with TypeScript these days, but my opinion of it, or rather of its use, has suffered. I feel that often teams naively adopt TypeScript without understanding the responsibilities it comes with. It is not a silver bullet — you gotta buy into the type system to get the benefits it provides, otherwise it's just a cancerous lump of boilerplate in your codebase.
Inversely, I feel that a lot of teams seem to over-buy into TypeScript and forget that the reason why we are using TypeScript is to solve a type safety problem. Our users don't really care about how smart our interfaces and type unions are. I think we need to ask ourselves more often: is TypeScript serving us or are we serving TypeScript? I will leave you with this piece of comedy:
Here's the thing, I didn't go to college, I mean did, kinda, but not really, long story. But the point is I didn't really learn programming in the traditional path.
I went this professional course thing, offered by state to unemployed people, it's one of these state programs right. It wasn't very good, but it was my first real programming experience. And it was all with C# and .NET, but all of it under the ugliness of Windows Forms.
Early on my experience with C# was very OOP heavy as .NET development tended to be at the time. After the course I started working with Unity3d, not game development, not that fun. Mobile apps really, augmented reality stuff was a buzz back in 2016-2020.
My tenure with C# around these years peaked when I developed this whole tour guide app, was pretty neat really, you had augmented reality features in it, imagine a pokemon go app but instead of catching pokemons you are catching points of interest
I like the language, I like how structured everything is to the point where it can be hard for you to break things too hard, the compiler will be there for you. I do miss working with LINQ, especially in NODEJS. The heavy focus on OOP though is something that will always give me pause.
These days it is hard for me to fit C# into my daily work, even in my hobby projects it is quite awkward. To me it is a bit like Angular, it works, but it requires a certain level of commitment and discipline that honestly I'm not willing to provide. Last time I worked with C# they microsoft had just introduced top level statements and this solved a lot of my pains with C# to be honest, I still don't like the domain driven development and boilerplate and the solution files and the csprojs, but if I have a place in my heart for a language like this, let it be C# and not java.
I do have a softspot for functional stuff, very curious about Perl and Lua, probably next on my list to learn. Right now I'm in my honeymoon phase with golang, let's see how it goes.
There is this one game called Mordhau that I have played a lot, before this game - I'll be honest chief - my technical interest in these multiplayer games was scant if non-existent. I mean I did know how to setup a minecraft server and everything but beyond that I didn't really care, I remember seeing people with these complicated softwares open where they managed the stuff but it all felt like too much to me, as in too much commitment. The closest I ever got to this technical side was handling some hamachi lan groups back in the day, but this was really just routing connections, not so much on the management side.
Around the start of 2024 I got engaged in Mordhau game server management, and this is when I started seriously dealing with RCON. My first experience here was setting up some basic management tooling on a discord server. RCON knowledge was a requirement here so I started getting acquainted with this software called Simple SourceDS RCON.
I wasn't a big fan of this software, and I felt like I could do better - foreshadowing - but let's move on. My first project of this sort was something called Tailwagger.
This was a simple RCON client bot that served as bridge between discord and the game server. This allowed the game server to have a richer presence in discord. We are talking about things like a local server status display, player management, and automated server maintenance.
After this initial poodle-deep dive into RCON and discord APIs I began working on greater gameification aspects such as dynamic titles, player achievements, and other immersive game experiences I could implement via RCON. This is when I started feeling the limitation of my own tcp understanding.
As I began needing greater throughput I found out that a single connection wouldn't scale well, since each command sent over the connection would block until it was acknowledged. My first solution was to adopt an ephemeral connections strategy. This works well until you require handling dozens of concurrent connections, as when you have a large number of players triggering operations simultaneously you risk overloading either the server or the client, in my case it seemed like the high rate of connection churn (opening and closing connections) was the culprit.
Here I had to go back to the basics, as this was in fact a basic network problem. I ended up on connection pooling. With connection pooling, I was able to reuse connections across requests, reducing the overhead of opening and closing connections. The way this "reuse" differs from what I initially had - as in one connection I kept reusing - is that now I have a dynamic number of staged connections (the pool) that can scale up and down reactively to demand.
For this I needed greater contact with asyncio (the async lib I was using at the time, because python doesn't have a native one for whatever reason), two things especially:
Ah! At this point I needed some greater control of the connections themselves so I ended up abandoning the library I was using and implemented my own - although heavily copied from that library - solution. One of the main changes I did was replacing the socket (native python lib) usage with asyncio.StreamReader/Writer for greater asyncio compatibility. For event streaming I used python's reactive extensions library (reactivex), which is something I hadn't used since my C# days some years back.
Along the way I ran into some of asyncio's sharper edges. The first was task garbage collection: asyncio.create_task only keeps a weak reference to the task on the loop, so if you don't hold a reference to it yourself somewhere, the task can just vanish mid-execution with no error - a nasty thing to debug when it's a background job managing a live connection. The second was event-loop binding: primitives like asyncio.Lock and asyncio.Queue attach themselves to whatever loop happens to be running at the moment they're constructed, so creating one too early - before the real event loop was up and running - would blow up with an "attached to a different loop" error.
Don't get me wrong, I still like Python, and asyncio did what it could - but the async model wasn't great. I was, in fact, juggling three systems at once just to accomplish my goals:
Coincidentally, I had just gotten acquainted with Golang at work, and its feature-complete async model was exactly what I needed.
This time I wanted to do it right, as in, no skipped steps. So, I was familiar enough with networking matters that I didn't have to spend a lot of time down a rabbit hole - OSI models and classic network paradigms were a heavy component of my initial training in the industry. Heck I was "lucky" enough to have a short one year stint around cisco packet tracer on my Networks and IT Management course!
But! This was never my strong point - I've always been more of a programming guy than a networks guy - and this wasn't about to change, so I decided to start immediately with deepening my IO handling ability. Last time I had to do anything with byte streams for example was in NodeJS, something to do with streaming an ndjson file by newline, and I embarrassed myself to the point of installing a library to do that simple task.
A perfect exercise to get acquainted with tcp and IO streaming at the same time is implementing your own HTTP parser from the RFCs alone, no library, no "http client", simple tcp listener getting a bunch of seemingly gibberish bytes and transforming them into HTTP packets, line by line. Here's a couple of snippets of how that went:
More on the actual repo.
This was essential for wrapping my head around how to navigate Valve RCON's protocol. HTTP is, in essence, an agreement between two servers on how they communicate. RCON is that, but smaller - way smaller - in scope.
While the HTTP training helped me wrap my head around IO reading from streams it didn't really educate me on how to be the writer of those packets, especially in golang. LittleEndian was an initial boogeyman, I don't know, I was so unfamiliar with the terminology that it scared me, but after watching a video about it (I think from IBM youtube channel) it became awfully simple, all about padding policy for the bytes representing a number. Speaking of padding, I actually had a lot of fun learning about the packet structure, it's not a challenging affair or anything but it was very fresh for me to work on something so close to hardware, there was no abstraction here, just me constructing the bytes that would be transmitted between two network devices. Of course I'm simplifying it but the point is that I hadn't done anything like this in a while.
At the beginning I didn't really know what I wanted to do with this project, as in whether it would be a library or an app, so the whole project was itself a simple command line program that ran this loop that read from STDIN, converted into an RCON packet (built by the function above) and sent it over the connection.
It started by reading the connection details (address, port, password, etc) from environment variables, opening that connection, sending the first auth packet, and then running that loop. Very simple but enough to prove the concept.
TBD
TBD
TBD
This is my [in development] portfolio. Here you will see a lot of what I worked on + a few tidbits about myself.
Although, this div should be "about me" so yeah I'm a fullstack dev (10 years of experience) employed at [redacted] doing all kind of work, I code a lot in my free time, going through a golang phase right now.
There are many quirky portfolios out there, mine is only special in being coded by a stubborn programmer allergic to third party libs.