Adrian Toma builds web apps.

Full-stack developer. Two projects below: a multiplayer music game and a record shop.

View CV (PDF, opens in a new tab)

Based in
Zaragoza, Spain
Stack
Angular, C# / .NET
Open to
Junior roles, Spain or remote
Languages
Spanish native, English C1

Cronotune, a music timeline party game

Two to six players hear a short preview and place the track in their own timeline by release year. It is my final-degree project (TFG), and it is live.

Cronotune's home page: Guess the year, build the timeline

Everyone plays at once

In a live game, placements, timeouts and reconnects can all hit the same room at the same moment. So the server owns the game state: each room handles one action at a time, and turn deadlines run on the server, never in a browser timer.

Anti-cheat system

Well, not really... but I made sure that players can’t check the network tab to gain an advantage. Audio arrives through a short-lived token scoped to the room. The title, artist and year reach the browser only when the round resolves.

Release dates are hard

Songs can have multiple release dates and online data can be messy... so I created an offline C# tool that compares four sources. A track plays only when two agree within a year, one of them MusicBrainz or Wikidata.

Dancing Queen, ABBAPlays
Release year of Dancing Queen by source. It plays because MusicBrainz and Wikidata agree.
SourceYearAgrees
Spotify1992No
Deezer2005No
MusicBrainz1976Yes
Wikidata1976Yes
  • Angular 22
  • .NET 10
  • PostgreSQL 16
  • SignalR
  • Docker
  • GitHub Actions

Pressing Room, a record shop

A storefront for a fictional record shop selling vinyl, CD and cassette: catalog, cart, checkout and a collection of every Record a customer has bought. Payment is simulated.

Pressing Room's home page: Analog sound, digital ease

Never trust the cart

The cart lives in the browser, so anyone could edit it to pay less. That’s why checkout only sends Record ids and quantities, and the server sets the prices and checks the stock. If one line fails, the whole Order is rejected and no stock is touched.

Old orders shouldn’t change

If an Order just pointed at the live Record, changing a price or deleting a Record would rewrite a customer’s history. So every line copies the artist, title, format and price at purchase. I compared the alternatives and wrote the decision up in an ADR.

The admin can’t shop

Hiding a button isn’t enough, because anyone can call the API directly. So the roles are checked twice: route guards in Angular and middleware in the API. The admin manages the catalog, and the cart and checkout stay closed to it.

Who can use each part of the shop
VisitorCustomerAdmin
CartYesYesNo
CheckoutNoYesNo
CollectionNoYesNo
Manage RecordsNoNoYes
  • Angular 20
  • Angular Material
  • Node.js
  • Express
  • Docker

It started from a static design, my team’s Angular starter and a generic Node backend.

Angular up front..NET out back.Linux underneath.

I’m finishing my web application development diploma (CFGS DAW) at Centro San Valero in Zaragoza, after a frontend internship at ALTEN España working in Angular and TypeScript.

These days I’m studying for the AWS Solutions Architect Associate, which is a bit funny, since everything I build ends up on my own VPS anyway. I just like running my own stuff: I self-host a bunch of servers and services, all on Linux, and spend way too much time in dotfiles.

Path

Sep – Nov 2026
Frontend developer intern, ALTEN España
2024 – 2026
CFGS DAW, Centro San Valero
Speaks
Spanish and Romanian native, English C1