All projects

Norway Salmon

Ordering and operations for an importer that flies fresh Norwegian salmon to Ulaanbaatar: a website with scroll-driven 3D scenes, flight-based orders paid with QPay, and an admin for orders, markets and finance.

Norway Salmon, cover

What it is

Norway Salmon imports fresh Atlantic salmon from Norway to Ulaanbaatar: skinless, boneless E-trim fillets flown chilled at 0–2 °C from Oslo via Incheon and delivered the evening the flight lands. It also sells frozen and packaged products, such as sushi boxes, through partner markets. I built the whole platform: a Turborepo monorepo with a NestJS GraphQL API, a public website, an admin and a customer assistant, in Mongolian and English.

The website in 3D

  • How it is prepared. A scroll-driven 3D scene follows a whole salmon through nine cutting and packing steps, from the gutted fish to the trimmed fillet. Scrolling scrubs a baked animation clip from a GLB model.
  • Oslo to Ulaanbaatar. A second scene flies a plane across a 3D globe from Oslo (OSL) via Incheon (ICN) to Chinggis Khaan airport (UBN), with airport labels.
  • Built to stay light. React Three Fiber renders on demand only when the scroll moves, the models download with a progress bar into a shared cache, studio lighting comes from light formers instead of a downloaded HDR, and a slow or failed download falls back to still images. Reduced motion gets a skip link for each part.

Ordering

  • Guest orders, no account. A customer gives a phone number, picks delivery or pickup, chooses one of the open flights and the products, and pays a fixed 10,000₮ deposit by QPay. The rest is paid by weight once the fish is weighed.
  • Live payment status. The order page hears about the payment over a GraphQL subscription, with polling as a fallback.
  • Partner markets. A page lists the markets that sell the packaged products, with a map, addresses and phone numbers.
  • Assistant. A chat on every page answers customers' questions from the FAQ with Claude. It never places or changes orders.

The admin

  • Dashboard. Sales collected, orders, average order value, new customers, a sales chart, the open work that needs attention, top products and the next flight arrivals.
  • Orders. Each order goes from pending to paid: edit items, enter weights, deliver, then record the payment. Orders are grouped by flight, and a delivery map shows every order still to be delivered at its address.
  • Markets. Partner markets, their products, daily sales sheets and a sales report.
  • Finance. Income, expenses, net profit by month, VAT-reported sales, market commission, transactions, categories and loans with repayments.
  • Team and settings. Admin, staff (without money rights) and customer accounts, settings, contacts and feedback. A paid invoice shows up live.

Behind it

NestJS with GraphQL, PostgreSQL through Drizzle, Redis for caching, rate limits and the subscription pub/sub, S3 storage, QPay, CallPro SMS codes and Sentry. The assistant is a Python FastAPI service behind the API. It runs in Docker behind nginx on a VPS, with backups. The admin screenshots show development data.

  • Norway Salmon, image 1 of 9
  • Norway Salmon, image 2 of 9
  • Norway Salmon, image 3 of 9
  • Norway Salmon, image 4 of 9
  • Norway Salmon, image 5 of 9
  • Norway Salmon, image 6 of 9
  • Norway Salmon, image 7 of 9
  • Norway Salmon, image 8 of 9
  • Norway Salmon, image 9 of 9

Want something like this?

Get a quote