Aug 2024 – Nov 2024
Styl · Acquired by Sage AI Labs
Backend Developer, Part-Time · Remote

Styl was a swipe-to-shop fashion app: you swipe through clothes from different retailers and shop the ones you like. It was later acquired by Sage AI Labs. I joined part-time while I was still in college to work on the backend, mostly the part that got product data from retailers into the app.

The scraping pipeline and its scheduler

When I joined, the team had 40+ retailer scrapers, some in Python and some in Node.js. My teammates wrote the Node.js ones, and I wrote some of the Python ones. Running them was a manual job: someone ran a scraper on their own machine, got a CSV, and uploaded it by hand.

I built a pipeline on a VM that ran all of the team’s scrapers with one click. A scheduler backed by MongoDB kept track of each brand and refreshed it every 72 hours. After a scraper finished, the pipeline cleaned the data, removed duplicates, and loaded the results, so nobody had to run scrapers locally or upload CSVs anymore.

Validating the data for the ML service

A third-party ML service read our catalog directly from MongoDB, so bad data went straight into what it saw. I wrote validation rules for the scraped product data before it could reach the catalog:

  • Duplicates: the same product showing up more than once.
  • Size taxonomy: sizes had to fit our size categories.
  • Price bounds: prices outside a sensible range were caught.
  • Image counts: products needed the right number of images.
  • Reviews: review data was cleaned up.

Migration was also blocked until any new item types and colors in a brand’s data were mapped to our taxonomy, so unmapped values never made it into the live catalog.

The admin dashboard for review and migration

To move a brand’s data into the live catalog, I built an admin dashboard in Flask. It let us review each brand’s scraped data first and then migrate it. The migration was careful about what was already there:

  • It kept existing item IDs, so products already in the app stayed the same items.
  • It flagged changes to prices, sizes, and reviews, so we could see what had moved since the last run.
  • It soft-deleted products that had been removed from a retailer’s site instead of deleting them outright.
  • It used OpenAI to shorten product descriptions.

Deployment with Docker and GitHub Actions

I put the pipeline and an image-compression worker into a Docker container, using supervisord to run them together, and deployed it to the VM through GitHub Actions. The tricky part was that a deploy could land while the pipeline was in the middle of writing to the database. To handle that, the deploy waited for any in-progress database writes to finish before replacing the container, so a new release would not cut off a load halfway through.

The brand analytics API

I also built the Flask API behind a brand analytics dashboard, where brands could see how users were swiping on their products.

  • JWT authentication for logging in.
  • Per-company access control, so each brand could only see its own data.
  • MongoDB aggregations over user swipe data to produce the numbers.
  • Response caching, so repeated requests didn’t rerun the same aggregations.

Built with: Python, Flask, MongoDB, OpenAI, Docker, supervisord, GitHub Actions, and JWT.