Diego Andre Gomez Ruiz

Software developer · Greater Toronto Area · Currently building Preneur

Under the hood

I like the parts of software you only notice when they break.

I'm a software developer in the Toronto area, finishing my Information Technology degree at York (April 2028 is the plan for now). Most of my work lives on the backend. That means things like getting two systems to agree on what actually happened, making sure a job that runs twice doesn't leave a mess behind, and lately, getting an LLM to hand back something a program can actually trust.

That's taken me a few places so far. I spent sixteen months at ADS, a consulting firm downtown, building and looking after software that real companies used to run their day. I co-founded Preneur, a marketplace where homeowners and contractors find each other. And on the side I've been building StockIntel, which reads SEC insider-trading filings and flags buying that looks unusual.

My favourite stage of any project is the start, while nobody's quite sure yet what it should be. ADS taught me that the first version of a request is almost never the real one, and that a few extra questions early on can save weeks later. Past that, what I care about is software that keeps working when something around it doesn't, and that the next person can pick up without needing me in the room to explain it.

When I'm not at a keyboard for work, I'm usually at one for SEICI, the student IT group at York where I'm co-president. We run workshops and term-long projects so students have more than coursework to show when recruiting season comes around.

A few things I try to stick to:

If you've read this far, go ahead and poke around. The windows drag, resize and minimize like the real thing.

What I reach for

Languages

  • C#
  • TypeScript / JavaScript
  • Java
  • Python
  • SQL (mostly PostgreSQL)
  • C and C++
  • HTML and CSS

Frameworks

  • .NET 8 and ASP.NET Core
  • Next.js
  • React
  • Vue
  • Entity Framework Core
  • Redux Toolkit
  • Node and Express
  • FastAPI
  • pandas, NumPy, scikit-learn

Backend and infrastructure

  • RabbitMQ
  • PostgreSQL
  • Firebase and Firestore
  • Docker
  • Redis
  • Testcontainers
  • GitHub Actions
  • AWS
  • GCP
  • IBM Cloud
  • Linux
  • REST API

How I work

  • Sitting in on client calls
  • Turning vague asks into tickets
  • Two-week sprints in Jira
  • Writing down decisions (ADRs)
  • Tests that hit a real database

Where I've worked

Co-founder and lead developer · Preneur

Preneur started with a complaint pretty much everyone has: finding a good contractor is a pain. You ask around, you chase quotes, half the people never call back. So a friend and I started building a place for it. A homeowner posts a job, contractors nearby find it (or get it sent to them directly), and from there the two sides message each other, agree on a time, and leave reviews once the work is done. It's in public pre-launch right now. My co-founder took on profiles, reviews, settings and the overall look, dark mode included. I've been driving the rest of the app: search, the job posting flow, requests, scheduling, chat, and the state layer that ties them together.

Search is the part I'm proudest of. Asking for plumbers within 15 km sounds like one simple query, but Firestore has no idea what "within 15 km" means. So every user and job stores a geohash, which is a location turned into a short string where places that are close together share the same beginning. When you search, I turn your circle into a handful of those string ranges, fire them all off at once, merge what comes back, and then do the real distance math on each result to throw out the ones sitting in the corners of the box. One hook runs both the contractor browser and the job board, it just gets handed a different config. It also has a hard limit on how much it'll pull in, and if you hit it the page tells you to narrow things down instead of quietly showing you half the answer.

A lot of the work was designing the data backwards from the questions the app needs to ask. Scheduling is the easiest example. A job can go out to several contractors, so the thing that actually gets scheduled is a pairing of one job and one contractor. I made that pairing the document's ID, the job's ID and the contractor's ID joined with an underscore. Saving a schedule twice just writes over the same document, and loading one is a straight read with no search involved. I even changed our ID generator so it can never produce an underscore itself, which keeps the two halves from ever getting mixed up.

I also built the chat, which turned into the biggest single piece of the app. When you hit send, your message shows up right away, before the database has confirmed anything. If the save fails, it gets pulled back out and your text goes back in the box so you don't lose it. One message can touch up to five documents behind the scenes (both people's contact lists and unread counts, the message itself, sometimes a new date divider), so they all go through in a single batch or not at all. When someone changes a booking, a note about it gets posted into the conversation automatically.

Keeping the app's state sane was its own project. Anything coming from the server streams in live, and every change to jobs and schedules goes through one set of functions in Redux, so the rules for those only live in one spot. The five-step job posting form saves as you go, which means a refresh halfway through doesn't cost you anything. It's not done, and I keep an honest list of what I'd fix before real traffic shows up: moving a few multi-step writes onto the server so they can't overlap, loading long chat histories a page at a time, and a real search service so the filtering doesn't happen on your phone.

Preneur beta website

Software developer intern · ADS Business Transformation Experts Inc.

ADS is a consulting firm that builds and looks after custom software for other companies, and I spent sixteen months on their dev team. We were small, usually three developers on a project, and we were responsible for a few client systems at the same time: one for a construction materials company, one for a vehicle rental business, and an internal ERP. So in a normal week I might be building something new for one client, tracking down a bug another client had reported that morning, and updating a screen for a third because their process had changed.

What made it feel different from school was how close we were to the people using the software. I started sitting in on stakeholder meetings pretty early, and that's where I learned that the first version of a request is almost never the real one. A big part of the job was requirement gathering, which in practice meant asking follow-up questions until we understood what the person actually needed, writing that up as tickets for the next sprint, and then showing them the finished thing at the end so they could say "yes" or, more often, "close, but."

We ran everything in sprints, planned out in Jira. A change would go from my machine to a DEV environment, then to QAS, where the client could click through it themselves, and only then to PROD on IBM Cloud. Watching a client test your feature before it goes live is humbling in a good way. I got into the habit of writing short, plain notes on how to try out each change, so someone who isn't a developer could actually check it.

The project I think about most was for Holcim, one of the biggest building-materials companies in the world. Their dispatchers were planning the day's concrete trucks from screens that were basically long tables of times. Concrete can't sit around waiting (it starts setting in the drum), so knowing when every truck loads up and heads out really matters. I built them a scheduling view in Vue that lays the whole day out visually, truck by truck, so a dispatcher can spot a gap or a clash at a glance instead of reading it off a spreadsheet.

For another client, the staff told us pretty plainly that the screens they used every day were confusing. I went through the tasks they did most often, found where people were getting lost or typing the same thing in twice, and reworked those flows in Vue, changing the .NET side underneath to match. Same work, fewer steps. The best feedback I got was that people just stopped asking how to do things. And honestly, a lot of the sixteen months was plain upkeep, keeping three codebases healthy across four clients, chasing bugs that only showed up with one client's data, and updating things whenever a business rule changed. That kind of work doesn't make for exciting stories, but it's most of what keeps a client happy.

Things I've built

StockIntel

Whenever an executive or board member buys or sells shares in their own company, they have to tell the SEC within two business days, on a filing called a Form 4. All of it is public. StockIntel pulls those filings in and watches for patterns that are usually worth a second look, like three different insiders at the same company buying within a couple of weeks of each other. It's a learning project, and I set one rule for myself at the start: nothing gets added until there's a real problem for it to solve. That's why you won't find Kafka or Kubernetes in here.

It's made of two services that talk through RabbitMQ. A .NET 8 API handles pulling filings in, saving them and serving them, and it's the only thing allowed to write to the database. A Python service listens for new filings, keeps a rolling 14-day window for each company in memory, and runs three checks on it: several insiders buying together, an officer buying, and someone's stake jumping by more than a quarter. When one of those trips, it sends a signal back, and the API stores it and serves it up through a paginated endpoint.

The interesting problem is keeping a filing and the message about it from ever getting out of sync. If I save a filing and the broker happens to be down when I publish, nobody downstream ever hears about it. If I publish first and then the save fails, I've announced something that never happened. There's no single transaction that covers both. So the message goes into an "outbox" table inside the same database transaction as the filing, and a small relay empties that table into RabbitMQ every two seconds, fifty at a time. If RabbitMQ goes down, messages just pile up in Postgres and go out once it's back. The system gets slower for a bit, and nothing gets lost.

The catch is that a message can now show up more than once, so everything downstream has to shrug off duplicates. Filings are keyed on their SEC accession number with a unique index. Instead of checking first and inserting second (which can race), the code just tries the insert and handles the conflict. My favourite detail in the whole repo came out of this. When a duplicate gets caught, I clear out every pending change Entity Framework is holding, not only the filing. When I wrote it, that was just tidy-up. Once the outbox existed, it became the only thing stopping a duplicate filing from sending out a ghost message, and now there's a test that pins it in place.

I wired the RabbitMQ side by hand, no MassTransit, and that was on purpose, because I wanted to understand retries and dead-letter queues before letting a library hide them from me. Consumers only acknowledge a message once they're done with it. A message that fails waits ten seconds in a retry queue and gets three tries, and anything that can't be processed ends up in a dead-letter queue with a note explaining why. One thing you only find out by building it: when RabbitMQ dead-letters a message, it rewrites the routing key, so I have to dig the original back out of the x-death header. And on the way in, SEC lets you hit their servers ten times a second. I stay at five, because getting rate-limited by a government API is a bad way to spend a weekend.

Two languages means two chances to disagree about what a message looks like. Whichever side publishes an event also writes out sample files for it, and both test suites check against those samples, so a change that would break the other service fails in CI before it's merged. There are 130 tests right now, 107 in xUnit and 23 in pytest. The ones that touch Postgres or RabbitMQ run against the real thing in throwaway Docker containers, since a mocked database can't tell you whether your unique index actually fires.

What I'm working on now is a second listener on the same exchange that writes each user a short, plain-English recap of insider activity on their watchlist. An LLM writes it, its output gets checked against a strict schema, it runs on a token budget, and results are cached in Redis so the same summary never gets paid for twice. After that comes putting the whole thing online. It only runs as a single instance today, and I know the three reasons why: the relay would double-send if two copies ran at once, database migrations run at startup, and a second copy would double the traffic to the SEC. Each has a known fix, and that list is next.

StockIntel on GitHub

Wardrobe recommendation app

This was a four-person team project that tries to answer the question everyone asks at seven in the morning: what do I wear today? You add what's in your closet, the app checks the weather where you are, and it suggests a few outfits. You tell it which ones you actually liked, and over time it gets a little better at guessing.

I co-led the team and owned how everything fit together, meaning the overall architecture, the API design, and how the four of us used Git without stepping on each other. That last part took more effort than I expected. We landed on short-lived branches and pull requests that at least one other person had to read before anything got merged, which saved us more than once the week before the demo.

The backend is Node and Express sitting on Firestore. It keeps track of your wardrobe as you add, edit and remove pieces, takes the messy response from a weather API and boils it down to something simpler like "cold, windy, might rain," and records how you rated every suggestion so the model has something to learn from.

Recommendations happen in two passes. The first is plain rules: no shorts at minus five, no suede in the rain, nothing too casual for a formal event. Whatever survives gets scored by a scikit-learn model trained on the outfits you've said yes to before, and the top few become your options. The model is Python and the server is Node, so the server launches the scoring script as a child process, hands it the candidates and reads the scores back. It isn't a fancy bridge, but it let each half stay in the language it's best at, and we could swap the model without touching the API at all.

Wardrobe app on GitHub

This desktop (the site you're on)

I wanted a portfolio people would actually remember, and something about Windows XP makes just about everyone smile a little, so here we are. Everything you're clicking on is plain HTML, CSS and JavaScript.

The windows behave like the real ones. You can drag them by the title bar, resize them from any edge, minimize them to the taskbar, and maximize them and have them come back to exactly where they were. Whichever window you clicked last comes to the front. Each one also has its own link, so adding #win-projects to the address opens straight to this one.

You don't need a mouse for any of it. Alt+Space opens the little menu in the corner of a window, same as XP, and from there the arrow keys move or resize it and Enter locks it in. Tab and the arrow keys get you around the icons and the taskbar. The full list is in Help and Support.

Underneath the desktop, it's just a normal page. With JavaScript turned off, or if you print it with Ctrl+P, you get a clean, readable version of everything here. The icons and window borders all come from a single SVG sprite and a set of CSS variables, which is also how the three colour themes swap. It's hosted on S3 behind CloudFront, and the account that deploys it can't touch anything except this one bucket.

This site on GitHub

Groundwork

York University Toronto, Ontario

Registered to:

Diego Andre Gomez Ruiz

B.A., Specialized Honours, Information Technology

GPA 3.7

- (expected)

Eligible for 4, 8, 12, and 16 month Co-op Placements

Honours:

  • Dean's List
  • Continuing Student Award for Academic Excellence

Courses that stuck with me:

I want to say, I've enjoyed a lot of classes throughout my career; data analytics class, database management systems, web development and the machine learning class are the ones I can name right now. The ones that really stuck to me are: Data structures and databases, mostly because I kept running into both again at work. Systems analysis and design turned out to be surprisingly practical too.

Co-president · Student Excellence in ITEC Initiative (SEICI)

SEICI is a student-run group for people in York's IT program. School gives you the theory, and we try to fill in what it leaves out: how to actually land an internship, what working on a real team feels like, and how to build something outside of class. I joined as a regular member and ended up as co-president, which mostly means I help decide what we do and then make sure it actually happens.

Before each school year starts, we map out the whole Fall and Winter terms, every workshop, every project and every deadline, with one person's name next to each item. One name sounds like a small thing, but it changed a lot. Stuff stopped falling into the gap between "someone should do this" and "I thought you were doing it."

In practice, that looks like resume and interview workshops before recruiting season, evening sessions where members build something small from scratch, and team projects that run across a term so people have something real to talk about in interviews. I've led a few of the technical sessions myself, including one on Git that a good chunk of the room said they wished they'd had in first year.

Co-leading turned out to be its own skill. Everyone involved is a student with exams and jobs, so a lot of it is keeping plans realistic, knowing when an event should be cut because it isn't ready, and making sure the people doing the work get the credit for it.

Certifications:

  • AWS Certified Cloud Practitioner · Amazon Web Services
    Issued , good until · Verify on Credly

I went for this one mostly because this site runs on AWS and I wanted to properly understand what I was using. It covers how the main services fit together, how permissions and security work, and how billing works, which as a student is the chapter you read twice.

Notes and write-ups

Why I stopped trusting "save, then publish"

Pretty much every service that saves to a database and then sends a message runs into the same bug eventually. This one walks through what goes wrong, how a plain outbox table and a relay that runs every two seconds fixed it in StockIntel, and the part where a clean-up line I'd written months earlier turned out to be holding the whole thing together.

Transactional outbox article

Transactional outbox implementation article

Finding nearby contractors on a database that doesn't do distance

Firestore can't answer "who's within 15 km of me?" on its own. This is how geohashes get you most of the way there, why the box they give you is always a bit bigger than the circle you asked for, and what Preneur does to clean up the difference.

Geographical queries

Geohashing article

Rebuilding Windows XP in a browser

Notes from building this desktop: dragging windows without letting them escape off screen, keeping track of which one is on top, copying XP's keyboard shortcuts, and making sure the whole thing still reads as a normal page when JavaScript is off.

Window follows cursor article

Say hi

To:
diangoru@my.yorku.ca
GitHub:
GitHub
LinkedIn:
LinkedIn
Location:
Maple, Ontario (Toronto area)

If you're hiring for a software engineering, software development, data analytics/engineering or ML position, want to dig into something you saw on here, or you're stuck on a Firebase or RabbitMQ problem and want a second pair of eyes, send me an email, I'll be happy to hear from you.

I read everything that lands in my inbox and usually reply within a day or two.

Send email

Help and Support

Keyboard shortcuts

You don't need a mouse for anything on this desktop. It all works from the keyboard, and nothing needs dragging.

Keyboard shortcuts for the desktop and its windows
KeyWhat it does
TabJump between the desktop icons, open windows and the taskbar
Move around the icons, the taskbar or an open menu
EnterOpen the selected icon, or press whatever has focus
EscClose the window you're in, or back out of a menu
Alt + SpaceOpen a window's menu (Restore, Move, Size, Minimize, Maximize, Close)
Alt + TabSwitch to the next open window
Ctrl + EscOpen the Start menu
Ctrl + PPrint everything as a plain page

How this site works

Under the desktop, this is one ordinary HTML page. The desktop gets drawn on top of it with JavaScript.

  • With JavaScript off, you get everything as a simple page you can read top to bottom.
  • With JavaScript on, each section opens up as its own window.
  • Ctrl + P prints the plain version, not the desktop.
  • Every window has its own link, like #win-projects, so you can send someone straight to it.

Colophon

Written by hand in HTML, CSS and plain JavaScript. There's no framework and nothing to install, so what you see in View Source is what's actually running.

  • Font: Tahoma, falling back to whatever your system has.
  • Themes: Luna (blue), Olive Green and Silver, swapped with CSS variables. You can switch between them in Display Properties.

Display Properties

Color scheme
Font size
Effects