webcake-landing-mcp 1.0.44 → 1.0.46

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.
@@ -1,4 +1,18 @@
1
1
  [
2
+ {
3
+ "v": "1.0.46",
4
+ "d": "09/06/2026",
5
+ "type": "Changed",
6
+ "en": "validate_page now emits an advisory warning when no section, button, or text on the page carries a non-neutral color (white, black, or grey),…",
7
+ "vi": "validate_page nay phát cảnh báo tư vấn khi không có section, button hay text nào trên trang mang màu thực sự (không phải trắng, đen hoặc xám), giúp…"
8
+ },
9
+ {
10
+ "v": "1.0.45",
11
+ "d": "09/06/2026",
12
+ "type": "Changed",
13
+ "en": "get_generation_guide workflow condensed to four steps: element-type reads and image fetches are now batched into single calls…",
14
+ "vi": "Workflow trong get_generation_guide được rút gọn xuống còn bốn bước: việc đọc loại phần tử và tìm ảnh nay được gộp thành các lần gọi batch duy nhất…"
15
+ },
2
16
  {
3
17
  "v": "1.0.44",
4
18
  "d": "09/06/2026",
@@ -26,19 +40,5 @@
26
40
  "type": "Changed",
27
41
  "en": "get_generation_guide and server instructions now require the agent to write all page copy in the same language the user is chatting in, with full,…",
28
42
  "vi": "get_generation_guide và hướng dẫn server nay yêu cầu agent viết toàn bộ nội dung trang bằng cùng ngôn ngữ người dùng đang nhắn tin, với đầy đủ dấu…"
29
- },
30
- {
31
- "v": "1.0.40",
32
- "d": "09/06/2026",
33
- "type": "Added",
34
- "en": "New ingest_html tool parses an HTML string into a compact reference AST (~2–5KB) that classifies sections by role (header, hero, features, form,…",
35
- "vi": "Công cụ ingest_html mới phân tích cú pháp một chuỗi HTML thành AST tham chiếu thu gọn (~2–5KB) phân loại các section theo vai trò (header, hero,…"
36
- },
37
- {
38
- "v": "1.0.39",
39
- "d": "08/06/2026",
40
- "type": "Internal",
41
- "en": "Added server.json MCP Registry manifest (namespace io.github.vuluu2k/webcake-landing-mcp) and the corresponding mcpName field in package.json so the…",
42
- "vi": "Thêm manifest MCP Registry server.json (namespace io.github.vuluu2k/webcake-landing-mcp) và trường mcpName tương ứng trong package.json để MCP…"
43
43
  }
44
44
  ]
@@ -84,7 +84,7 @@ PREMIUM CRAFT (what separates a polished page from an amateur one — apply to E
84
84
  - CTA WEIGHT: the primary button is the heaviest thing on its band — accent background, bold label, generous padding (height ~46–52), the same radius used everywhere else.
85
85
 
86
86
  SECTION BUILD HINTS (apply to whichever sections the chosen archetype uses)
87
- - Each section is one visual band: height that comfortably holds its content (taller on mobile since things stack), background that contrasts its text.
87
+ - Each section is one visual band: height that comfortably holds its content (taller on mobile since things stack), and a background that contrasts its text. SET responsive.<bp>.styles.background ON EVERY SECTION (both breakpoints) — the section factory default has NO background, so a section you leave unset renders transparent/white and the whole page looks colorless. Pull each band's background from the locked PALETTE and alternate them (light / tinted / dark) so consecutive bands read as distinct, never a flat white wall.
88
88
  - HEADER — logo/brand at the page's LEFT margin (left=80 desktop / 20 mobile), nav/CTA flush to the RIGHT margin (its left = canvas − margin − width, so its right edge lands on 880 desktop / 400 mobile). Use the SAME margin as every section below — do NOT center the logo or invent a new left; a header on a different axis than the bands under it is the #1 header defect. Put every header child on ONE shared vertical centerline: match top + height/2 across the logo, brand text, and CTA button so nothing sits higher/lower than the rest.
89
89
  - HERO — always a clear H1, a short supporting line, and the primary CTA visible without scrolling.
90
90
  - FEATURES / BENEFITS — a row of equal cards (icon + title + text) or a 2-column list. Center the row with the ROW math; on mobile shrink to one canvas width or stack.
@@ -57,6 +57,45 @@ function num(v) {
57
57
  }
58
58
  return undefined;
59
59
  }
60
+ /**
61
+ * True when a CSS color string carries real hue — i.e. NOT white/black/grey/
62
+ * transparent. Used to flag a page that ships with no color at all (every band
63
+ * white/neutral, no accent), which renders flat/"colorless". A gradient or image
64
+ * background counts as color. Neutrals (white/black/grey) have ~0 channel spread.
65
+ */
66
+ function isVividColor(v) {
67
+ if (typeof v !== "string")
68
+ return false;
69
+ const s = v.trim().toLowerCase();
70
+ if (!s || s === "transparent" || s === "none" || s === "inherit")
71
+ return false;
72
+ if (s.includes("gradient") || s.startsWith("url("))
73
+ return true;
74
+ let r, g, b, a = 1;
75
+ const rgba = s.match(/rgba?\(([^)]+)\)/);
76
+ if (rgba) {
77
+ const parts = rgba[1].split(",").map((x) => parseFloat(x.trim()));
78
+ [r, g, b] = parts;
79
+ if (parts.length >= 4 && Number.isFinite(parts[3]))
80
+ a = parts[3];
81
+ }
82
+ else {
83
+ const hex = s.match(/^#([0-9a-f]{3}|[0-9a-f]{6})$/);
84
+ if (!hex)
85
+ return false;
86
+ let h = hex[1];
87
+ if (h.length === 3)
88
+ h = h[0] + h[0] + h[1] + h[1] + h[2] + h[2];
89
+ r = parseInt(h.slice(0, 2), 16);
90
+ g = parseInt(h.slice(2, 4), 16);
91
+ b = parseInt(h.slice(4, 6), 16);
92
+ }
93
+ if (![r, g, b].every((n) => Number.isFinite(n)))
94
+ return false;
95
+ if (a <= 0.05)
96
+ return false; // fully transparent
97
+ return Math.max(r, g, b) - Math.min(r, g, b) >= 16; // channel spread ⇒ has hue
98
+ }
60
99
  /** Accept an object or a JSON string. Returns the parsed page or throws. */
61
100
  export function coercePage(input) {
62
101
  if (typeof input === "string")
@@ -90,6 +129,9 @@ export function validatePage(input) {
90
129
  // form nodes — used to check field_name uniqueness within each form's scope
91
130
  const forms = [];
92
131
  let elementCount = 0;
132
+ // Whether ANY element (section, button, text…) carries real color on either
133
+ // breakpoint. A page where this stays false renders flat/colorless (warned once).
134
+ let anyVividColor = false;
93
135
  const topList = Array.isArray(page?.page)
94
136
  ? page.page
95
137
  : page?.page
@@ -117,6 +159,20 @@ export function validatePage(input) {
117
159
  if (!node.responsive?.desktop || !node.responsive?.mobile) {
118
160
  errors.push(`${path} (${type}): must have responsive.desktop AND responsive.mobile.`);
119
161
  }
162
+ // does this element put any real color on the page? (background / text / border)
163
+ if (!anyVividColor) {
164
+ for (const bp of ["desktop", "mobile"]) {
165
+ const st = node.responsive?.[bp]?.styles;
166
+ if (st &&
167
+ (isVividColor(st.background) ||
168
+ isVividColor(st.backgroundColor) ||
169
+ isVividColor(st.color) ||
170
+ isVividColor(st.borderColor))) {
171
+ anyVividColor = true;
172
+ break;
173
+ }
174
+ }
175
+ }
120
176
  // children only on containers
121
177
  if (Array.isArray(node.children) && node.children.length > 0 && type && !CONTAINER_TYPES.has(type)) {
122
178
  errors.push(`${path} (${type}): has children but "${type}" is not a container type.`);
@@ -383,6 +439,12 @@ export function validatePage(input) {
383
439
  warnings.push(`Sections start on different left margins (${list}). Put every band's left-anchored content (the header logo included) on ONE shared left axis — e.g. left=${minEdge} desktop — so the page reads aligned, not ragged. This is the #1 header-misalignment defect.`);
384
440
  }
385
441
  }
442
+ // 3c) Colorless page — nothing on the page carries real color (every band/button/
443
+ // heading is white/black/grey). Sections have NO default background, so a page
444
+ // that never sets one renders as a flat white wall. Advisory only.
445
+ if (topList.length >= 2 && elementCount >= 3 && !anyVividColor) {
446
+ warnings.push(`Page has no color — no section background, button, or text uses a non-neutral color, so it renders as a flat white/grey wall. Set responsive.<bp>.styles.background on each section (alternate light/tinted/dark from the palette) and give the primary CTA an accent background. If a stark black-and-white look is intentional, ignore this.`);
447
+ }
386
448
  popups.forEach((p, i) => {
387
449
  const ds = p?.responsive?.desktop?.styles ?? {};
388
450
  const ms = p?.responsive?.mobile?.styles ?? {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webcake-landing-mcp",
3
- "version": "1.0.44",
3
+ "version": "1.0.46",
4
4
  "description": "MCP server exposing Webcake landing-page element schemas + AI usage hints, and persisting LLM-generated page sources to a Webcake backend.",
5
5
  "mcpName": "io.github.vuluu2k/webcake-landing-mcp",
6
6
  "type": "module",