Skip to content
Jonathan Andreanus
Jonathan Andreanus
All work

Yamaha dealer online shop

The online shop of a Yamaha dealership in Bandung, selling spare parts and accessories, on a Medusa.js v2 backend and a Next.js storefront.

Year
2025
Role
Software Developer (contract), sole developer
Stack
Medusa.js v2, Next.js, PostgreSQL, Redis, Meilisearch, Biteship, Midtrans

Bintang Rejeki Motor is a Yamaha dealer in Bandung. Its shop sells parts and accessories to retail customers. The brief was to launch with the product data already on the dealer’s marketplace store, and once the shop was ready, to make the marketplace the mirror of the shop. The source is private because this is client work.

What I built

  • A Medusa v2 backend with custom modules for WhatsApp OTP login (through n8n), Biteship shipping with RajaOngkir as a fallback, Midtrans and manual bank transfer, pre-orders, product insurance, part compatibility, reviews, shipping labels and payment reconciliation.
  • Biteship integration covering rates, draft orders, labels, tracking and webhooks, across 85+ courier options.
  • Admin widgets for shipping status, labels and pre-orders.
  • Catalog loading: first with Python scripts that converted the marketplace’s Excel exports to CSV, then with an Excel bulk import/export in the admin and product metadata generated by Gemini through n8n.
  • Redis caching for shipping rates, order tracking and payment tokens, and Meilisearch for product search.
  • Deployment on a VPS with PM2 and nginx.

Decisions

One Biteship draft order per address

Medusa asks for a price once per shipping option, which meant one Biteship call for every courier. The shop now caches one draft order per address combination and reuses it, so rates can be up to an hour old.

Payment tokens handled on the backend

Midtrans tokens are cached on the server, retried up to twice when they expire, and invalidated by the payment webhook when a payment fails or expires.

Excel import in two phases

The import shows a preview first. Confirming writes in batches of 50 inside database transactions, and updates prices in place, because deleting and re-adding them wasn’t atomic and risked losing data.

Numbers

  • 18 custom Medusa modules.
  • An import file of 3,416 unique SKUs prepared for the catalog.