CLIENT WORK — SHIPPED —
Yacht Assets Reviewer
One shared review app for 115 yacht interior assets: swipe, agree live, export the picks in one click. Built in a day.
≈ 3 min read
AT A GLANCE
- STATUS
- SHIPPED
- TIMELINE
- 2025-12 — 2025-12 · 1 DAYS
- LANGUAGES
- Python / JavaScript / HTML / CSS
- CATEGORY
- CLIENT WORK
ASSETS REVIEWED
OUTCOME
All 115 assets land in one shared, image-led review pass, and approved picks export as a numbered ZIP the 3D designer can use with zero reassembly.
METRICS
M.01 — ASSETS REVIEWED
Premium assets reviewed and exported across 10 interior design categories
M.02 — PRODUCT URLS SCRAPED
Supplier product URLs collected by the scraper (91 from one supplier, 24 from the other)
M.03 — REVIEW CATEGORIES
Asset categories: tableware, seating, tables, storage, decor, plants, lighting, audio, textiles, accessories
M.04 — PYTHON SOURCE LINES
Python powering the scraper, uploader, and Flask backend
M.05 — DEPLOYMENT TARGET
Live cloud web service (gunicorn), deploy in about 30 minutes per the deployment docs.
CH.01
The problem
A team had to agree on 115 premium furnishing assets from two suppliers, working over a spreadsheet of links with no images and no shared state.
A yacht interior design project required shortlisting premium 3D furnishing models across 10 categories, including seating, tables, tableware, lighting, decor, and more. The catalog covered 115 products. The team needed a way to review product images side by side, agree on approvals, flag top picks, and hand off a clean selection to the 3D designer, all without a shared license to a dedicated asset management tool.
Reviewers worked from URLs alone, pasted screenshots into chat, and reconciled decisions by email. Approvals collided, picks went missing, and the 3D designer reassembled the final set by hand.
CH.02
What I built
A web app where the whole team swipes through product images, approves or rejects each one, and sees everyone's decisions in real time.
A purpose-built multi-user review tool: a Flask backend serving a single-page interface where reviewers navigate assets one by one, approve or decline each, and mark favourites. All review state persists in a shared JSON catalog stored in Dropbox, so any reviewer's decision is visible to everyone else immediately.
A separate scraper pipeline was built first to collect and organise all 115 product URLs from both supplier sites, download product images, and upload them to Dropbox alongside the catalog file. No accounts, no installs, any browser. This gave the review app a self-contained data layer with nothing to log into at review time.
CH.03
How it works
Shared state lives in one Dropbox JSON file, making every decision instantly visible to everyone, with no database to run.
The Flask backend exposes a REST API with endpoints for catalog read/write, per-image link generation, ZIP export, CSV export, and stats. The frontend loads the full catalog on page load, then fetches Dropbox temporary image links on demand to avoid 115 calls at once on startup.
Reviewers use keyboard shortcuts or on-screen buttons: approve, decline, top-rated, back, skip. A live sidebar tracks progress and allows filtering by category or review status, and the filter narrows the navigation queue in real time without a page reload. The whole interface is a single HTML file with no build step and no framework dependencies.
CH.04
The handoff
One click exports approved assets as a numbered ZIP plus a links manifest, ready for the designer with no manual cleanup.
When review is complete, one click generates a ZIP in memory: it includes a links.txt manifest grouped by category with ordered item numbers, plus all approved images renamed with numeric prefixes so anyone can say "use item #7." The 3D designer receives a clean, numbered set with no further assembly needed. A CSV export covers the full catalog with order, category, source URL, status, and rating columns for direct Notion import.
Deployment uses Render.com with Dropbox OAuth2 refresh tokens, and no credentials are committed to the repository.
CH.05
Results
Built, documented, and deployed to cloud hosting in a single day, replacing hours of spreadsheet and screenshot back-and-forth.
The scraper automated all image prep, the app turned 115 assets across 10 categories into one image-led review pass, and the export hands off a clean selection with no manual cleanup. The entire stack (scraper, uploader, Flask backend, and single-page frontend) runs in 922 lines of Python. Deployed on Render.com in about 30 minutes with token-based Dropbox sign-in and no passwords stored.
6 COMMITS — IN 1 DAYS — AVG 6/DAY
55 NODES · 62 EDGES · 14 COMMUNITIES — EXTRACTED FROM THE CODEBASE BY TREE-SITTER
FEATURES
| Card-swipe review interface | Reviewers approve, decline, top-rate, back, or skip each asset by keyboard or button, with live progress stats and category filters. |
|---|---|
| Shared Dropbox state | The catalog JSON lives in a Dropbox App Folder, so every reviewer's decision persists instantly and shows up in all other sessions. |
| Image scraper pipeline | A scraper pulls product images from two supplier sites, sorts them by category, and uploads the full dataset to Dropbox before review begins. |
| ZIP export | One click builds an in-memory ZIP of approved images, renamed with numeric prefixes and bundled with a category-grouped links manifest. |
| CSV / Notion export | The full catalog exports as a CSV with order, category, source, URL, status, and rating columns, ready to import straight into Notion. |
ARCHITECTURE
| scrape_yacht_assets.py | Scrapes 115 product URLs from two suppliers, downloads images into category subfolders, and produces the initial JSON catalog |
|---|---|
| upload_to_dropbox.py | Uploads the local catalog JSON and image folders to the Dropbox App Folder that the web app reads from |
| app.py | Flask backend: serves the SPA, exposes REST endpoints for catalog read/write, per-image link generation, ZIP export, CSV export, and stats |
| templates/asset_reviewer.html | Single-page frontend: card review UI, sidebar filters, stats panel, keyboard shortcut handler |
STACK
SKILLS DEMONSTRATED
Same-day delivery of a working tool · Multi-user review apps without a database · Web scraping across different site structures · Flask REST API design · Dropbox OAuth2 integration · Cloud deployment (Render.com) · Clean export and handoff pipelines · Replacing manual workflows with automation
