webcake-landing-mcp 1.0.22 → 1.0.24

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.24",
4
+ "d": "07/06/2026",
5
+ "type": "Changed",
6
+ "en": "The numbered installation steps on the GET / guide page now display a faint vertical connector line between step numbers, giving the list a clear…",
7
+ "vi": "Các bước cài đặt được đánh số trên trang hướng dẫn GET / nay hiển thị đường kết nối dọc mờ giữa các số thứ tự, tạo giao diện stepper rõ ràng."
8
+ },
9
+ {
10
+ "v": "1.0.23",
11
+ "d": "07/06/2026",
12
+ "type": "Added",
13
+ "en": "The GET / guide page now includes a dark/light theme toggle button in the header; the preference is saved in localStorage and applied before the…",
14
+ "vi": "Trang hướng dẫn GET / nay có nút chuyển chế độ sáng/tối trong header; lựa chọn được lưu vào localStorage và áp dụng trước khi trang hiển thị để…"
15
+ },
2
16
  {
3
17
  "v": "1.0.22",
4
18
  "d": "07/06/2026",
@@ -26,19 +40,5 @@
26
40
  "type": "Changed",
27
41
  "en": "get_generation_guide now includes a Section Playbook block that lists a common section menu for lead-gen and COD sales pages (header, hero,…",
28
42
  "vi": "get_generation_guide nay có thêm khối \"Section Playbook\" liệt kê bộ section thường dùng cho trang thu lead và bán hàng COD (header, hero, tính…"
29
- },
30
- {
31
- "v": "1.0.18",
32
- "d": "07/06/2026",
33
- "type": "Changed",
34
- "en": "new_element for list-product now seeds a default styles.colorBtn (rgba(246,4,87,1)) so generated product-list button labels have a visible accent…",
35
- "vi": "new_element cho list-product nay gán sẵn styles.colorBtn mặc định (rgba(246,4,87,1)) để nhãn nút của danh sách sản phẩm có màu nhấn nhìn thấy được…"
36
- },
37
- {
38
- "v": "1.0.17",
39
- "d": "07/06/2026",
40
- "type": "Fixed",
41
- "en": "get_element and get_generation_guide no longer suggest https://picsum.photos as an alternative image placeholder; agents are now directed to use…",
42
- "vi": "get_element và get_generation_guide không còn gợi ý https://picsum.photos làm ảnh placeholder thay thế; agent nay được hướng dẫn chỉ dùng…"
43
43
  }
44
44
  ]
package/dist/web-guide.js CHANGED
@@ -24,6 +24,9 @@
24
24
  import { readFileSync } from "node:fs";
25
25
  import { ICON_SVG } from "./branding.js";
26
26
  const MCP_REMOTE_URL = "https://webcake.io/mcp-remote";
27
+ // The "configure every IDE" one-liner — rendered as a code block (with a copy
28
+ // button) rather than long inline code, which wrapped messily on mobile.
29
+ const INSTALL_ALL_CMD = "npx -y webcake-landing-mcp install --ide all --env prod --jwt <TOKEN>";
27
30
  const GITHUB_URL = "https://github.com/vuluu2k/webcake-landing-mcp";
28
31
  const NPM_URL = "https://www.npmjs.com/package/webcake-landing-mcp";
29
32
  const DOCS_URL = `${GITHUB_URL}#readme`;
@@ -61,6 +64,8 @@ const ICONS = {
61
64
  bulb: '<path d="M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5"/><path d="M9 18h6"/><path d="M10 22h4"/>',
62
65
  server: '<rect width="20" height="8" x="2" y="2" rx="2"/><rect width="20" height="8" x="2" y="14" rx="2"/><path d="M6 6h.01"/><path d="M6 18h.01"/>',
63
66
  window: '<rect x="2" y="4" width="20" height="16" rx="2"/><path d="M2 9h20"/><path d="M6 6.5h.01"/><path d="M9 6.5h.01"/>',
67
+ moon: '<path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"/>',
68
+ sun: '<circle cx="12" cy="12" r="4"/><path d="M12 2v2"/><path d="M12 20v2"/><path d="m4.93 4.93 1.41 1.41"/><path d="m17.66 17.66 1.41 1.41"/><path d="M2 12h2"/><path d="M20 12h2"/><path d="m6.34 17.66-1.41 1.41"/><path d="m19.07 4.93-1.41 1.41"/>',
64
69
  };
65
70
  function icon(name) {
66
71
  return `<svg class="i" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">${ICONS[name] ?? ""}</svg>`;
@@ -183,7 +188,7 @@ const T = {
183
188
  '<b>Làm theo hỏi đáp:</b> chọn môi trường (<code class="inl">prod</code>) → đăng nhập Webcake qua trình duyệt (hoặc dán JWT) → chọn IDE (Claude Desktop / Cursor / Claude Code…).',
184
189
  '<b>Khởi động lại IDE</b> → thấy <code class="inl">webcake-landing</code> trong danh sách MCP là xong.',
185
190
  ],
186
- m1Note: 'Muốn cấu hình mọi IDE một phát: <code class="inl">npx -y webcake-landing-mcp install --ide all --env prod --jwt &lt;TOKEN&gt;</code>',
191
+ m1Note: "Muốn cấu hình mọi IDE một phát:",
187
192
  m2Tag: "Cách ② · URL remote — không cần cài gì",
188
193
  m2Sub: "Hợp khi máy không có Node.js, dùng theo nhóm, hoặc dùng claude.ai trên web.",
189
194
  m2Steps: [
@@ -261,7 +266,7 @@ const T = {
261
266
  '<b>Follow the prompts:</b> pick an environment (<code class="inl">prod</code>) → sign in to Webcake in the browser (or paste a JWT) → pick your IDE (Claude Desktop / Cursor / Claude Code…).',
262
267
  '<b>Restart your IDE</b> → see <code class="inl">webcake-landing</code> in the MCP list and you\'re done.',
263
268
  ],
264
- m1Note: 'Configure every IDE at once: <code class="inl">npx -y webcake-landing-mcp install --ide all --env prod --jwt &lt;TOKEN&gt;</code>',
269
+ m1Note: "Configure every IDE at once:",
265
270
  m2Tag: "Way ② · Remote URL — nothing to install",
266
271
  m2Sub: "Best when you have no Node.js, work in a team, or use claude.ai on the web.",
267
272
  m2Steps: [
@@ -373,6 +378,7 @@ export function guideHtml(origin, lang = "vi") {
373
378
  <html lang="${L}"><head>
374
379
  <meta charset="utf-8">
375
380
  <meta name="viewport" content="width=device-width,initial-scale=1">
381
+ <script>(function(){try{var t=localStorage.getItem('wc-theme');if(t==='dark'||t==='light')document.documentElement.setAttribute('data-theme',t);}catch(e){}})();</script>
376
382
  <title>${m.title}</title>
377
383
  <meta name="description" content="${m.desc}">
378
384
  <meta name="keywords" content="${m.keywords}">
@@ -400,10 +406,15 @@ export function guideHtml(origin, lang = "vi") {
400
406
  <meta name="twitter:image" content="${ogImage}">
401
407
  <script type="application/ld+json">${jsonLdScript}</script>
402
408
  <style>
409
+ /* Light defaults. Dark applies via OS preference OR a forced [data-theme="dark"]
410
+ (the toggle); [data-theme="light"] forces light even on a dark OS. */
403
411
  :root{--g:#1DB954;--g7:#178f43;--ink:#11231b;--mut:#5e6d65;--bg:#f5f9f7;--card:#ffffff;
404
- --line:rgba(16,40,30,.09);--glass-hi:transparent;--shadow:0 1px 2px rgba(16,40,30,.05),0 6px 20px -12px rgba(16,40,30,.18);--code:#0e1714}
405
- @media(prefers-color-scheme:dark){:root{--ink:#e8f0ec;--mut:#9aaba2;--bg:#0b110e;--card:#141b17;
406
- --line:rgba(255,255,255,.07);--glass-hi:transparent;--shadow:0 1px 2px rgba(0,0,0,.3),0 8px 24px -14px rgba(0,0,0,.7);--code:#070f0b;--g7:#5ee08a}}
412
+ --line:rgba(16,40,30,.09);--shadow:0 1px 2px rgba(16,40,30,.05),0 6px 20px -12px rgba(16,40,30,.18);--code:#0e1714;
413
+ --ic-fg:#178f43;--btn-hover:#178f43}
414
+ @media(prefers-color-scheme:dark){:root:not([data-theme="light"]){--ink:#e8f0ec;--mut:#9aaba2;--bg:#0b110e;--card:#141b17;
415
+ --line:rgba(255,255,255,.07);--shadow:0 1px 2px rgba(0,0,0,.3),0 8px 24px -14px rgba(0,0,0,.7);--code:#070f0b;--g7:#5ee08a;--ic-fg:#6fe79a;--btn-hover:#21c264}}
416
+ :root[data-theme="dark"]{--ink:#e8f0ec;--mut:#9aaba2;--bg:#0b110e;--card:#141b17;
417
+ --line:rgba(255,255,255,.07);--shadow:0 1px 2px rgba(0,0,0,.3),0 8px 24px -14px rgba(0,0,0,.7);--code:#070f0b;--g7:#5ee08a;--ic-fg:#6fe79a;--btn-hover:#21c264}
407
418
  *{box-sizing:border-box}
408
419
  html{scroll-behavior:smooth}
409
420
  body{margin:0;font-family:system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;color:var(--ink);
@@ -424,9 +435,15 @@ export function guideHtml(origin, lang = "vi") {
424
435
  header .logo{width:50px;height:50px;border-radius:14px;overflow:hidden;flex:0 0 auto;
425
436
  box-shadow:0 6px 16px -4px rgba(29,185,84,.4)}
426
437
  header .logo svg{width:100%;height:100%;display:block}
427
- .langsw{margin-left:auto;align-self:flex-start;font-size:.82rem;font-weight:700;color:var(--g7);text-decoration:none;
438
+ .hgrow{flex:1 1 auto;min-width:0}
439
+ .controls{margin-left:auto;flex:0 0 auto;display:flex;align-items:center;gap:8px}
440
+ .langsw{font-size:.82rem;font-weight:700;color:var(--g7);text-decoration:none;white-space:nowrap;
428
441
  border:1px solid var(--line);background:var(--card);padding:7px 12px;border-radius:999px;display:inline-flex;align-items:center;gap:6px}
429
442
  .langsw:hover{border-color:var(--g)}
443
+ .iconbtn{width:36px;height:36px;flex:0 0 auto;display:grid;place-items:center;cursor:pointer;color:var(--g7);
444
+ border:1px solid var(--line);background:var(--card);border-radius:10px;transition:border-color .15s ease,color .15s ease}
445
+ .iconbtn:hover{border-color:var(--g)}
446
+ .iconbtn svg{width:17px;height:17px}
430
447
  h1{font-size:1.78rem;margin:0;font-weight:800;letter-spacing:-.02em}
431
448
  .sub{color:var(--mut);margin:3px 0 0;font-size:.98rem}
432
449
  .lead{font-size:1.16rem;margin:20px 0 18px;max-width:60ch}
@@ -439,9 +456,8 @@ export function guideHtml(origin, lang = "vi") {
439
456
  .dot{width:8px;height:8px;border-radius:50%;background:var(--g);box-shadow:0 0 0 0 rgba(29,185,84,.5);animation:pulse 2s infinite}
440
457
  @keyframes pulse{70%{box-shadow:0 0 0 7px rgba(29,185,84,0)}100%{box-shadow:0 0 0 0 rgba(29,185,84,0)}}
441
458
  h2{font-size:1.32rem;margin:46px 0 16px;font-weight:800;letter-spacing:-.01em}
442
- .ic{width:42px;height:42px;border-radius:12px;display:grid;place-items:center;flex:0 0 auto;color:var(--g7);
459
+ .ic{width:42px;height:42px;border-radius:12px;display:grid;place-items:center;flex:0 0 auto;color:var(--ic-fg);
443
460
  background:rgba(29,185,84,.11);border:1px solid var(--line);transition:transform .2s ease}
444
- @media(prefers-color-scheme:dark){.ic{color:#6fe79a}}
445
461
  .ic .i{width:22px;height:22px}
446
462
  .grid{display:grid;gap:16px;grid-template-columns:1fr 1fr 1fr}
447
463
  @media(max-width:720px){.grid{grid-template-columns:1fr}}
@@ -450,11 +466,20 @@ export function guideHtml(origin, lang = "vi") {
450
466
  .card h3{margin:0 0 6px;font-size:1.04rem}
451
467
  .card p{color:var(--mut);font-size:.93rem;margin:0}
452
468
  .tag{display:inline-flex;align-items:center;gap:9px;font-size:.82rem;font-weight:800;color:var(--g7);
453
- text-transform:uppercase;letter-spacing:.04em}
469
+ text-transform:uppercase;letter-spacing:.04em;flex-wrap:wrap}
454
470
  .tag .ic{width:30px;height:30px;border-radius:9px}
455
471
  .tag .ic .i{width:16px;height:16px}
456
472
  pre{margin:0;background:var(--code);color:#e8f0ec;border-radius:11px;padding:12px 14px;overflow-x:auto;
457
473
  border:1px solid rgba(255,255,255,.06);font:600 .82rem/1.5 ui-monospace,SFMono-Regular,Menlo,monospace}
474
+ /* Copy button injected onto every <pre> by the inline script */
475
+ .codewrap{position:relative}
476
+ .codewrap pre{padding-right:46px}
477
+ .copy{position:absolute;top:8px;right:8px;width:30px;height:30px;display:grid;place-items:center;cursor:pointer;
478
+ border:1px solid rgba(255,255,255,.15);border-radius:8px;background:rgba(255,255,255,.06);color:#cfe9d8;
479
+ transition:background .15s ease,color .15s ease,border-color .15s ease}
480
+ .copy:hover{background:rgba(255,255,255,.13);color:#fff}
481
+ .copy svg{width:15px;height:15px}
482
+ .copy.done{color:#5ee08a;border-color:rgba(94,224,138,.55)}
458
483
  .feat{list-style:none;padding:0;margin:0;display:grid;gap:12px}
459
484
  .feat li{display:flex;gap:13px;align-items:center;font-size:.97rem;padding:13px 16px}
460
485
  .feat li b{color:var(--ink)}
@@ -484,8 +509,7 @@ export function guideHtml(origin, lang = "vi") {
484
509
  background:var(--g);color:#fff;text-decoration:none;font-weight:700;font-size:.93rem;
485
510
  box-shadow:0 4px 12px -4px rgba(29,185,84,.5);transition:transform .15s ease,background .15s ease}
486
511
  .btn .i{width:18px;height:18px}
487
- .btn:hover{transform:translateY(-1px);background:var(--g7)}
488
- @media(prefers-color-scheme:dark){.btn:hover{background:#21c264}}
512
+ .btn:hover{transform:translateY(-1px);background:var(--btn-hover)}
489
513
  .btn.ghost{background:var(--card);color:var(--ink);border:1px solid var(--line);box-shadow:none}
490
514
  .btn.ghost:hover{border-color:var(--g);background:var(--card)}
491
515
  .uses{display:grid;gap:14px;grid-template-columns:1fr 1fr;padding:0;margin:0;list-style:none}
@@ -500,17 +524,24 @@ export function guideHtml(origin, lang = "vi") {
500
524
  .method{margin-bottom:16px;padding:24px}
501
525
  .method>.tag{margin-bottom:4px}
502
526
  .msub{color:var(--mut);font-size:.92rem;margin:.5rem 0 1.2rem}
503
- .steps{list-style:none;margin:0;padding:0;display:grid;gap:16px}
504
- .steps li{display:flex;gap:14px}
505
- .steps .n{flex:0 0 auto;width:28px;height:28px;border-radius:50%;color:var(--g7);
527
+ .steps{list-style:none;margin:0;padding:0;display:grid;gap:18px;position:relative}
528
+ .steps li{display:flex;gap:14px;align-items:flex-start;position:relative}
529
+ /* Faint connector between step numbers → reads as an intentional stepper */
530
+ .steps li:not(:last-child)::after{content:"";position:absolute;left:13px;top:30px;bottom:-18px;width:2px;background:var(--line)}
531
+ .steps .n{flex:0 0 auto;width:28px;height:28px;border-radius:50%;color:var(--ic-fg);
506
532
  background:rgba(29,185,84,.12);border:1px solid var(--line);
507
533
  font:800 .85rem/1 system-ui;display:flex;align-items:center;justify-content:center}
508
- @media(prefers-color-scheme:dark){.steps .n{color:#6fe79a}}
509
534
  .steps .body{flex:1;min-width:0;font-size:.95rem}
510
535
  .steps .body pre{margin-top:9px}
511
- .steps .body .btn{margin-top:10px}
512
- code.inl{background:rgba(29,185,84,.13);color:var(--g7);padding:1px 6px;border-radius:6px;font-size:.85em;font-weight:600}
536
+ /* A button inside a step drops to its own left-aligned line (inline-flex would
537
+ sit beside the text and be shoved off-baseline by the top margin). */
538
+ .steps .body .btn{display:flex;width:fit-content;margin-top:10px}
539
+ code.inl{background:rgba(29,185,84,.13);color:var(--g7);padding:1px 6px;border-radius:6px;font-size:.85em;font-weight:600;
540
+ overflow-wrap:anywhere;word-break:break-word}
513
541
  .note{font-size:.86rem;color:var(--mut);margin-top:10px}
542
+ .note + pre,.note + .codewrap{margin-top:9px}
543
+ .tip{margin-top:16px;background:rgba(29,185,84,.06);border:1px solid var(--line);border-radius:12px;padding:13px 15px}
544
+ .tip .note{margin:0}
514
545
  details{padding:2px 18px;margin-bottom:11px}
515
546
  details summary{cursor:pointer;font-weight:600;padding:15px 0;list-style:none;display:flex;align-items:center;gap:10px}
516
547
  details summary::-webkit-details-marker{display:none}
@@ -549,6 +580,32 @@ export function guideHtml(origin, lang = "vi") {
549
580
  @keyframes blink{50%{opacity:.55}}
550
581
  .cl-more{display:inline-flex;align-items:center;gap:6px;margin-top:6px;font-size:.86rem;font-weight:600;color:var(--g7);text-decoration:none}
551
582
  .cl-more:hover{gap:9px}
583
+ @media(max-width:640px){
584
+ .wrap{padding:30px 15px 56px}
585
+ /* Header: logo + controls on the top row, title drops to its own full line */
586
+ header{flex-wrap:wrap;gap:12px}
587
+ .hgrow{order:2;flex:1 1 100%}
588
+ h1{font-size:1.4rem}
589
+ h2{font-size:1.2rem;margin:34px 0 14px}
590
+ .lead{font-size:1.05rem}
591
+ .method{padding:18px 15px}
592
+ .card{padding:18px}
593
+ .tip{padding:11px 12px}
594
+ .cl-wrap{padding:18px 16px 10px}
595
+ .langsw{padding:6px 10px}
596
+ .uses li,.feat li{padding:14px}
597
+ /* Flow diagram: stack vertically (the horizontal row overflows narrow screens) */
598
+ .flow{flex-direction:column;align-items:stretch;overflow:visible;padding:16px}
599
+ .flow .node{flex-direction:row;width:auto;align-items:center;gap:13px;text-align:left}
600
+ .flow .node .ic{width:44px;height:44px;border-radius:13px}
601
+ .flow .node .ic .i{width:22px;height:22px}
602
+ .flow .node b{font-size:.95rem}
603
+ .flow .node span{font-size:.8rem}
604
+ .flow .wire{flex:0 0 auto;width:2px;height:20px;min-width:0;margin:3px 0 3px 21px;
605
+ background:linear-gradient(var(--line),var(--g))}
606
+ .flow .wire::after{content:none}
607
+ .flow .wire .pkt{display:none}
608
+ }
552
609
  @media(prefers-reduced-motion:no-preference){
553
610
  @supports (animation-timeline:view()){
554
611
  .reveal{animation:rise linear both;animation-timeline:view();animation-range:entry 0% entry 32%}
@@ -564,11 +621,14 @@ export function guideHtml(origin, lang = "vi") {
564
621
 
565
622
  <header class="hero-in">
566
623
  <span class="logo">${ICON_SVG}</span>
567
- <div>
624
+ <div class="hgrow">
568
625
  <h1>Webcake Landing MCP</h1>
569
626
  <p class="sub">${t.sub}</p>
570
627
  </div>
571
- <a class="langsw" href="${otherHref}" hreflang="${otherLang}" rel="alternate">${icon("globe")} ${t.switchLabel}</a>
628
+ <div class="controls">
629
+ <button class="iconbtn" id="theme" type="button" aria-label="Toggle theme" title="Theme">${icon("moon")}</button>
630
+ <a class="langsw" href="${otherHref}" hreflang="${otherLang}" rel="alternate">${icon("globe")} ${t.switchLabel}</a>
631
+ </div>
572
632
  </header>
573
633
 
574
634
  <p class="hero-in" style="display:flex;gap:9px;flex-wrap:wrap"><span class="pill"><span class="dot"></span> ${t.running}</span>${CHANGELOG[0] ? `<span class="pill">v${CHANGELOG[0].v}</span>` : ""}</p>
@@ -613,7 +673,7 @@ export function guideHtml(origin, lang = "vi") {
613
673
  <ol class="steps">
614
674
  ${steps(t.m1Steps.map(fill))}
615
675
  </ol>
616
- <p class="note">${t.m1Note}</p>
676
+ <div class="tip"><p class="note">${t.m1Note}</p><pre>${INSTALL_ALL_CMD}</pre></div>
617
677
  </div>
618
678
 
619
679
  <div class="glass card method reveal">
@@ -659,7 +719,36 @@ export function guideHtml(origin, lang = "vi") {
659
719
  <a href="${selfPath === "/" ? "/health" : "/health"}">Health</a>
660
720
  </footer>
661
721
 
662
- </div></body></html>`;
722
+ </div>
723
+ <script>
724
+ (function(){
725
+ var COPY='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>';
726
+ var DONE='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>';
727
+ function copyText(t){
728
+ if(navigator.clipboard&&navigator.clipboard.writeText){return navigator.clipboard.writeText(t);}
729
+ return new Promise(function(res,rej){try{var ta=document.createElement('textarea');ta.value=t;ta.style.position='fixed';ta.style.opacity='0';document.body.appendChild(ta);ta.select();document.execCommand('copy');document.body.removeChild(ta);res();}catch(e){rej(e);}});
730
+ }
731
+ document.querySelectorAll('pre').forEach(function(pre){
732
+ var w=document.createElement('div');w.className='codewrap';
733
+ pre.parentNode.insertBefore(w,pre);w.appendChild(pre);
734
+ var b=document.createElement('button');b.type='button';b.className='copy';b.title='Copy';b.setAttribute('aria-label','Copy');b.innerHTML=COPY;
735
+ b.addEventListener('click',function(){
736
+ copyText(pre.innerText).then(function(){b.classList.add('done');b.innerHTML=DONE;setTimeout(function(){b.classList.remove('done');b.innerHTML=COPY;},1400);}).catch(function(){});
737
+ });
738
+ w.appendChild(b);
739
+ });
740
+
741
+ // Dark / light toggle — overrides the OS preference and persists the choice.
742
+ var SUN='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2"/><path d="M12 20v2"/><path d="m4.93 4.93 1.41 1.41"/><path d="m17.66 17.66 1.41 1.41"/><path d="M2 12h2"/><path d="M20 12h2"/><path d="m6.34 17.66-1.41 1.41"/><path d="m19.07 4.93-1.41 1.41"/></svg>';
743
+ var MOON='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"/></svg>';
744
+ var html=document.documentElement, tBtn=document.getElementById('theme');
745
+ function effective(){return html.getAttribute('data-theme')||(window.matchMedia&&window.matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light');}
746
+ function paint(){if(tBtn)tBtn.innerHTML=effective()==='dark'?SUN:MOON;}
747
+ paint();
748
+ if(tBtn)tBtn.addEventListener('click',function(){var next=effective()==='dark'?'light':'dark';html.setAttribute('data-theme',next);try{localStorage.setItem('wc-theme',next);}catch(e){}paint();});
749
+ })();
750
+ </script>
751
+ </body></html>`;
663
752
  }
664
753
  /**
665
754
  * The social-card image served at `/og.svg` and referenced by the page's
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webcake-landing-mcp",
3
- "version": "1.0.22",
3
+ "version": "1.0.24",
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
  "type": "module",
6
6
  "bin": {