Files
mozimo.in/.scratch/shopify-headless-commerce/plan.md
T
tanshu de0553d0d4 Wayfinder: chart the Shopify headless commerce map
The route from "mozimo.in displays Shopify products" to "mozimo.in sells them",
as a plan with a phase spine and gates, plus the open decision tickets that
still shape it and the evidence they rest on.

- .scratch/shopify-headless-commerce/: plan.md (phases and gates), map.md (the
  wayfinder map), 10 open decision tickets
- CONTEXT.md: Storefront / Theme store / Cart / Parity vocabulary
- docs/adr/0001-0003: Checkout stays Shopify-hosted, one Variant per product,
  the checkout domain stays shop.mozimo.in
- docs/research/ and docs/shopify-catalog-inventory.md: verified store facts,
  the Cart API probe, and the catalogue inventory

Raw Shopify doc scrapes under .scratch/shopify-research/ are ignored: they are
working material, not record.
2026-10-14 09:00:42 +05:30

139 lines
7.0 KiB
Markdown

# Shopify Headless Commerce — Plan
The phased route from "mozimo.in displays products from Shopify" to "mozimo.in sells
them", and the retirement of the theme store's pages.
This plan holds the spine and the gates. The open decisions inside each phase are
held as wayfinder tickets on `map.md` in this directory.
## Destination
A Storefront on which a buyer can assemble a Cart, review it, and complete a purchase —
with `shop.mozimo.in` reduced to the Checkout domain and its storefront pages retired.
## Settled constraints
Facts, verified against the live store and Shopify's documentation in October 2026.
Sources: [`docs/research/shopify-headless-commerce-2026-10.md`](../../docs/research/shopify-headless-commerce-2026-10.md),
[`docs/research/shopify-cart-probe-2026-10.md`](../../docs/research/shopify-cart-probe-2026-10.md),
[`docs/shopify-catalog-inventory.md`](../../docs/shopify-catalog-inventory.md).
| Constraint | Value |
| --- | --- |
| Production plan | **Grow** — checkout UI extensions and checkout branding are Plus-only, so custom checkout is unavailable by plan |
| Storefront API version | Pinned in code as `2025-01`, a retired version currently served as `2025-10`. Target is **2026-10** |
| Checkout | Shopify-hosted, reached via the Cart's `checkoutUrl`. The Storefront never renders it |
| Checkout host | **`shop.mozimo.in`** — store-level config, not the host the API is called on |
| Catalogue | **61 products**, each with **exactly one Variant**; sizes are separate products |
| Currency / market | Single currency **INR**, single country **IN**. No Markets complexity |
| Shipping | **India only.** `shipsToCountries` currently lists 29 destinations and disagrees with the published policy |
| Inventory | **Not tracked, and not wanted.** `availableForSale` is `true` for all 61 products, permanently |
| Gift cards | **None exist**, and none are queryable on the Storefront API |
| Customer accounts | **New** customer accounts — strongly indicated by the admin panel, not certain. The legacy sunset is still unannounced, so verify rather than assume |
| Carts | Not shared with the theme store, and cannot be — the Ajax API is theme-only |
| Catalogue seeding | The product CSV round-trips products and product **metafields** (definitions must exist first), but **cannot** carry collection membership — the `Collection` column is import-only and permits one collection per product |
| Cart limits | 500 lines per cart, 250 lines per request, expire after 30 days, deleted on checkout completion |
## Phase spine
Each phase ships independently. The gate is what makes it a phase rather than a task list.
### Phase 0 — Foundations
Prerequisites for anything that writes.
- Pin the Storefront API to `2026-10` and log `X-Shopify-API-Version` so drift is visible
instead of silent. Remove the stale `2025-01` comment about `predictiveSearch`.
- Carry the Variant GID and per-variant price in `ShopProduct` — an add-to-cart needs a
merchandise ID and there is none today.
- Send `Shopify-Storefront-Buyer-IP` on server-side calls.
- Standardise the credential path on the minted OAuth token.
- Shopify admin data fixes: shipping zones down to India only; populate `productType`
and weight tags so the collection filter chips and card weights stop reading nothing.
- Degraded mode: prefer stale cached real data over the Editorial catalog, and disable
buying when the Cart API is unreachable.
- Fix the broken `/products/rakhi-bark-box-200gm` link.
**Gate:** product and collection pages render as they do today, every product exposes a
Variant GID, and the served API version is `2026-10`.
### Phase 1 — Cart
- Shopify Cart API: create, add, update, remove, query.
- The Cart ID persisted in an httpOnly cookie, hydrated safely under SSR.
- Mini-cart drawer and a `/cart` page, with editable lines.
- Add-to-cart on the product page.
- Gift note captured as a Cart attribute.
- Analytics: `add_to_cart`, `view_cart`, `remove_from_cart`.
**Gate:** a guest can add, edit and remove; the subtotal is correct; the Cart survives a
reload and a browser restart.
### Phase 2 — Checkout handoff
- Redirect to the Cart's `checkoutUrl`.
- Fire `begin_checkout` with the real Cart.
- Handle price change and Cart expiry at handoff. Sold-out is not a reachable state.
- Verify an India address completes and a non-India address is refused.
- Complete at least one test-mode order through the Bogus Gateway.
**Gate:** a genuine test-mode order completes end-to-end from mozimo.in.
### Phase 3 — Commercial parity
- Surface the full 61-product catalogue.
- Discount code entry in the Cart. Whether any discount exists is unverifiable from the
Storefront API, so this is built against configuration, not against observed data.
- Gifting: wrap and delivery options beyond the Phase 1 gift note.
- Quick-add from collection grids.
- Close the content gaps that make product pages look broken at scale: 41 of 61 products
have no ingredients or nutrition, and `custom.tagline` is populated on exactly one.
- Rebuild collection pages against the 16 live collections.
**Gate:** the parity checklist is met and the Theme store adds nothing commercially.
### Phase 4 — Accounts
- Customer Account API: hosted login, order history, saved addresses.
- Retires the `shop.mozimo.in/account` handoff.
**Gate:** a customer can sign in and see their orders without leaving mozimo.in.
### Phase 5 — Retire the theme storefront
- `shop.mozimo.in` **stays attached to Shopify as the Checkout domain**. Checkout is
served from it, so the domain cannot be retired — only the Theme store's pages can.
- Redirect the theme's **storefront paths** only, leaving Cart and Checkout paths intact.
See [ADR-0003](../../docs/adr/0003-checkout-domain-stays-shop-mozimo-in.md).
- Channel audit: paid ads, shopping feeds, marketplace listings, printed QR codes.
- SEO: sitemap, canonicals, redirect coverage.
**Gate:** the theme's pages are retired, Checkout still resolves, and no channel depends
on the theme storefront.
## Out of scope
Work consciously ruled beyond this destination.
- **Fully on-domain checkout.** Plus-only. Revisit only via a plan upgrade, which would
be a fresh effort, not a resumption of this one.
- **Multi-currency and Shopify Markets.** One currency, one country.
- **Subscriptions and selling plans.** No product requires one.
- **Gift cards.** None exist in the store.
- **Inventory and stock display.** Explicitly not tracked and not wanted.
- **Customer account migration.** The store already uses new customer accounts, so there
is no legacy sunset to outrun.
## Open decisions
Held as tickets on `map.md` in this directory, wired with blocking edges.
- How the dev store is seeded from the live catalogue.
- Cart persistence and hydration design under SSR.
- What degraded mode looks like to a buyer.
- The gifting model: note, wrap, delivery date.
- Where the Cart lives in the UI, and what the mini-cart drawer must show.
- The parity checklist that gates Phase 5.
- What currently points at the Theme store.
- Whether the Storefront should absorb the catalogue's content gaps.