dev.oceanheart.ai

Client work

Sarah Mozer Studio

An artist’s shop, with an editing workflow she can own.

Sarah Mozer Studio homepage with a large coastal painting and links to landscapes and pet portraits.
Live website

The work comes first

A painting fills the opening view. The navigation leads directly to the kinds of work a visitor can buy or commission.

View full size

Sarah needed a place to sell her artwork, prints and cards, and a manageable way to look after it. I built the shop, catalogue, checkout and inventory controls together with the editing workflow.

She can change customer-facing words and photographs while technical fields remain protected. An owner guide and support using annotated screenshots help her make routine changes. My work included discovery, implementation, deployment and ongoing support.

Delivered client system. Availability and product details are maintained by the studio.

More views (1)
Dorset landscapes collection introduction with a harbour painting.
Live website

A place for each collection

The landscape collection has its own introduction and visual identity. Captured September 2026; stock and availability change.

View full size
Technical detail

Architecture checked against the catalogue configuration, checkout and webhook implementation. This is a code account, not a fresh live-payment test.

Catalogue and ownership

One catalogue row represents one sellable format. An artwork grouping ID connects an original, print and card derived from the same painting. Product IDs, Stripe price IDs and inventory policy have technical ownership; the CMS describes that boundary separately from editable words and images.

Checkout and finite stock

The server resolves submitted product IDs to canonical catalogue entries and Stripe prices. Originals are restricted to quantity one. Finite-stock lines require an enabled inventory path and a reservation; unavailable stock, cart conflicts or database failures stop checkout. A fingerprint binds the attempt to its cart, and the attempt ID becomes the Stripe idempotency key.

Payment events and recovery

Webhook construction verifies the raw body with the Stripe signature. The handler distinguishes paid, pending asynchronous, expired and failed sessions, filters application ownership, and passes event and reservation IDs to the inventory repository before persisting a paid order. A definitive checkout-creation failure may release a new reservation; an uncertain failure retains it rather than assuming no payment session exists.

Stack / components
Next.js, TypeScript, TinaCMS, Stripe, Neon

Visit the project Back to Systems work