~/work/mule-mart
Mule Mart
An online marketplace for the Colby College community
A full-stack web app where verified Colby College students can buy, sell, and donate items. I started it with three other students, and as lead engineer I wrote most of the backend, including its semantic search feature and image storage service built on AWS S3.
Semantic search
ranks listings by meaning instead of shared keywords
S3
private image storage, with uploads and downloads through presigned URLs
Docker
containerized, with automatic deploys through a Procfile
mulemart.com

01 · the problem
Seniors and other students at Colby often throw away perfectly good things because they can't find anyone who wants them. The main place to post those things is Colby Now, the daily announcements email, but posts there are easy to miss and hard to find again. There's also no way to tell whether an item that was posted is still available. My team therefore wanted to build a better place for the Colby community to buy, sell, and donate things.
02 · what I built
- Led the four-person team as lead engineer: set the technical direction, decided what to build and in what order, and split the work across the team.
- Wrote most of the backend, a Flask app that stores data in PostgreSQL through SQLAlchemy.
- Built Mule Mart's semantic search feature, which finds listings by meaning instead of matching keywords. It uses SentenceTransformers (all-MiniLM-L6-v2) and PyTorch to store each listing's title and description as a vector embedding, and it ranks results by cosine similarity.
- Wrote the storage service for images, which live in a private AWS S3 bucket. Images are uploaded and loaded through presigned URLs, so large files never pass through the app server.
- Containerized the app with Docker.
- Wrote the three GitHub Actions workflows, which run the tests, linting, and the Docker build on every change.
- Set up automatic deploys through a Procfile, which also runs database migrations on each release.
03 · how it works
- 01sign in
Students sign in with Google or a password, using their Colby email.
student@colby.edusigned instudent@gmail.comPlease use your @colby.edu email address to sign in. - 02post a listing
The seller's photos upload from the browser straight to S3 through presigned URLs, and the listing is saved to PostgreSQL.
browserprivate S3 bucketphotos, through a presigned URL
browserFlaskPostgreSQL
listing details
- 03prepare for search
When a listing is saved, its title and description are turned into a vector embedding with all-MiniLM-L6-v2 and stored with it.
The North Face parka White down parka, size M. Kept me warm through two Maine winters.
all-MiniLM-L6-v2
[-0.001, 0.146, 0.078, 0.064, …, 0.011]
384 numbers, stored with the listing
- 04search
When a student searches, their search term is turned into an embedding with the same model and compared with every listing's embedding. Listings are ranked by cosine similarity, and those scoring below 0.25 aren't shown.
winter jacketsimilarityThe North Face parka0.54Winter boots0.46Wool beanie0.43Patagonia fleece pullover0.43Knit gloves0.29below 0.25, not shown
Futon0.21Mini fridge0.20 - 05message and order
Buyers message the seller in the app, and the chat checks for new messages every 2 seconds. Orders go to the seller to approve or reject. Once the seller approves an order, the listing is hidden from other buyers.
Hi! Is the parka still available?
Yes, it is. I can meet on campus tomorrow.
order: pendingapproved
04 · key decisions
Keeping search in PostgreSQL
Instead of adding a separate vector database, I stored each listing's embedding in PostgreSQL next to the listing. At Colby's size, the app can compare a search against every listing directly, so one database was enough.
Uploading images straight to S3
Photos upload from the browser straight to S3 through presigned URLs, so large files don't pass through the app server and slow down other requests.
Checks on every change
I set up GitHub Actions to run the tests, linting, and a Docker build on pull requests and pushes to main, so problems show up before code is merged.
05 · where it stands
- ✓Live at mulemart.com for the Colby College community.
- ✓Students can search listings by meaning. For example, a search for “winter jacket” can find a listing titled “North Face parka”.
- ✓I'm rebuilding the backend as event-driven Go microservices for Mule Mart 2.0.