AppRouter replaces the single-page App as the mounted root: shop routes
(/ and /shop → ShopHome, /shop/:productSlug → ProductPage, /cart →
CartStub, /customize → CustomizeRoute) plus the template-manager admin
surfaces (/admin/templates|products|featured|trash, v0.8 adds
/admin/inventory + RequireAdmin wrapping). App.jsx stays on disk one
release as the documented legacy fallback — nothing imports it.
New shop UI: components/shop/ (ShopHome/Hero/ProductGrid/ProductCard/
ProductPage/ProductGallery/ProductInfo/ProductBuyPanel/CartStub/
ShopHeader/TemplateGalleryForProduct), hooks (useShopProducts/
useShopProduct/useCart/useFacetCatalog), and shop.css + admin.css.
Header gains the module-gated Clear button (onCanClearChange /
onElementCountChange mirror the editor module's history-commit
signals); i18n keys follow. vite proxies /products to the Node server
(template-manager serves product imagery — without it the SPA fallback
returns index.html as an image) and adds a template-manager chunk.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The host no longer carries a runtime product catalog. products.js
shrinks to a legacy single-product stub; the canonical catalog lives in
template-manager's productsStore, seeded ONCE on first boot from the
new seedProducts.js (after that the store under templates/ is
authoritative and the seed is ignored — intentional, so restarts never
rewrite an admin-managed catalog). phoneModels.js and
templateCategories.js are the supporting constant sets, and
docs/template-schema.md documents the v4 schema.
templates/ is the admin-managed store itself (_products_index.json +
products/<id>/product.json, JSON only) — committed so the configured
catalog (sizes, pricing, options built up in the admin UI) survives a
fresh checkout rather than regressing to the seed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>