cbd.domains

Before / After · Case Study

Big Moose Hemp: Wix Platform Prison to Headless Medusa

Big Moose Hemp migrated from a locked-in Wix storefront to a fully-owned headless architecture — Medusa 2.x commerce backend on Railway + Next.js 15 storefront on Vercel, live at new.bigmoosehemp.com. The rebuild was forced by a hard regulatory deadline: the November 12, 2026 federal hemp ban (P.L. 119-37) that outlaws ~86% of the current catalog, making Wix's V1 schema, deprecated APIs, and single payment rail a business blocker. A three-phase compliance strategy (Liquidation → Sunset → Post-ban) is baked into the schema so the cutoff is driven by per-SKU total-THC data, not a midnight content edit. The team shipped 551 TypeScript files across 229 commits with complete parity to legacy order/customer data (142 historical Wix orders materialized + a consent-stratified 23,924-contact archive), compliance automation (total-THC per SKU, state ship-block enforcement), real payment rails (Clover high-risk processor), an IMAP-verified transactional email + SMS chain, a live Medusa-backed mobile admin, and a 24/7 Slack-fed AI approval queue where agents draft and only the owner ships. The same backend that started as a survival migration is now the operating spine for the whole brand.

When the legal catalog shrinks 86% on a fixed date, the platform has to know which SKU is on which side of the line — and Wix never could.
🔒https://new.bigmoosehemp.com
jackiej.events — modern site

Receipts — measured

Numbers that moved.

0%
Catalog removed by P.L. 119-37 on Nov 12 2026
was 0%
0orders
Historical Wix orders materialized into Medusa
was 0orders
0products
SKUs migrated off Wix V1
was 0products
0
Legacy Wix contacts audited + stratified
was 0
0
Bulk-import contacts quarantined CRM-only (TCPA/CAN-SPAM safe)
was 0
43
Manual SKU sweeps required on Nov 12
was 43
  • 229 commits from Apr 19 → Jun 30, 2026
  • 142 historical Wix orders + 16,881 customers migrated with consent
  • 551 source files (TS/TSX); 8 test suites
  • Live at new.bigmoosehemp.com (Vercel) + Railway backend

The pixel diff

Overview, then the walkthrough.

Left: everything the legacy site shipped — frozen in place. Right: an auto-scrolling tour of the rebuild, from hero to booking. No slider to fight with.

Before — the overview
🔒https://bigmoosehemp.com
Before — the overview

This is everything the legacy site had to offer above the fold. No pricing, no calendar, no booking — the funnel ended at a mailto.

After — scroll through what shipped
🔒https://new.bigmoosehemp.com
After — scroll through what shipped

Auto-scrolls through the modern site so you can see the booking surface, the package grid, the pricing table, and the calendar inline — without leaving this page.

The four beats

Problem · Insight · Build · Outcome.

Scroll past the legacy frame. The four beats land in order. At the end, the modern site fades into the same window.

🔒https://bigmoosehemp.com
Legacy
01 · Problem

A platform about to lose 86% of its legal catalog on a fixed date

Wix's V1 catalog, deprecated blog API, and locked-in schema couldn't support the structural work needed to survive the November 12, 2026 federal hemp ban (P.L. 119-37). THCa + THCP + Δ9 gummies become Schedule I substances under the new total-THC rule, and Wix exposed neither the compliance controls nor the payment-policy controls the pivot required. The runway to ship a new stack and rebuild the product line was 207 days.

02 · Insight

Make the cutoff a data fact, not a content edit

Farm Bill hemp (≤0.3% Δ9) is shippable via card networks; post-ban legality turns on total-THC per SKU. Compute that bright line once at migration, store it on the product, and query it at runtime. The Phase 2 cutoff becomes a flag flip, not a 43-SKU hand sweep at midnight on Nov 11 — and a headless rebuild can separate the compliant and non-compliant paths at the database and checkout layer.

03 · Build

Medusa 2.x backend + Next 15 storefront + total-THC pipeline

Why Medusa: MIT-licensed, owns the data model, plugin ecosystem for payments + shipping. Why Next.js 15: RSC + ISR for SEO, Vercel-native, every file AI-editable. The migration script computes total-THC for every Wix SKU before it lands in Medusa; AlpineIQ + Klaviyo + Bland keep the messaging surfaces running off the customer table. 551 TypeScript files across 229 commits, 8 test suites, with a kill-switch (BMH_SUPPRESS_ALL_SIDE_EFFECTS) to prevent double-notifies during migration.

04 · Outcome

new.bigmoosehemp.com live; the cutoff is one query, not 43 delistings

Storefront deployed to Vercel (prj_dgfmPr43RnP17MDG1Ac0hnvP5HZT); Medusa backend on Railway (reliable-prosperity). Compliance automation — total-THC calculator, state ship-blocks, container-cap audits, dynamic sitemap filtering — is live. Clover Ecommerce (sandbox) is wired; production MID awaits GPS ISO approval and real orders remain gated while the kill-switch stays on for Wix-archive orders. DNS cutover to apex bigmoosehemp.com is pending Brendon's approval; the legacy Wix site is still live at the apex.

05 · Compounding

The same backend now runs marketing, sales, CS, and a 24/7 approval crew

Once the catalog lived in Medusa, every adjacent surface got to share it. Retention reads the customer table; transactional comms fire off order events; a live JWT-bridged mobile admin shows orders and timelines; and a Slack-fed AI approval queue lets staff and agents propose content and design changes around the clock while the owner keeps the only key that ships anything live. Each agent runs a narrow, named job on real data and hands edge cases to a human queue — so the system gets more capable without the agents losing the plot.

🔒https://new.bigmoosehemp.com
Modern

Architecture

One chain replaced by another. Receipts above.

Old stack
  • Black-box page builder
  • Wix V1 catalog + deprecated blog API
  • Wix subscriber list (locked in)
  • Wix dashboard (no API, no mobile ops)
  • Square via WIX-PAY-PRO (single rail)
  • No automation, no approval workflow
New stack
  • Fully owned TypeScript/React code (AI-editable day 1)
  • Medusa 2.x + Neon Postgres + Upstash Redis
  • Customer table → AIQ v2 SMS + Resend/SES/Stalwart email
  • Live JWT-bridged admin (orders, timeline, mobile PWA)
  • Clover high-risk rail (Aeropay backup; Phase-2 Stripe planned)
  • Slack-ingested AI approval queue, owner-gated promotion
  • Custom compliance automation + SEO via ISR + RSC

What changed

Grouped by what kind of system shipped.

Each claim ships with concrete evidence — env vars, table names, cadence chips. No marketing fluff.

Design

Compliance automation by law — the cutoff is a query, not a sweep

Each SKU's total-THC fraction (total = THCa × 0.877 + Δ9 + synthetics) is computed once at Wix → Medusa migration time and stored on the product. The Phase 2 Sunset cutoff is a database query — WHERE total_thc <= 0.003 — not a hand-curated list, so there is no room for a missed delisting on Nov 12. State ship-blocks (HI/ID/IA/MS/NH/SD) and container-cap audits run at every add-to-cart and checkout.

Before
Wix had no cannabis-specific compliance tooling; Brendon manually tracked SKU legality
After
Medusa workflows reject non-compliant SKUs at the API level, surfacing inline errors to the customer UI
Retention

142 historical orders + a consent-stratified customer archive

Exported the Wix order transaction API and materialized 142 orders (#10001–10142) into Medusa Postgres with exact payment/fulfillment history. 16,881 email / 11,354 phone / 7,043 phone-only SMS customers were migrated to Medusa + Neon ops DB with import-source=wix_archive tags and full consent preservation. Separately, all 23,924 legacy Wix contacts were audited and classified into five legal tiers; only 116 cleared as marketable, while 16,712 bulk-import leads were written CRM-only (crm_only=true) so no Klaviyo/AIQ sync ever touches them. CAN-SPAM/TCPA compliance is a column, not a promise.

Before
Wix warehouse; orders + subscribers live only on Wix (not portable)
After
Orders + customers live in Medusa/Neon, queryable, archivable, consent-tiered
  • 142 orders (#10001–10142) live in Medusa Postgres, queryable and not dependent on Wix
  • 23,924 contacts audited via the Wix Contacts v4 API; 116 green-tier marketable; 0 red-tier ever written
  • Stratifier: scripts/wix-customer-import-stratified.ts (5-tier classifier)
Retention

Three-phase strategy baked into the schema

Phase 1 (Liquidation, Apr 19 → Oct 31): full catalog on current rails. Phase 2 (Sunset, Nov 1–11): only compliant SKUs visible, fallback payment rail. Phase 3 (Post-ban, Nov 12 →): adaptogen coffee + CBD/CBG wellness + compliant smokable hemp. The phase is a runtime flag; product visibility, payment rail, and compliance copy all consult it — so the pivot is a flag flip, not a content emergency.

Before
Wix had no concept of a future-dated catalog cutover
After
A runtime phase flag drives visibility, payment rail, and compliance copy in lockstep
Agent backbone

A Slack-driven, human-gated approval pipeline — agents draft, the owner ships

Staff and superusers queue content and design work into Slack; a 5-minute cron ingests it, an AI classifier routes it into one of eight action kinds across two review lanes, and nothing reaches a customer or production without a human tap. Content drafts (SMS/email/blog) wait on the brand owner; site-design changes assemble a Vercel preview and wait on the account owner to promote. The agents operate on real store data and hand edge cases to a review queue instead of guessing.

Before
Wix inbox locked; no AI assistance; no custom order-approval workflows
After
In-house chat + email threading; AI-classified approval queue; ops queue visible in admin
  • Neon bmh-storefront-ops: triage_queue, superuser_uploads, design_requests, approval_audit
  • canPromoteToProd() = owner-only hard gate, re-checked server-side on every ship action
  • Every state transition written to an append-only approval_audit table
  • Wix inbox port (PR #70): live-visitor presence + multi-threaded email (Wix-parity)
Real-time push

Order → confirmed → shipped → delivered, verified end-to-end to a real inbox

The transactional spine isn't a stub. An order fires confirmation, shipping (with carrier tracking), and delivery emails — each rendered, sent, and confirmed landing in a real IMAP inbox. The send path is Resend → AWS SES → a self-hosted Stalwart mail server on verified domains. Customer SMS rides AlpineIQ's v2 transactional endpoint, consent-gated against AIQ's own opt-out suppression so it never texts a stranger.

Before
Square-via-WIX-PAY-PRO with email-only, platform-controlled comms
After
Direct Clover REST + 3 IMAP-verified transactional emails + consent-gated SMS
  • 3/3 lifecycle emails delivered + IMAP-confirmed (Resend → SES → Stalwart)
  • AIQ migrated off dead v1.1 → POST /api/v2/sms + GET /api/v2/loyalty/lookup
  • Order-placed webhook fans out: email + consent-gated SMS + AIQ retention tag
  • SES bounce/complaint → identity suppression, fail-closed
Real-time push

Payment processor escape from Square via Wix

Clover high-risk processor (hemp-friendly ISO reseller) is wired as primary with Aeropay (ACH) as backup; Square is abandoned. Medusa payment modules handle tokenization, capture, void, and webhook reconciliation; a Phase-2 Stripe rail is planned through the same abstraction. Sandbox creds are wired; production MID awaits GPS ISO approval.

Before
Square-via-WIX-PAY-PRO (subject to platform bans during reputational cycles)
After
Direct Clover REST integration; full SLA and risk control owned by Brendon
Design

An operating surface, not just a storefront — live Medusa-backed admin on mobile

The old store had a Wix dashboard. The rebuild has an admin that reads live from Medusa over a Bearer-JWT bridge: orders with payment + fulfillment status pills, a per-order activity timeline (placed/paid/shipped/delivered), search and filters, and an iOS-style bottom nav so it runs as an installable PWA from a phone. A customer preferences page round-trips consent to the cross-brand OG.Life identity layer so a shopper never opts in four times. Every component, page, and workflow is TypeScript in git — 76 storefront pages + 38 backend modules, AI-editable from day one.

Before
Wix drag-and-drop; custom code required Wix HTML-widget knowledge
After
Next.js App Router + RSC; shadcn/ui; Tailwind; Medusa workflows in TypeScript
  • /admin/orders renders 'Live from Medusa' over admin.bigmoosehemp.com (JWT-authed)
  • Per-order timeline + status pills + search/filter; mobile bottom-nav PWA
  • /preferences/[token] ↔ OG.Life biz-preferences webhook (HMAC-signed)
  • 76 storefront pages + 38 backend modules; no page-builder black box
Retention

SEO parity maintained via 301s + ISR

Wix URLs redirect to Medusa equivalents (generated by scripts/generate-301-redirects.ts). ISR (revalidate: 3600) + RSC drive SEO, and a dynamic sitemap filters by compliance phase after Nov 12. A middleware-owned redirect map prevents losing organic equity through the platform change.

Before
Wix-hosted URLs with Wix domain authority; risk of lost traffic on platform change
After
Owned domain; ISR caching; 301-protected old URLs; dynamic compliance filtering in sitemap

While she sleeps.

Autonomous surfaces

The agent backbone keeps the brand earning between gigs. Jackie approves; the system runs.

  • Tags SKUs by phase eligibility at migration time

    once per SKU at migration; queried on every page render

    Per-SKU total-THC is computed during the Wix → Medusa migration and stored on the product. Phase visibility is a single query (WHERE total_thc <= 0.003) at runtime.

  • Keeps the messaging surfaces decoupled from the catalog

    continuous

    AlpineIQ (SMS), Klaviyo (email), and Bland (outbound voice) all read from the Medusa customer table. The audience survives the catalog pivot.

  • Ingests Slack into a triaged approval queue

    every 5 minutes

    Staff and superusers post content/design work into Slack; a cron pulls new messages, an AI classifier sorts them into eight action kinds and two review lanes, and items wait for human approval — content for the brand owner, design for the account owner.

  • Fires the transactional + retention chain on every order

    per order; instant

    An order event fans out: confirmation/shipping/delivery email (Resend → SES → Stalwart), consent-gated AIQ SMS, and a retention tag write (bmh_customer, order_placed_YYYY_MM) so segmentation builds itself.

  • Suppresses bounced + complained identities automatically

    continuous, event-driven

    SES bounce/complaint events route to an identity-suppression handler that fails closed — a hard-bounced or complaining address can never be re-marketed, no human in the loop required.

← All rebuilds

Big Moose Hemp: Wix Platform Prison to Headless Medusa — cbd.domains