Agates From Mexico
2023–presentA full e-commerce store for collectible agates: rich multi-image product listings, role-based admin, cart and wishlist, Stripe/PayPal checkout, and ShipStation fulfillment, all on a custom type-safe data layer.
- Next.js ·
- PostgreSQL ·
- Stripe ·
- PayPal ·
- NextAuth
The problem
Collectible agates do not fit the catalog model that off-the-shelf stores are built around. Every stone is one of a kind, so there is no concept of a SKU with a stock count of fifty. Each piece is its own product, sold once, and the thing that actually sells it is the photography: buyers want to see the same stone from several angles, in real light, before they commit. A platform like Shopify can be bent into this shape, but you spend your time fighting its assumptions about variants and inventory rather than building the store the product deserves.
An earlier version of the store also showed how much a weak data layer costs. It was held together by hand-written raw SQL, and every change to the schema turned into a round of boilerplate rewriting with nothing to catch mistakes.
The approach
I have worked on Agates across both versions of the store, on Next.js, with the catalog modeled the way the inventory actually works: each agate is a single, unique product with rich multi-image listings, so the photography leads. On the first version I built most of the storefront end to end: a custom Stripe Elements checkout, the cart and favorites, a separate wholesale and retail product system, an in-house point-of-sale for in-person orders, PDF invoice generation, product reviews, and a custom Tiptap blog editor.
Fulfillment is wired through ShipStation, including the webhook that marks an order shipped and records its tracking number, so packing and shipping happen in the tooling the operator already knows instead of a half-built admin screen. On the rebuilt version I focused on the zql-based authentication, the admin (a new roles system, discounts and coupons, notifications), and the move to dual Stripe and PayPal checkout, because buyers in this market expect the choice and offering both removes a reason to abandon the cart. Later work rounded out the operational edges: repeatable per-item refunds that behave the same across every payment provider, in-person cash and terminal orders handled alongside online ones, and a blog editor with dual rich-text and HTML editing plus embeddable components.
Underneath the new version is zql, the type-safe data layer I built after the raw-SQL approach of the first version wore me down. The schema is the source of truth, the queries are typed from it, and a change to the database surfaces as a compile error instead of a production bug.
The outcome
Agates From Mexico runs in production as a complete storefront: browsing, wishlist, cart, dual-provider checkout, and ShipStation fulfillment, with an admin the owner uses to run the shop day to day. Because it is custom, the store fits the product rather than the other way around, and because it sits on zql, it stands on a foundation that is steady to keep building on rather than risky to touch.