Riverry
Order system for a hand-painted portrait studio — customers upload photos and approve proofs, while artists, editors and admins each work in their own workspace.
Riverry Studio sells hand-painted watercolor portraits of pets, homes, families and cars. Customers order on the storefront, send a photo, and a real artist paints it. Before anything ships, the customer sees a proof and approves it or asks for changes. Behind that promise is a lot of coordination: orders, photos, artists, quality checks, proofs, payments, printing and shipping.
I built the order system that runs all of it. It is one Next.js application with two faces: a customer app where buyers follow their portrait from photo to doorstep, and a staff workspace where every role in the studio does its part of the job.
What I built
- Order intake from the storefront, with every order tracked through a defined set of stages
- A customer app for photo uploads, proof review, add-on purchases and support messages
- User management with role-based workspaces for artists, editors, revisers, admins and customer service
- Two quality-check gates before a proof can reach a customer
- Payments for add-ons, plus payroll and reporting for the studio
- Fulfilment and tracking updates sent back to the storefront
- API integrations with AWS for file storage and transactional email
Product walkthrough
1. The customer app
Customers sign in with a one-time link sent to their email, or with Google. No password to remember. Orders placed before they had an account are linked to them automatically. From there they can:
- See every order with a progress bar showing where their portrait is
- Upload photos through a step-by-step wizard
- Review each proof, then approve it or request a revision with notes and reference images
- Buy add-ons such as rush processing, a gift message or digital files
- Correct their shipping address up until they approve the artwork
- Download digital files and message the support team
2. Workspaces for every role
A portrait passes through several hands, so the staff side is split into workspaces, and each person only sees the work that is theirs:
- Artists see their assigned pieces and upload versioned artwork.
- Editors claim finished pieces from a shared queue, make them print-ready, and pass them on or send them back.
- Revisers handle customer revision requests, or send a piece back to be repainted.
- Admins run the final quality check, assign artists and route orders to print and shipping.
- Customer service handles order holds and support conversations.
- Studio owners manage users, products, payroll and reports.
3. Quality before the customer sees anything
Artwork goes through two separate checks before a customer sees a proof, and the first reviewer can never send work straight to the customer. Once a piece passes, the system makes a watermarked proof and emails the customer automatically.
4. One order, many artists
An order with several portraits can be split across different artists. Each item moves through the pipeline on its own, and the order only moves forward when the last piece is done.
How it works technically
- Orders that are never lost. Each incoming storefront order is saved before it is acknowledged, then processed in the background. If processing fails it can be replayed, and the same order can never be created twice.
- One source of truth for status. Every move between stages goes through a single table of allowed transitions and leaves a history record, so nothing skips a step or ends up in an impossible state.
- Large uploads, straight to storage. Photos and print files are big, so the browser uploads them directly to S3 and the server checks them afterwards. That avoids the hosting platform's request size limit.
- Scheduled jobs instead of a queue service. Scheduled tasks sync tracking and fulfilment, reconcile orders with the storefront, retry failed events and send support emails.
- A clean data layer. Only one layer of the code talks to the database, and what each person can see and do is decided by their role.
Migrating a live business
The studio already ran on an older Express and MongoDB backend with a separate single-page app. I moved it to Next.js and Postgres without stopping orders. A compatibility layer let the existing backend logic run inside the new app while routes were ported one at a time, and anything not yet ported was passed through to the old API. Type checks in CI fail only on new errors, so the codebase gets stricter with every change instead of being blocked by old ones.
A working operations system for a real studio: customers, artists, quality checks, payments, printing and shipping, all in one app.