E-commerce ·May 2025 → ongoing ·paused
OPI Tech
The company's own electronics storefront, built from the database up: card payments in a market the provider does not serve, store credit honoured in the same transaction as the order, and a checkout that makes three services fire in the right order.
- Timeframe
- May 2025 → ongoing
- Tags
- E-commerce · next.js · stripe · retention
- Credits
- Xern Mottley — Engineer
Where it started
OPI Tech is the company's own electronics line, and the storefront is the side project that kept coming back. Several earlier versions ran on hosted platforms — Shopify, WooCommerce and the like — and none of them did what the business needed: sell electronics in Trinidad and Tobago, streamline the process behind a sale, and keep the customer afterwards.
Two things in particular. Accepting a card online: Stripe, the provider with the developer tools the build wanted, does not operate in Trinidad and Tobago. And a checkout that does not leak — one where the payment, the order, the stock, the customer's credit and the confirmation all agree, every time, with the customer seeing none of the seams.
Priced in TTD, charged in USD. Every price the customer sees is in their currency; when a payment intent is created the total is converted at a live rate, refused below the card minimum, and charged by Stripe in its own — settled to banking arranged abroad, because the provider does not operate in Trinidad and Tobago. The checkout says the bank statement may differ slightly. Cash on delivery and store credit never leave TTD.
What was done
A storefront and its administration, on one schema, from the database up.
A catalogue with variants, brands and categories. A cart that works for a guest and for a signed-in customer. Delivery by island, with addresses chosen from a Trinidad-and-Tobago location list, delivery methods that each say whether cash on delivery is allowed, and free delivery on a first order. Prices in the customer's currency, with the card charged in the provider's at a live rate — and the checkout says so.
Payment through Stripe, which meant a decision before a line of code: the provider does not operate here, so accepting a card online meant arranging banking abroad that it could connect to. The alternatives were researched; Stripe was chosen for its developer options and how far it could be customised.
Then the layer that keeps a customer. Store credit, with a balance and a ledger that records the balance before and after every movement, arriving for four reasons and spent inside the order's own transaction.
Where credit comes from and where it goes. Four sources — a cash-on-delivery refund, a referral bonus after verification, a delivery reward, an administrator's adjustment — into one balance with a ledger that records the balance before and after every movement; out through a checkout, an expiry, or a refund.
Store credit as the customer sees it: the balance, each credit with its rolling one-year expiry, and the ledger of every movement with the balance after it — a demonstration account, credited by an administrator's adjustment.
A referral programme with its integrity in the schema — no self-referral, one referee per link, a bonus issued only after the new account's email is verified, and a delivery reward to both parties once an order arrives. Reviews that only a verified purchaser may write, moderated before they show.
Twelve transactional emails, from the order's confirmation to a review request, with abandoned-cart reminders at twenty-four and forty-eight hours that check, at the moment of sending, whether the cart is still abandoned.
Twelve emails and what sends them. The two abandoned-cart reminders are scheduled with the provider at twenty-four and forty-eight hours and check at send time whether the cart is still abandoned. The provider reports back on every email, and a complaint switches that customer's marketing email off.
The order confirmation, rendered from the repository's own template with sample data — the catalogue's real product, a placeholder customer. No customer's email is shown.
Every order moves through a stated set of states, with a written rule for who may move it: a customer cancels on their own before anything ships; a refund is an administrator's workflow, only after delivery and within thirty days, back to the card for a card order and to store credit for cash on delivery.
An order's states and who may move it. Cancel is the customer's own action before anything ships; refund is an administrator's workflow after delivery, within thirty days — back to the card for a card order, to store credit for cash on delivery.
The administration behind all of it — products, stock with history and alerts, orders, customers and their credit, reviews, communications, and the referral programme's own parameters on a surface that sets them.
The referral programme's parameters on the surface that sets them: the order that qualifies, the reward on an order and on a first order, the signup bonus. Every change to them is audited.
The decision that mattered
The checkout. It is the single most important part of an e-commerce site, and it is where three services with their own clocks — the payment provider, the database, the email provider — have to be made to fire in one order and end up agreeing.
One checkout, three clocks: the browser's sequence, the server's and Stripe's, drawn in the order they fire. Step six is a single database function that writes the order, its items, the stock decrement, the payment record and the store-credit deduction together — or nothing. Credit was once deducted after the order; the race that produced is why it now happens inside it.
The browser's sequence is the customer's: choose delivery, apply credit, pick card or cash. The server's begins when a payment intent is requested — the total converted to the provider's currency at a live rate, rejected below the card minimum, the intent stamped with the cart and the rate used. The card is confirmed in the browser against that intent and never touches the server.
Only then is the order created, and before anything is written the server goes back to the provider to retrieve the intent, confirms the cart still exists, and saves or reuses the addresses.
The writing itself is one atomic database function: the order, its items, the stock decrement, the payment record, the status history, the store-credit deduction and the cleared cart, together — or, if a variant has run out, none of it. The confirmation email goes the moment the order exists. And the provider's own clock closes the loop: a signed webhook finds the order by its intent and marks it processing, or marks it failed and keeps the reason.
The checkout, signed in, with a pair of earbuds in the cart: delivery methods with their rate and cash-on-delivery flag, store credit to apply, the choice of card or cash on delivery with the currency conversion stated, and the summary in the customer's currency — first-order delivery free and the delivery reward already counted. Captured locally on a demonstration account; nothing was typed into the card element and no order was placed.
The same checkout on a phone, where most shop traffic lands.
The part worth copying is the part that was wrong first. Store credit was originally deducted after the order was created — a second step, a moment later. The project's own working notes record what that produced: race conditions, and order totals that did not match the credit actually taken.
The fix was not a retry. It was to move the deduction inside the same function as the order, so that an order and its credit either both happen or neither does. That is the whole lesson of the build in one change: in a checkout, the order of operations is the product.
Three paths share the sequence. A card takes all eight steps. An order covered entirely by credit skips the intent and is processing at once. Cash on delivery skips it too, and stays pending until the goods arrive.
Where it stands
Not live, and between iterations — on purpose. The storefront runs against its own catalogue, and the next version is being refined rather than the current one rushed out.
Sixteen commits in ten weeks, May to July 2025; then nothing in either repository for fourteen months; then two days in September 2026 — the split into a repository of its own, and the review that preceded this page.
In September 2026 it was decoupled from the company's main site into a repository of its own, by a written plan of five decisions — whether the admin was ever meant to be shared (no), separate repositories rather than a monorepo or a subdomain, and what to do with the database (first one answer, then, the same day, its reversal, left visible in the record rather than overwritten).
The split moved two hundred and sixty files, found three that had been living outside the storefront's namespace, fixed a shared utility that had been living inside it, and was verified with a production build before it was called done.
Before this page was written, every route a visitor can reach was reviewed against a written rubric at two widths — nineteen routes, eleven findings, two of them security-grade, all fixed the same day — and then the storefront was refined against the company's own design principles: one accent, one display face, a shape language that says what can be pressed.
Every route a visitor can reach, reviewed at two widths against eight written checks: nineteen routes, eleven findings, all fixed the same day. Then seven design rules from the company's own principles, applied and verified the same way.
The intent is plain: build more of these, with increasing proficiency, and keep refining this one until it is a working part of the OPI brand.
Everything shown here is the storefront's own surfaces and templates, captured locally. The catalogue in the captures was seeded for them — real, current products, each with a freely licensed photograph from Wikimedia Commons, credited in the storefront — because the shop's own stock is between iterations. The account shown is a demonstration account; no customer, order or address appears; the email is the real template rendered with sample data, and says so.
Next — NMLS Document Repository →