← All notes

The Tofte Wellness storefront, so far

Tofte Wellness is the supplement side of the portfolio, and MySenses is the product line under it. This is a recap of the storefront that got built for it, mostly the parts that are invisible if you are just looking at the site.

Being upfront about status first: the catalog is still placeholder listings. Real products go in through the admin, and they are not in yet. So this is a note about the build, not an announcement that you can go buy something.

The shape of it

Next.js on the App Router, MongoDB behind it for products, orders, and admin accounts, and Stripe Checkout handling payment. Storefront on one side, a session-protected admin dashboard on the other.

Nothing exotic. The interesting decisions are smaller than the stack.

Prices are looked up on the server

The checkout route never trusts a price sent from the browser. The client says which product, the server looks up what it actually costs, and the Stripe session is built from that.

This sounds obvious written down. It is also one of the most common ways storefronts get robbed: accept a price from the client, and someone edits it before it is sent. Worth doing right the first time rather than discovering it later.

Orders come from the webhook, not the redirect

When Stripe sends a customer back to the success page, that redirect is not proof that anything was paid. It is just a URL, and a URL can be visited directly.

So the order gets recorded when Stripe's webhook says the payment happened. The success page is only what the customer sees.

Admin sessions had to work in two runtimes

Session cookies are signed and verified with Web Crypto rather than a Node-only library. That was a deliberate constraint: middleware.ts runs on the Edge runtime, the admin API routes run on Node, and both need to verify the same cookie.

One implementation, two runtimes, no duplicated auth logic to drift apart.

It degrades instead of breaking

Two small things in that spirit. The catalog falls back to a seed list if MongoDB is not configured, so the site renders instead of erroring on a fresh checkout of the repo. The mailer logs and moves on when it has no credentials rather than throwing, so a missing env var does not take down order confirmation.

Neither is clever. Both save an afternoon at some point.

What is next

Real products in the catalog, then actual order flow with real inventory behind it. When there is something worth looking at, that will be its own post.