Foundations for the phases that write. The Storefront served a retired API
version (2025-01 was answered as 2025-10) and no product carried a merchandise
ID, so nothing could be carted.
- Pin the Storefront API to 2026-10 and log the version Shopify actually
served, so retired-version drift is visible instead of silent. Drop the
stale predictiveSearch comment.
- ShopProduct carries the Variant GID and per-variant price, replacing the
product-level price range with the Variant as the one source of truth.
Products without a Variant are dropped rather than shown uncartable.
- Send Shopify-Storefront-Buyer-IP from the buyer's request, and omit it when
no request is in scope (builds, scripts).
- Standardise on the minted OAuth token; the static storefront token is a
warned legacy fallback.
- Persist the last known-good payloads to disk beside the token cache, so a
Shopify outage serves stale real commerce data rather than the bundled
Editorial catalog. Verified against an unreachable store: a product absent
from the Editorial catalog still rendered from last-good data.
- Fix a latent 500: a failed OAuth mint threw out of gql (it ran outside the
try). Transport failures now report status 0 and gql fails closed.
- Point the seasonal Rakhi card at the gift collection; its
/products/rakhi-bark-box-200gm handle is dead and no Rakhi product remains.
POST / with a React server-actions header is not a request this app
makes — TanStack server functions POST to /_serverFn/<id>. Left alone
the transform stream sat open until the 120s lifetime timer force-cleaned
it, surfacing as a fatal uncaught exception in Sentry (event e267e264,
release 84dffa8). Now answered 404 in 9ms; normal pages unaffected.
- composed hero stays split ivory/copy + image; bonbons carry the
mustard/oxblood/copper of the r9 direction; Shop Chocolate opens
same-tab now
- preview mock shown and approved before this commit; swap again when
the r9 shoot lands
- collection_rows: hampers-boxes row (seed default + ensure-row migration);
/chocolate shows the button, /collections/hampers-boxes gets the two-tone
hero (last-word script rule) + live Shopify hampers + row blurb as lead
- gifting_page: tabs/hampers/seasonal heading fields (seed + fill-missing
migration, never overwrites admin edits); gifting.tsx consumes them
- site_settings: home seasonal + universe copy keys (seed + ensure-keys
migration); index loader passes them to SeasonalTeaser/UniverseSection
- hero lead on collection pages falls back to the PB row blurb
- www host: /_* and /api/* proxy to pocketbase :8090, everything else to
the TanStack app; redir /_ /_/ for the admin path
- cms host unchanged: redir / -> /_/
- migration: legacy per-host marker blocks are removed before the new
combined block is installed
- cms.ts: PB file urls are now same-origin relative (/api/files/...) —
browsers could never load the old 127.0.0.1:8090 urls; validated the
rendered Caddyfile with caddy:2
- snippet generation moved to a j2 template; per-host pb_root flag
- cms.mozimo.in emits 'redir / /_/' before reverse_proxy (pattern from
overlord's Caddyfile); other hosts unchanged
- snippets now update in place (blockinfile idempotency) instead of
skipping when the desired block changed
- Makefile builds from 'git archive HEAD' (stale-remote-HEAD impossible):
tags registry.tanshu.com/mozimo:<short-commit> + :main; build-check target
verifies both architectures without pushing
- deploy.sh: refuses dirty tracked tree / HEAD != origin/main (--force to
bypass), ff-only pull, passes the commit as image_tag to ansible,
--prune flag for opt-in image cleanup
- ansible: docker_image uses image_tag extra-var (falls back to tag),
prune task keeps the 3 newest mozimo images, mozimo-repo only