sbuilder-mcp 0.74.1 → 0.76.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -6,6 +6,16 @@ All notable changes to this project are documented in this file.
6
6
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
7
7
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
8
8
 
9
+ ## [0.76.0] - 2026-09-28
10
+
11
+ ### Added
12
+ - `sb_review` gains a `siteFooter` readiness gap: since `sb_store` action `chrome` builds the shared header and treats the footer as an opt-in flag on a separate call, a site built this way can end every page at its last section with no policy links, no contact, and no copyright line; it fires once the site already has at least one global section and two or more pages but no footer among them, pointing at `sb_store` action `chrome` with `footer:true`.
13
+
14
+ ## [0.75.0] - 2026-09-28
15
+
16
+ ### Added
17
+ - `sb_review` gains a `productImages` readiness gap: since the renderer falls back to its grey `ImagePlaceholder` whenever a node has no `src`, an active product created without `images` shows that same placeholder on every card, cart line, and its own product page with nothing erroring anywhere; it counts active products with no non-empty `images` entry and fires after the pricing gaps, pointing at `sb_media_upload` (or `POST /api/media/{siteId}/from-url`) followed by a `PUT` of the product with `images: [url, …]`.
18
+
9
19
  ## [0.74.1] - 2026-09-28
10
20
 
11
21
  ### Fixed
package/CHANGELOG.vi.md CHANGED
@@ -6,6 +6,16 @@ Mọi thay đổi đáng chú ý của dự án được ghi lại trong file n
6
6
  Định dạng dựa trên [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
7
7
  và dự án tuân theo [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
8
8
 
9
+ ## [0.76.0] - 2026-09-28
10
+
11
+ ### Added
12
+ - `sb_review` có thêm gap readiness `siteFooter`: vì `sb_store` action `chrome` dựng header dùng chung còn footer là một cờ tùy chọn ở một lệnh riêng, một site dựng theo cách này có thể khiến mọi trang kết thúc ở section cuối cùng, không có link chính sách, không có liên hệ, không có dòng bản quyền; gap báo khi site đã có ít nhất một global section và từ hai trang trở lên nhưng không trang nào có footer, trỏ tới `sb_store` action `chrome` với `footer:true`.
13
+
14
+ ## [0.75.0] - 2026-09-28
15
+
16
+ ### Added
17
+ - `sb_review` có thêm gap readiness `productImages`: vì renderer dùng `ImagePlaceholder` màu xám mặc định bất cứ khi nào một node không có `src`, một sản phẩm active được tạo mà không có `images` sẽ hiện cùng ô xám đó trên mọi thẻ, mọi dòng giỏ hàng và trên chính trang sản phẩm mà không lỗi ở đâu cả; gap đếm số sản phẩm active không có mục `images` nào khác rỗng và báo sau các gap về giá, trỏ tới `sb_media_upload` (hoặc `POST /api/media/{siteId}/from-url`) rồi `PUT` lại sản phẩm với `images: [url, …]`.
18
+
9
19
  ## [0.74.1] - 2026-09-28
10
20
 
11
21
  ### Fixed
@@ -110,6 +110,9 @@ export async function gatherReadiness(ctx, siteId, pageNodes, openPageId) {
110
110
  purchasable: rows.filter((p) => (p.status ?? 'active') === 'active' && (p.priceCents ?? 0) > 0).length,
111
111
  // Drafts and archived: what a catalogue built without status:"active" is.
112
112
  inactive: rows.filter((p) => (p.status ?? 'active') !== 'active').length,
113
+ // Active and pictureless: the grey placeholder on every card.
114
+ unpictured: rows.filter((p) => (p.status ?? 'active') === 'active' &&
115
+ !(Array.isArray(p.images) && p.images.some((u) => typeof u === 'string' && u !== ''))).length,
113
116
  }
114
117
  : null;
115
118
  // A page an entity links to is that entity's own; only the shared template
@@ -217,6 +217,29 @@ export function readinessGaps(input) {
217
217
  'globalRef instead of a copy, and one edit reaches every page.',
218
218
  });
219
219
  }
220
+ // A HEADER AND NO FOOTER.
221
+ //
222
+ // `sb_store action:"chrome"` builds the header; the footer is an opt-in flag
223
+ // on the same call, so a site built here has a shared header and, on every
224
+ // page, either its own footer or none — no policy links, no contact, no
225
+ // copyright line, and nothing below the last section but the end of the
226
+ // document. The same threshold as siteChrome, asked only once the site HAS
227
+ // shared chrome (an empty list is siteChrome's finding, not this one).
228
+ if (pages &&
229
+ pages.length >= 2 &&
230
+ input.globalKinds &&
231
+ input.globalKinds.length > 0 &&
232
+ !input.globalKinds.includes('footer')) {
233
+ gaps.push({
234
+ id: 'siteFooter',
235
+ draft: false,
236
+ problem: 'The site shares a header and no footer, so every page ends at its last section — ' +
237
+ 'no policy links, no contact, no copyright line, and each page that has a footer of ' +
238
+ 'its own drifts from the next.',
239
+ fix: 'sb_store action:"chrome" footer:true builds one shared footer on a real site menu and ' +
240
+ 'attaches it to every page. Put the policy, contact and about pages in it.',
241
+ });
242
+ }
220
243
  // THE SITE IS DARK RIGHT NOW AND SAYING NOTHING IN ITS OWN VOICE.
221
244
  //
222
245
  // Reported FIRST, because it is the only finding here that is not about what
@@ -558,6 +581,26 @@ export function readinessGaps(input) {
558
581
  });
559
582
  }
560
583
  }
584
+ // A CARD WITH THE PLATFORM'S GREY SQUARE WHERE THE PHOTO GOES.
585
+ //
586
+ // render/nodes/image/html.go: no src → nodes.ImagePlaceholder, "a card
587
+ // instead of a broken icon". So a product created without `images` renders
588
+ // on every card, in every drawer line and on its own page as the same grey
589
+ // placeholder — nothing errors, and a catalogue of twenty reads as a
590
+ // template nobody finished. Asked after the money questions: a store with
591
+ // no photos still takes an order.
592
+ if (input.products && input.products.active > 0 && (input.products.unpictured ?? 0) > 0) {
593
+ const n = input.products.unpictured;
594
+ gaps.push({
595
+ id: 'productImages',
596
+ draft: false,
597
+ problem: `${n} of ${input.products.active} active products have no image, so every card, cart ` +
598
+ "line and product page shows the platform's grey placeholder where the photo goes.",
599
+ fix: 'Get a picture into the library (sb_media_upload: a file, a url, or query + pick), then ' +
600
+ 'PUT the whole product back with images: [url, …] — first is the primary. POST ' +
601
+ '/api/media/{siteId}/from-url ingests straight from a url in one hop.',
602
+ });
603
+ }
561
604
  if (input.shippingMethods === 0) {
562
605
  gaps.push({
563
606
  id: 'shipping',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sbuilder-mcp",
3
- "version": "0.74.1",
3
+ "version": "0.76.0",
4
4
  "description": "MCP server that designs and operates a Store Builder site — pages, data, theme and publish — through the platform's own API and live-edit protocol.",
5
5
  "mcpName": "io.github.vuluu2k/sbuilder-mcp",
6
6
  "type": "module",