What to build
Several Shopify data fetchers run inside 'use cache' boundaries but emit no cacheTag / cacheLife. Their callers cache by content hash and rely solely on cacheLife('max') for expiry. Webhook-driven invalidation cannot reach them — when a shop admin edits a vendor, the cached storefront copy persists until the cache simply ages out.
Sites missing tags:
apps/storefront/src/api/shopify/brand.ts:64-65 — api.query(BRAND_QUERY) has no tags
apps/storefront/src/api/shopify/vendor.ts:62-63 — api.query(VENDORS_QUERY) has no tags
apps/storefront/src/api/_loaders.ts:52-57 — BlogApi, ArticleApi, HeaderApi, FooterApi, InfoBarApi use react.cache() only; the safeCacheTag pattern that ProductApi (line 38) and CollectionApi (line 45) use is missing
Reference shape: apps/storefront/src/api/shopify/search.ts:110-123 (cacheLife('hours') + cacheTag(...) with shop+locale keys).
Acceptance criteria
Blocked by
None — can start immediately.
References
apps/storefront/src/api/shopify/brand.ts:64
apps/storefront/src/api/shopify/vendor.ts:62
apps/storefront/src/api/_loaders.ts:52
apps/storefront/src/api/shopify/search.ts:110 — reference impl
apps/storefront/src/app/[domain]/api/revalidate/
What to build
Several Shopify data fetchers run inside
'use cache'boundaries but emit nocacheTag/cacheLife. Their callers cache by content hash and rely solely oncacheLife('max')for expiry. Webhook-driven invalidation cannot reach them — when a shop admin edits a vendor, the cached storefront copy persists until the cache simply ages out.Sites missing tags:
apps/storefront/src/api/shopify/brand.ts:64-65—api.query(BRAND_QUERY)has notagsapps/storefront/src/api/shopify/vendor.ts:62-63—api.query(VENDORS_QUERY)has notagsapps/storefront/src/api/_loaders.ts:52-57—BlogApi,ArticleApi,HeaderApi,FooterApi,InfoBarApiusereact.cache()only; thesafeCacheTagpattern thatProductApi(line 38) andCollectionApi(line 45) use is missingReference shape:
apps/storefront/src/api/shopify/search.ts:110-123(cacheLife('hours')+cacheTag(...)with shop+locale keys).Acceptance criteria
cacheTagkeyed by shop + locale (and entity id where applicable)cacheLife(e.g.'hours'for content,'max'for static-ish data)cacheTagMockis called with the expected tags — mirror the pattern insearch.test.tsrevalidate/route.ts)Blocked by
None — can start immediately.
References
apps/storefront/src/api/shopify/brand.ts:64apps/storefront/src/api/shopify/vendor.ts:62apps/storefront/src/api/_loaders.ts:52apps/storefront/src/api/shopify/search.ts:110— reference implapps/storefront/src/app/[domain]/api/revalidate/