MacMarket Place
A marketplace for McMaster students, built with four friends and live at macmarketplace.ca. Sign-up is gated to @mcmaster.ca addresses, listings are searchable the moment they are posted, and buyers and sellers talk inside the app.
MacMarketPlace started with a phone call. Ahmad Allabadi rang me and our friend Moustafa Moustafa to say he had an idea: a marketplace built only for McMaster students. It took about a minute to agree, mostly because the need was so obvious once he said it out loud. Every September the same things happen on campus. Somebody is stuck with a $200 textbook the course dropped from its reading list. Somebody is graduating and needs to unload a desk, a mini fridge and a winter coat in the same week. Somebody is leaving for a co-op term in Toronto and needs a person to take over their lease. All of that was already happening in Facebook groups and group chats, where posts scroll away and nobody can search anything.
We built it between August and the beginning of October. Before writing much of it we wrote down what the thing actually had to do, then kept a Kanban board going for the whole build. A task went on the board with a description of what it needed, it got assigned to one of the five of us, and it moved across as it got done. Everything went through pull requests, so someone else read the code before it landed. That turned out to matter more than the board did. Five people working in the same repository at once will happily build the same thing twice otherwise.
The part I owned end to end is everything that leaves the app as an email: the hourly job that finds unread messages and sends them out through SendGrid, the daily feedback digest, and the nudges for people who signed up and never posted anything. I also did a lot of the feed work, filters, pagination, the swipeable image carousel on mobile, and the routing fixes that came out of using it on an actual phone rather than a desktop browser window pretending to be one.
The front end is React 19 and Vite with Tailwind, React Router for navigation and Framer Motion for the parts that move. Firebase does the rest: Auth for accounts, Firestore for listings, threads and users, Storage for images, and Cloud Functions on Node 20 for the work that has to happen away from the browser. Search is Algolia. Mail is SendGrid. The choice was deliberate rather than lazy. Three students with course loads could not also run servers, and every hour spent on infrastructure was an hour not spent on the thing students would actually open.
The interesting problems were mostly about keeping things consistent. Search is the clearest example: instead of writing to Algolia from the client and hoping every path remembered to, a function watches Firestore and mirrors each listing on write, deletions included, so the index cannot drift from the database. Messaging works the same way in reverse, with onSnapshot subscriptions pushing new messages to whoever has the thread open and unread counters updated inside the same transaction as the message itself. Images get compressed in the browser before upload, HEIC files off iPhones converted first, then a function makes 400px thumbnails so the feed is not downloading full-size photos to draw a grid of cards.
This is the project that taught me what running something is like. An assignment ends when it is marked. This one has real students on it, which means a slow query is somebody waiting, a broken image is somebody's listing looking abandoned, and an email that fires twice is an inbox somebody has to clean up. It is the first thing I built where the database is being read constantly, APIs are being called constantly, and a front end and a back end have to agree with each other while people are using both.



