@gemboss/website-ui 0.4.0 → 0.5.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/demo/blog.html ADDED
@@ -0,0 +1,314 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>Blog · GemBoss</title>
7
+ <meta name="description" content="The kit's blog index: a post list of cards with pictures, prev and next pagination, and the compact list.">
8
+ <script>try{var t=localStorage.getItem('gw-theme');if(t==='light'||t==='dark')document.documentElement.setAttribute('data-theme',t)}catch(e){}</script>
9
+ <link rel="preconnect" href="https://fonts.googleapis.com">
10
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
11
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;650;700&display=swap">
12
+ <link rel="stylesheet" href="../website.css">
13
+ </head>
14
+ <body class="gw-page">
15
+ <a class="gw-skip" href="#main">Skip to content</a>
16
+
17
+ <div class="gw-announce" role="region" aria-label="Announcement">GemBoss is built by the team behind GemPages. <a href="https://feedback.gemboss.ai/changelog" rel="noopener">What's new on the changelog</a></div>
18
+ <header class="gw-header" data-gw-header>
19
+ <div class="gw-wrap gw-header__bar">
20
+ <a class="gw-brand" href="https://gemboss.ai/"><svg class="gw-brand__mark" viewBox="0 0 100 116" aria-hidden="true"><polygon points="26,14 74,14 66,50 34,50" style="fill:var(--gw-accent)"/><path d="M26,14 74,14 96,50 50,110 4,50Z" fill="none" stroke="currentColor" stroke-width="9" stroke-linejoin="round"/><path d="M4,50H96M26,14 34,50M74,14 66,50M34,50 50,110M66,50 50,110" fill="none" stroke="currentColor" stroke-width="5.6" stroke-linejoin="round"/></svg><span class="gw-brand__name">GemBoss</span></a>
21
+ <nav class="gw-nav" aria-label="Main">
22
+ <ul class="gw-nav__list">
23
+ <li class="gw-nav__item">
24
+ <button class="gw-nav__trigger" type="button" aria-expanded="false" aria-controls="gw-mega-product" data-gw-mega="gw-mega-product">Product</button>
25
+ <div class="gw-mega" id="gw-mega-product" hidden>
26
+ <div class="gw-wrap gw-mega__grid">
27
+ <div class="gw-mega__col">
28
+ <p class="gw-mega__heading">Build</p>
29
+ <a class="gw-mega__link" href="https://gemboss.ai/funnel"><span class="gw-mega__icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M3 4h18l-7 8v6l-4 2v-8z"/></svg></span><span><b>Funnel builder</b><i>Angles, advertorials, offers</i></span></a>
30
+ <a class="gw-mega__link" href="https://gemboss.ai/ai-store-builder"><span class="gw-mega__icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M3 9l1.5-5h15L21 9"/><path d="M4 9v11h16V9"/><path d="M9 20v-6h6v6"/></svg></span><span><b>Storefront builder</b><i>Headless, on your Shopify</i></span></a>
31
+ <a class="gw-mega__link" href="https://gemboss.ai/gempages"><span class="gw-mega__icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="3" width="16" height="18" rx="2"/><path d="M8 8h8M8 12h8M8 16h5"/></svg></span><span><b>Page builder</b><i>Ask, watch, publish</i></span></a>
32
+ </div>
33
+ <div class="gw-mega__col">
34
+ <p class="gw-mega__heading">Grow</p>
35
+ <a class="gw-mega__link" href="https://gemboss.ai/gemx"><span class="gw-mega__icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4v16M20 4v16M4 9h16M4 15h16"/></svg></span><span><b>Tests &amp; personalization</b><i>You promote the winner</i></span></a>
36
+ <a class="gw-mega__link" href="https://gemboss.ai/gemoffers"><span class="gw-mega__icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M20 12l-8 8-9-9V3h8z"/><circle cx="7.5" cy="7.5" r="1.5"/></svg></span><span><b>Offers &amp; upsells</b><i>Bundles, gifts, bumps</i></span></a>
37
+ <a class="gw-mega__link" href="https://gemboss.ai/data"><span class="gw-mega__icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M3 3v18h18"/><path d="M7 15l4-4 3 3 5-6"/></svg></span><span><b>Analytics &amp; data</b><i>First-party, yours</i></span></a>
38
+ </div>
39
+ <div class="gw-mega__col">
40
+ <p class="gw-mega__heading">Connect</p>
41
+ <a class="gw-mega__link" href="https://gemboss.ai/integrations"><span class="gw-mega__icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M9 3v6M15 3v6M6 9h12v3a6 6 0 0 1-12 0z"/><path d="M12 18v3"/></svg></span><span><b>Integrations</b><i>Klaviyo, Meta, Google</i></span></a>
42
+ <a class="gw-mega__link" href="https://gemboss.ai/mcp"><span class="gw-mega__icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="m8 9-4 3 4 3"/><path d="m16 9 4 3-4 3"/><path d="m14 5-4 14"/></svg></span><span><b>MCP &amp; agents</b><i>Claude and Codex</i></span></a>
43
+ <a class="gw-mega__link" href="https://gemboss.ai/agent-ready"><span class="gw-mega__icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><rect x="5" y="8" width="14" height="11" rx="3"/><path d="M12 4v4"/><circle cx="9.5" cy="13.5" r="1"/><circle cx="14.5" cy="13.5" r="1"/></svg></span><span><b>Agent-ready storefront</b><i>Ready for AI shoppers</i></span></a>
44
+ </div>
45
+ <a class="gw-mega__feature" href="https://gemboss.ai/engine"><b>How the engine works</b><i>Six stages, one loop. Nothing ships without you.</i><span class="gw-link gw-link--arrow">See the engine</span></a>
46
+ </div>
47
+ </div>
48
+ </li>
49
+ <li class="gw-nav__item">
50
+ <button class="gw-nav__trigger" type="button" aria-expanded="false" aria-controls="gw-mega-usecases" data-gw-mega="gw-mega-usecases">Use cases</button>
51
+ <div class="gw-mega" id="gw-mega-usecases" hidden>
52
+ <div class="gw-wrap gw-mega__grid">
53
+ <div class="gw-mega__col">
54
+ <p class="gw-mega__heading">Adaptive funnels</p>
55
+ <a class="gw-mega__link" href="https://gemboss.ai/meta-ads"><span class="gw-mega__icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M3 11v2a1 1 0 0 0 1 1h3l5 4V6L7 10H4a1 1 0 0 0-1 1z"/><path d="M16 9a4 4 0 0 1 0 6"/></svg></span><span><b>Meta, Google &amp; TikTok ads</b><i>A funnel for every ad angle</i></span></a>
56
+ <a class="gw-mega__link" href="https://gemboss.ai/klaviyo-personalized-landing-pages"><span class="gw-mega__icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="5" width="18" height="14" rx="2"/><path d="m3 7 9 6 9-6"/></svg></span><span><b>Klaviyo email <span class="gw-badge gw-badge--warning">Early access</span></b><i>A page per recipient, after the click</i></span></a>
57
+ </div>
58
+ <div class="gw-mega__col">
59
+ <p class="gw-mega__heading">Adaptive storefront</p>
60
+ <a class="gw-mega__link" href="https://gemboss.ai/ai-store-builder"><span class="gw-mega__icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M3 9l1.5-5h15L21 9"/><path d="M4 9v11h16V9"/><path d="M9 20v-6h6v6"/></svg></span><span><b>Headless storefront</b><i>Your whole Shopify store, on GemBoss</i></span></a>
61
+ <a class="gw-mega__link" href="https://gemboss.ai/agent-ready"><span class="gw-mega__icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><rect x="5" y="8" width="14" height="11" rx="3"/><path d="M12 4v4"/><circle cx="9.5" cy="13.5" r="1"/><circle cx="14.5" cy="13.5" r="1"/></svg></span><span><b>AI agents &amp; AI search</b><i>Readable by AI, shoppable by agents</i></span></a>
62
+ </div>
63
+ <a class="gw-mega__feature" href="https://gemboss.ai/meta-ads"><b>Every ad gets its own page</b><i>The page keeps the promise the ad made.</i><span class="gw-link gw-link--arrow">See the ad-to-page path</span></a>
64
+ </div>
65
+ </div>
66
+ </li>
67
+ <li class="gw-nav__item"><a class="gw-nav__link" href="https://gemboss.ai/pricing">Pricing</a></li>
68
+ <li class="gw-nav__item">
69
+ <button class="gw-nav__trigger" type="button" aria-expanded="false" aria-controls="gw-mega-resources" data-gw-mega="gw-mega-resources">Resources</button>
70
+ <div class="gw-mega" id="gw-mega-resources" hidden>
71
+ <div class="gw-wrap gw-mega__grid">
72
+ <div class="gw-mega__col">
73
+ <p class="gw-mega__heading">Learn</p>
74
+ <a class="gw-mega__link" href="https://gemboss.ai/blog"><span class="gw-mega__icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4h11a2 2 0 0 1 2 2v14H6a2 2 0 0 1-2-2z"/><path d="M8 8h7M8 12h7"/></svg></span><span><b>Blog</b><i>Playbooks and guides</i></span></a>
75
+ <a class="gw-mega__link" href="https://gemboss.ai/docs"><span class="gw-mega__icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M14 3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"/><path d="M14 3v6h6"/></svg></span><span><b>Docs</b><i>Guides and MCP tools</i></span></a>
76
+ </div>
77
+ <div class="gw-mega__col">
78
+ <p class="gw-mega__heading">Company</p>
79
+ <a class="gw-mega__link" href="https://gemboss.ai/company"><span class="gw-mega__icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 11v5M12 8h.01"/></svg></span><span><b>About</b><i>Why we build it</i></span></a>
80
+ <a class="gw-mega__link" href="https://gemboss.ai/contact"><span class="gw-mega__icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg></span><span><b>Contact</b><i>Talk to a human</i></span></a>
81
+ </div>
82
+ </div>
83
+ </div>
84
+ </li>
85
+ </ul>
86
+ </nav>
87
+ <div class="gw-header__actions">
88
+ <button class="gw-theme-toggle" type="button" data-gw-theme-toggle aria-label="Switch to dark theme"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><circle cx="12" cy="12" r="8"/><path d="M12 4a8 8 0 0 1 0 16z" fill="currentColor"/></svg></button>
89
+ <a class="gw-nav__link gw-header__signin" href="https://admin.gemboss.ai/login">Sign in</a>
90
+ <a class="gw-btn gw-btn--secondary gw-btn--sm" href="https://gemboss.ai/contact">Book a demo</a>
91
+ <a class="gw-btn gw-btn--sm" href="https://admin.gemboss.ai/signup">Start free</a>
92
+ <button class="gw-menu-toggle" type="button" aria-expanded="false" aria-controls="gw-mobile-menu" data-gw-menu-toggle aria-label="Open menu"><svg class="gw-menu-toggle__open" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" aria-hidden="true"><path d="M4 7h16M4 12h16M4 17h16"/></svg><svg class="gw-menu-toggle__close" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" aria-hidden="true"><path d="M6 6l12 12M18 6 6 18"/></svg></button>
93
+ </div>
94
+ </div>
95
+ <div class="gw-mobile-menu" id="gw-mobile-menu" hidden>
96
+ <nav class="gw-wrap" aria-label="Main, mobile">
97
+ <details class="gw-mobile-menu__group">
98
+ <summary>Product</summary>
99
+ <ul class="gw-mobile-menu__list">
100
+ <li><a class="gw-mobile-menu__link" href="https://gemboss.ai/funnel">Funnel builder</a></li>
101
+ <li><a class="gw-mobile-menu__link" href="https://gemboss.ai/ai-store-builder">Storefront builder</a></li>
102
+ <li><a class="gw-mobile-menu__link" href="https://gemboss.ai/gemx">Tests &amp; personalization</a></li>
103
+ <li><a class="gw-mobile-menu__link" href="https://gemboss.ai/gemoffers">Offers &amp; upsells</a></li>
104
+ <li><a class="gw-mobile-menu__link" href="https://gemboss.ai/integrations">Integrations</a></li>
105
+ </ul>
106
+ </details>
107
+ <details class="gw-mobile-menu__group">
108
+ <summary>Use cases</summary>
109
+ <ul class="gw-mobile-menu__list">
110
+ <li><a class="gw-mobile-menu__link" href="https://gemboss.ai/meta-ads">Meta, Google &amp; TikTok ads</a></li>
111
+ <li><a class="gw-mobile-menu__link" href="https://gemboss.ai/ai-store-builder">Headless storefront</a></li>
112
+ <li><a class="gw-mobile-menu__link" href="https://gemboss.ai/agent-ready">AI agents &amp; AI search</a></li>
113
+ </ul>
114
+ </details>
115
+ <a class="gw-mobile-menu__top" href="https://gemboss.ai/pricing">Pricing</a>
116
+ <details class="gw-mobile-menu__group">
117
+ <summary>Resources</summary>
118
+ <ul class="gw-mobile-menu__list">
119
+ <li><a class="gw-mobile-menu__link" href="https://gemboss.ai/blog">Blog</a></li>
120
+ <li><a class="gw-mobile-menu__link" href="https://gemboss.ai/docs">Docs</a></li>
121
+ <li><a class="gw-mobile-menu__link" href="https://gemboss.ai/company">About</a></li>
122
+ <li><a class="gw-mobile-menu__link" href="https://gemboss.ai/contact">Contact</a></li>
123
+ </ul>
124
+ </details>
125
+ <div class="gw-mobile-menu__actions">
126
+ <a class="gw-btn gw-btn--block" href="https://admin.gemboss.ai/signup">Start free</a>
127
+ <a class="gw-btn gw-btn--secondary gw-btn--block" href="https://gemboss.ai/contact">Book a demo</a>
128
+ <a class="gw-mobile-menu__link" href="https://admin.gemboss.ai/login">Sign in</a>
129
+ </div>
130
+ </nav>
131
+ </div>
132
+ </header>
133
+
134
+ <main id="main">
135
+ <section class="gw-hero gw-hero--compact" aria-labelledby="blog-h">
136
+ <div class="gw-wrap">
137
+ <nav class="gw-breadcrumbs" aria-label="Breadcrumb">
138
+ <ol>
139
+ <li><a href="index.html">Home</a></li>
140
+ <li><a href="blog.html" aria-current="page">Blog</a></li>
141
+ </ol>
142
+ </nav>
143
+ <h1 id="blog-h">From the GemBoss blog</h1>
144
+ <p class="gw-lead">Notes on agentic commerce, storefront cloning, and the engineering behind the GemBoss section library.</p>
145
+ </div>
146
+ </section>
147
+
148
+ <section class="gw-section gw-section--tight" aria-label="Latest posts">
149
+ <div class="gw-wrap">
150
+ <ul class="gw-post-list" role="list">
151
+ <li>
152
+ <article class="gw-card gw-post">
153
+ <div class="gw-card__media"><img src="assets/post-theme.svg" alt="" width="640" height="360" loading="lazy"></div>
154
+ <p class="gw-label">Themes</p>
155
+ <h2 class="gw-post__title"><a href="https://gemboss.ai/blog/how-to-choose-shopify-theme">How to choose a Shopify theme that converts</a></h2>
156
+ <p>A checklist for choosing a theme: speed, mobile, features and fit, from free to premium to AI-built.</p>
157
+ <p class="gw-article-meta"><span><time datetime="2026-08-08">Aug 8, 2026</time></span><span>8 min read</span></p>
158
+ </article>
159
+ </li>
160
+ <li>
161
+ <article class="gw-card gw-post">
162
+ <div class="gw-card__media"><img src="assets/post-headless.svg" alt="" width="640" height="360" loading="lazy"></div>
163
+ <p class="gw-label">Headless</p>
164
+ <h2 class="gw-post__title"><a href="https://gemboss.ai/blog/headless-shopify-vs-liquid">Headless Shopify vs Liquid themes</a></h2>
165
+ <p>The speed, cost and control tradeoffs, and when a Liquid theme is the smarter choice.</p>
166
+ <p class="gw-article-meta"><span><time datetime="2026-08-08">Aug 8, 2026</time></span><span>10 min read</span></p>
167
+ </article>
168
+ </li>
169
+ <li>
170
+ <article class="gw-card gw-post">
171
+ <div class="gw-card__media"><img src="assets/post-speed.svg" alt="" width="640" height="360" loading="lazy"></div>
172
+ <p class="gw-label">Playbook</p>
173
+ <h2 class="gw-post__title"><a href="https://gemboss.ai/blog/page-speed-conversion-rate">Page speed and conversion rate: the numbers Shopify brands should know</a></h2>
174
+ <p>How much page speed moves conversion, with cited numbers on load time, bounce and revenue.</p>
175
+ <p class="gw-article-meta"><span><time datetime="2026-08-08">Aug 8, 2026</time></span><span>10 min read</span></p>
176
+ </article>
177
+ </li>
178
+ <li>
179
+ <article class="gw-card gw-post">
180
+ <div class="gw-card__media"><img src="assets/post-voice.svg" alt="" width="640" height="360" loading="lazy"></div>
181
+ <p class="gw-label">Product</p>
182
+ <h2 class="gw-post__title"><a href="https://gemboss.ai/blog/brand-voice-copy">Copy that sounds like your brand</a></h2>
183
+ <p>How GemBoss writes section copy in your brand's captured voice, and writes each language natively instead of translating English.</p>
184
+ <p class="gw-article-meta"><span><time datetime="2026-07-21">Jul 21, 2026</time></span><span>6 min read</span></p>
185
+ </article>
186
+ </li>
187
+ <li>
188
+ <article class="gw-card gw-post">
189
+ <div class="gw-card__media"><img src="assets/post-output.svg" alt="" width="640" height="360" loading="lazy"></div>
190
+ <p class="gw-label">Opinion</p>
191
+ <h2 class="gw-post__title"><a href="https://gemboss.ai/blog/owning-the-output">Why we bet on owning the output</a></h2>
192
+ <p>Your store is real, editable Shopify on an open framework, your domain, your data. Cancel and it keeps running.</p>
193
+ <p class="gw-article-meta"><span><time datetime="2026-07-21">Jul 21, 2026</time></span><span>6 min read</span></p>
194
+ </article>
195
+ </li>
196
+ <li>
197
+ <article class="gw-card gw-post">
198
+ <div class="gw-card__media"><img src="assets/post-motion.svg" alt="" width="640" height="360" loading="lazy"></div>
199
+ <p class="gw-label">Design</p>
200
+ <h2 class="gw-post__title"><a href="https://gemboss.ai/blog/motion-language">A motion language in one knob</a></h2>
201
+ <p>How GemBoss sets a whole store's motion character, editorial, bold or soft, from a single knob.</p>
202
+ <p class="gw-article-meta"><span><time datetime="2026-07-21">Jul 21, 2026</time></span><span>6 min read</span></p>
203
+ </article>
204
+ </li>
205
+ </ul>
206
+ <nav class="gw-pagination" aria-label="Blog pages">
207
+ <a class="gw-btn gw-btn--secondary" href="blog.html?page=1" rel="prev">Newer posts</a>
208
+ <p class="gw-pagination__status">Page 2 of 4</p>
209
+ <a class="gw-btn gw-btn--secondary" href="blog.html?page=3" rel="next">Older posts</a>
210
+ </nav>
211
+ </div>
212
+ </section>
213
+
214
+ <!-- the compact list: rows without cards or pictures -->
215
+ <section class="gw-section gw-section--soft" aria-labelledby="guides">
216
+ <div class="gw-wrap gw-wrap--narrow">
217
+ <div class="gw-section__head">
218
+ <p class="gw-label">Guides</p>
219
+ <h2 id="guides">Also on the blog</h2>
220
+ </div>
221
+ <ul class="gw-post-list gw-post-list--compact" role="list">
222
+ <li>
223
+ <article class="gw-card gw-post">
224
+ <h3 class="gw-post__title"><a href="https://gemboss.ai/blog/headless-shopify-without-developer">Headless Shopify without a developer: ship in a weekend</a></h3>
225
+ <p class="gw-article-meta"><span>Headless</span><span><time datetime="2026-08-08">Aug 8, 2026</time></span><span>9 min read</span></p>
226
+ </article>
227
+ </li>
228
+ <li>
229
+ <article class="gw-card gw-post">
230
+ <h3 class="gw-post__title"><a href="https://gemboss.ai/blog/headless-shopify-cost">How much does headless Shopify cost?</a></h3>
231
+ <p class="gw-article-meta"><span>Headless</span><span><time datetime="2026-08-08">Aug 8, 2026</time></span><span>9 min read</span></p>
232
+ </article>
233
+ </li>
234
+ <li>
235
+ <article class="gw-card gw-post">
236
+ <h3 class="gw-post__title"><a href="https://gemboss.ai/blog/best-shopify-page-builders">Best Shopify page builders in 2026, ranked by use case</a></h3>
237
+ <p class="gw-article-meta"><span>Comparison</span><span><time datetime="2026-08-08">Aug 8, 2026</time></span><span>13 min read</span></p>
238
+ </article>
239
+ </li>
240
+ <li>
241
+ <article class="gw-card gw-post">
242
+ <h3 class="gw-post__title"><a href="https://gemboss.ai/blog/section-library-dawn-gem">A token-driven section library, on one runtime</a></h3>
243
+ <p class="gw-article-meta"><span>Engineering</span><span><time datetime="2026-07-21">Jul 21, 2026</time></span><span>7 min read</span></p>
244
+ </article>
245
+ </li>
246
+ </ul>
247
+ </div>
248
+ </section>
249
+ </main>
250
+
251
+ <footer class="gw-footer">
252
+ <div class="gw-wrap">
253
+ <div class="gw-footer__grid">
254
+ <div class="gw-footer__brand">
255
+ <a class="gw-brand" href="https://gemboss.ai/"><svg class="gw-brand__mark" viewBox="0 0 100 116" aria-hidden="true"><polygon points="26,14 74,14 66,50 34,50" style="fill:var(--gw-accent)"/><path d="M26,14 74,14 96,50 50,110 4,50Z" fill="none" stroke="currentColor" stroke-width="9" stroke-linejoin="round"/><path d="M4,50H96M26,14 34,50M74,14 66,50M34,50 50,110M66,50 50,110" fill="none" stroke="currentColor" stroke-width="5.6" stroke-linejoin="round"/></svg><span class="gw-brand__name">GemBoss</span></a>
256
+ <p>The AI Conversion Engine for Shopify. Build a brand-true store, ship it blazing fast, and see what to change to sell more.</p>
257
+ </div>
258
+ <nav class="gw-footer__col" aria-label="Product">
259
+ <h2 class="gw-footer__heading">Product</h2>
260
+ <ul>
261
+ <li><a href="https://gemboss.ai/funnel">Funnel builder</a></li>
262
+ <li><a href="https://gemboss.ai/ai-store-builder">Storefront builder</a></li>
263
+ <li><a href="https://gemboss.ai/gemx">Tests &amp; personalization</a></li>
264
+ <li><a href="https://gemboss.ai/gemoffers">Offers &amp; upsells</a></li>
265
+ <li><a href="https://gemboss.ai/integrations">Integrations</a></li>
266
+ <li><a href="https://gemboss.ai/pricing">Pricing</a></li>
267
+ </ul>
268
+ </nav>
269
+ <nav class="gw-footer__col" aria-label="Use cases">
270
+ <h2 class="gw-footer__heading">Use cases</h2>
271
+ <ul>
272
+ <li><a href="https://gemboss.ai/meta-ads">Meta, Google &amp; TikTok ads</a></li>
273
+ <li><a href="https://gemboss.ai/klaviyo-personalized-landing-pages">Klaviyo landing pages</a></li>
274
+ <li><a href="https://gemboss.ai/affiliate-landing-pages">Affiliate pages</a></li>
275
+ <li><a href="https://gemboss.ai/agent-ready">AI agents &amp; AI search</a></li>
276
+ </ul>
277
+ </nav>
278
+ <nav class="gw-footer__col" aria-label="Resources">
279
+ <h2 class="gw-footer__heading">Resources</h2>
280
+ <ul>
281
+ <li><a href="https://gemboss.ai/audit">Free store audit</a></li>
282
+ <li><a href="https://gemboss.ai/blog">Blog</a></li>
283
+ <li><a href="https://gemboss.ai/docs">Docs</a></li>
284
+ <li><a href="https://gemboss.ai/mcp">MCP for AI agents</a></li>
285
+ <li><a href="https://feedback.gemboss.ai/changelog" rel="noopener">Changelog</a></li>
286
+ </ul>
287
+ </nav>
288
+ <nav class="gw-footer__col" aria-label="Company">
289
+ <h2 class="gw-footer__heading">Company</h2>
290
+ <ul>
291
+ <li><a href="https://gemboss.ai/company">About</a></li>
292
+ <li><a href="https://gemboss.ai/careers">Careers</a></li>
293
+ <li><a href="https://gemboss.ai/partners">Partners</a></li>
294
+ <li><a href="https://gemboss.ai/contact">Contact</a></li>
295
+ </ul>
296
+ </nav>
297
+ </div>
298
+ <div class="gw-footer__bottom">
299
+ <span>© 2026 GemBoss. All rights reserved.</span>
300
+ <ul aria-label="Legal">
301
+ <li><a href="https://gemboss.ai/privacy">Privacy</a></li>
302
+ <li><a href="https://gemboss.ai/terms">Terms</a></li>
303
+ </ul>
304
+ <ul aria-label="Social">
305
+ <li><a href="https://www.linkedin.com/company/gempages" rel="noopener">LinkedIn</a></li>
306
+ <li><a href="https://x.com/gempages" rel="noopener">X</a></li>
307
+ </ul>
308
+ </div>
309
+ </div>
310
+ </footer>
311
+
312
+ <script src="../js/website.js" defer></script>
313
+ </body>
314
+ </html>
package/demo/index.html CHANGED
@@ -583,6 +583,7 @@ npx gemboss-website check --fix-list</code></pre>
583
583
  <li>Look at the site in light and dark, at 320px and 1366px.</li>
584
584
  </ol>
585
585
  </article>
586
+ <p class="demo-mt">The whole page for a blog post, with breadcrumbs, the meta row, contents and callouts: <a href="article.html">an article</a>, and <a href="blog.html">the blog index</a> with its post list.</p>
586
587
  </div>
587
588
  </section>
588
589
 
@@ -35,8 +35,8 @@ Don't remove the skip link, and don't leave out `id="main"`.
35
35
  ## Script
36
36
 
37
37
  `js/website.js` (a `<script defer>`) or `js/website.mjs` (an `import`) wires every part that moves: the mega menu,
38
- the mobile menu, the theme toggle, reveal, the header's scroll state, the current page, the segmented control and
39
- the busy button. Markup that arrives after the page loaded (a client-side route change, a builder block, a CMS
38
+ the mobile menu, the theme toggle, reveal, the header's scroll state, the current page, the segmented control, the
39
+ busy button, an article's contents list and the scroll box of its tables (0.5.0). Markup that arrives after the page loaded (a client-side route change, a builder block, a CMS
40
40
  preview) is wired by calling `init` on it, as often as needed: an element is wired once.
41
41
 
42
42
  ```js
@@ -51,7 +51,7 @@ import { init } from '@gemboss/website-ui/website.mjs';
51
51
  ```
52
52
 
53
53
  `destroy(root)` takes it back when a framework unmounts. The Next.js recipe, the `data-gw-ready` mark and the
54
- events (`gw:mega`, `gw:theme`, `gw:segmented`) are in `docs/markup-contract.md`, "Script".
54
+ events (`gw:mega`, `gw:theme`, `gw:segmented`, `gw:toc`) are in `docs/markup-contract.md`, "Script".
55
55
 
56
56
  Don't: wire a kit part with your own script (a click handler on a trigger, a class toggled by hand), or load two
57
57
  copies of the script and expect both to work (the first owns the page).
@@ -219,8 +219,27 @@ Variants: `--soft` (on `--gw-bg-soft`), `--link` (the whole card is one `<a>`; t
219
219
  </a>
220
220
  ```
221
221
 
222
+ **A picture on top (0.5.0)**: `.gw-card__media` as the card's first child, around one `<img>` (or `<video>`). It runs
223
+ edge to edge across the card's top, its corners the card's radius inside the hairline, and is an aspect-ratio box the
224
+ picture covers: 16:9 by default, `--wide` 1.91:1 (the 1200 × 630 share image a post usually has, so it fits uncut),
225
+ `--square` 1:1. One shape for every card of a row. The box shows the soft ground until the picture loads.
226
+
227
+ ```html
228
+ <article class="gw-card">
229
+ <div class="gw-card__media"><img src="/img/case-study.webp" alt="" width="640" height="360" loading="lazy"></div>
230
+ <h3>…</h3>
231
+ <p>…</p>
232
+ </article>
233
+ ```
234
+
235
+ Alt text: `alt=""` when the card's title already says what the picture is (a post's cover, a case study's photo); a
236
+ real description when the picture carries something the words do not (a chart, a before and after). Always `width`,
237
+ `height` and `loading="lazy"` (the box keeps its shape before the picture arrives). A list of posts is
238
+ `.gw-post-list` (below, "Article and blog").
239
+
222
240
  Don't: put links or buttons inside a `--link` card (one card, one destination); a bigger shadow or a hover lift; a
223
- radius of your own (cards take the card radius, plans and the quote the panel radius, both from the profile).
241
+ radius of your own (cards take the card radius, plans and the quote the panel radius, both from the profile); a
242
+ `.gw-card__media` anywhere but first in the card; pictures of different shapes in one row.
224
243
 
225
244
  ### Window `.gw-window`
226
245
 
@@ -393,13 +412,13 @@ The HTML a CMS or a markdown renderer writes needs no classes. Inside `.gw-prose
393
412
  | `blockquote` | a 3px rule on its left, muted words (the dashboard's reader quote) |
394
413
  | `code` | a tint chip in `--gw-font-mono` (16px, 14px in `--sm`) that wraps on a phone; in a table it stays whole |
395
414
  | `pre` | a soft box, 14px mono, that scrolls sideways inside itself |
396
- | `table` | as a direct child: the `.gw-table` look, and it scrolls inside its own box when it is wider than the column |
415
+ | `table` | as a direct child: the `.gw-table` look, and it scrolls inside its own box when it is wider than the column. `website.js` (0.5.0) puts it in a box of its own, `div.gw-prose__table`: a region named after its `<caption>` (else its first header cell) that a keyboard can focus and scroll, while the table stays a table for screen readers. Give it a `<caption>` |
397
416
  | `img`, `figure`, `figcaption` | images take the card radius; a caption 14px muted, 12px under its figure |
398
417
  | `hr`, `a` | a hairline with 32px of air; links in the accent, underlined |
399
418
 
400
419
  Kit components inside the prose keep their own look (`.gw-table`, `.gw-window`, `.gw-list--check`, `.gw-quote`,
401
- `.gw-btn`). Prefer the `.gw-table` wrapper (`role="region"`, a name, `tabindex="0"`) when you write the markup: a
402
- keyboard can scroll it.
420
+ `.gw-btn`, `.gw-callout`, `.gw-faq`). Prefer the `.gw-table` wrapper (`role="region"`, a name, `tabindex="0"`) when
421
+ you write the markup; a bare table from the CMS gets the same from `website.js`.
403
422
 
404
423
  ```html
405
424
  <section class="gw-section">
@@ -418,6 +437,163 @@ keyboard can scroll it.
418
437
  Don't: marketing sections inside the prose (end the article, then the section); headings chosen for their size (keep
419
438
  them in order); a page without `.gw-prose` that styles its articles in site CSS (that was the stopgap of gap #46).
420
439
 
440
+ ## Article and blog (0.5.0)
441
+
442
+ A blog post is `templates/sections/article.html`: breadcrumbs, the title, the meta row, a hero image, the contents
443
+ list, the article's own HTML in `.gw-prose` with callouts where they help, the FAQ last. The blog index and "more from
444
+ the blog" are `templates/sections/post-list.html`. See both whole in `demo/article.html` and `demo/blog.html`.
445
+
446
+ | class | for |
447
+ |---|---|
448
+ | `.gw-article` (with `.gw-wrap`, on the `<article>`) | the page's layout: one column on phones; from 1080px the reading column (68ch) and the contents beside it |
449
+ | `.gw-article__head` | breadcrumbs, the `<h1>` (at the section-headline size) and the meta row, 16px apart |
450
+ | `.gw-article__hero` | a `<figure>` with the post's own picture, the card radius; not lazy, it is the first screen |
451
+ | `.gw-breadcrumbs` | the trail above the title: a `<nav>` with a name, an `<ol>`, the page itself last with `aria-current="page"` |
452
+ | `.gw-article-meta`, `__avatar` | author, category, date, read time: 14px muted, a dot between items |
453
+ | `.gw-toc` (`data-gw-toc`) | the contents: links to the article's h2s (and h3s), sticky beside it from 1080px, folded above it below |
454
+ | `.gw-callout` (+ `--note`, `--tip`, `--warning`), `__label` | a note, a tip or a warning inside the article, its kind in words |
455
+ | `.gw-post-list` (+ `--compact`) | a grid of post cards (one, two from 768px, three from 1080px); `--compact`: rows, no card, no picture |
456
+ | `.gw-post` (with `.gw-card`), `__title` | a post card: picture, category, title (its link covers the card), excerpt, meta row |
457
+ | `.gw-pagination`, `__status` | previous and next links with "Page 2 of 12" between them |
458
+
459
+ ### Breadcrumbs `.gw-breadcrumbs`
460
+
461
+ Every level above the page, then the page itself, marked `aria-current="page"` (cut with an ellipsis on a phone:
462
+ the title under it says it in full). The chevrons between items are drawn by the CSS: never type ›, / or > in the
463
+ text, a screen reader would read them out.
464
+
465
+ ```html
466
+ <nav class="gw-breadcrumbs" aria-label="Breadcrumb">
467
+ <ol>
468
+ <li><a href="/blog">Blog</a></li>
469
+ <li><a href="/blog/guides">Guides</a></li>
470
+ <li><a href="/blog/plan-a-product-page" aria-current="page">How to plan a product page</a></li>
471
+ </ol>
472
+ </nav>
473
+ ```
474
+
475
+ The kit does not write structured data. A site that wants the trail in search results adds a BreadcrumbList with the
476
+ same items, each `item` the page's full URL:
477
+
478
+ ```html
479
+ <script type="application/ld+json">
480
+ {"@context": "https://schema.org", "@type": "BreadcrumbList", "itemListElement": [
481
+ {"@type": "ListItem", "position": 1, "name": "Blog", "item": "https://example.com/blog"},
482
+ {"@type": "ListItem", "position": 2, "name": "Guides", "item": "https://example.com/blog/guides"},
483
+ {"@type": "ListItem", "position": 3, "name": "How to plan a product page", "item": "https://example.com/blog/plan-a-product-page"}
484
+ ]}
485
+ </script>
486
+ ```
487
+
488
+ `check` reports breadcrumbs without a named `<nav>`, without an `<ol>`, without `aria-current="page"` on the last item
489
+ (or with it on another one) and with a typed separator (`breadcrumbs-markup`).
490
+
491
+ ### Meta row `.gw-article-meta`
492
+
493
+ Each item a `<span>` (a link sits inside its span). The date is a `<time datetime>`, written "Updated …" when the
494
+ post changed after it was published; the read time counts about 200 words a minute. The avatar is optional, 24px,
495
+ `alt=""` because the name is next to it. The row wraps on a phone, and a wrapped line never starts with a dot.
496
+
497
+ ```html
498
+ <p class="gw-article-meta">
499
+ <span><img class="gw-article-meta__avatar" src="/img/team.webp" alt="" width="24" height="24">GemBoss Team</span>
500
+ <span><a href="/blog/guides">Guides</a></span>
501
+ <span>Updated <time datetime="2026-10-25">October 25, 2026</time></span>
502
+ <span>5 min read</span>
503
+ </p>
504
+ ```
505
+
506
+ ### Contents `.gw-toc`
507
+
508
+ One link per `<h2>` of the article (a nested `<ol>` for its `<h3>`s), with the heading's own words, to the heading's
509
+ id. The markup holds the list, so it works without the script and search engines see it. With `data-gw-toc`,
510
+ `website.js` marks the section in view (`aria-current="true"`: an accent bar, the weight does not change) and fires
511
+ `gw:toc`; it opens the `<details>` from 1080px, where the list sits beside the article and sticks under the header,
512
+ and below 1080px leaves it folded above the article and folds it again when a link is followed. A contents link
513
+ glides to its section, except for a visitor who asked for less motion.
514
+
515
+ ```html
516
+ <nav class="gw-toc" aria-label="On this page" data-gw-toc>
517
+ <details>
518
+ <summary>On this page</summary>
519
+ <ol>
520
+ <li><a href="#start-from-the-questions">Start from the questions</a></li>
521
+ <li><a href="#first-screen">Answer the first question on the first screen</a>
522
+ <ol><li><a href="#write-the-title">Write the title for the shopper</a></li></ol>
523
+ </li>
524
+ <li><a href="#faq">Frequently asked questions</a></li>
525
+ </ol>
526
+ </details>
527
+ </nav>
528
+ ```
529
+
530
+ Put it in the `<article class="gw-wrap gw-article">` between the hero and the `.gw-prose`. `check` reports a link to
531
+ an id that is not on the page (`toc-target`). Don't: list h4s; a contents list on a page with fewer than three h2s;
532
+ headings written for the list rather than the reader.
533
+
534
+ ### Callout `.gw-callout`
535
+
536
+ A note (`--note`, on the accent's tint), a tip (`--tip`, success's tint) or a warning (`--warning`, the warning tint),
537
+ inside or next to the prose. The kind is said in words: `__label` ("Note", "Tip", "Warning", or the same word in the
538
+ page's language), with an icon before it in the kind's hue. The tint only repeats it.
539
+
540
+ ```html
541
+ <div class="gw-callout gw-callout--tip" role="note">
542
+ <p class="gw-callout__label">Tip</p>
543
+ <p>Ask someone who has never seen the product to find the return window while you watch.</p>
544
+ </div>
545
+ ```
546
+
547
+ Don't: a callout told by its colour alone (`check` warns: `callout-label`); a callout as a section band or an ad
548
+ ("Try GemBoss free!"); more than one callout every few sections; a whole procedure inside one.
549
+
550
+ ### Post list `.gw-post-list` and pagination `.gw-pagination`
551
+
552
+ A `<ul role="list">` of post cards. The card is a `.gw-card.gw-post`: a `.gw-card__media` picture (`alt=""`, lazy),
553
+ the category as a `.gw-label`, the title in a heading one level below the section's, one or two lines of excerpt and
554
+ a meta row. The title's link covers the whole card, so the card is one target and a screen reader hears the title
555
+ alone. Pagination is two links and the page number, no script: `rel="prev"` and `rel="next"`, and the link that does
556
+ not exist is left out.
557
+
558
+ ```html
559
+ <ul class="gw-post-list" role="list">
560
+ <li>
561
+ <article class="gw-card gw-post">
562
+ <div class="gw-card__media"><img src="/img/post.webp" alt="" width="640" height="360" loading="lazy"></div>
563
+ <p class="gw-label">Themes</p>
564
+ <h3 class="gw-post__title"><a href="/blog/how-to-choose-a-theme">How to choose a Shopify theme that converts</a></h3>
565
+ <p>A checklist for choosing a theme: speed, mobile, features and fit.</p>
566
+ <p class="gw-article-meta"><span><time datetime="2026-08-08">Aug 8, 2026</time></span><span>8 min read</span></p>
567
+ </article>
568
+ </li>
569
+ </ul>
570
+ <nav class="gw-pagination" aria-label="Blog pages">
571
+ <a class="gw-btn gw-btn--secondary" href="/blog?page=1" rel="prev">Newer posts</a>
572
+ <p class="gw-pagination__status">Page 2 of 12</p>
573
+ <a class="gw-btn gw-btn--secondary" href="/blog?page=3" rel="next">Older posts</a>
574
+ </nav>
575
+ ```
576
+
577
+ `--compact` is the same markup without the picture, drawn as rows with a hairline between them: a long archive, a
578
+ "more on this" list in a narrow column.
579
+
580
+ Don't: a second link or a button inside a post card; an excerpt longer than two lines; numbered page links (prev and
581
+ next only); "Read more" as a link.
582
+
583
+ ### FAQ at the end of an article
584
+
585
+ The last `<h2>` of the prose, then a `.gw-faq`. A site that marks it up as FAQPage does so only when every answer is
586
+ visible on the page, with the same words:
587
+
588
+ ```html
589
+ <script type="application/ld+json">
590
+ {"@context": "https://schema.org", "@type": "FAQPage", "mainEntity": [
591
+ {"@type": "Question", "name": "How long should a product description be?",
592
+ "acceptedAnswer": {"@type": "Answer", "text": "Long enough to answer the questions on your list, and no longer."}}
593
+ ]}
594
+ </script>
595
+ ```
596
+
421
597
  ## Motion
422
598
 
423
599
  | class | for |
@@ -427,6 +603,14 @@ them in order); a page without `.gw-prose` that styles its articles in site CSS
427
603
  Put it on a block (a grid, a list, a window), not on each card in a grid. Don't use it on the hero or anything in
428
604
  the first screen, and don't animate anything but `transform` and `opacity`.
429
605
 
606
+ ## Additions to the markup contract in 0.5.0
607
+
608
+ The blog parts: `.gw-breadcrumbs`, `.gw-article-meta` (`__avatar`), `.gw-article` (`__head`, `__hero`), `.gw-toc` with
609
+ its `data-gw-toc` hook and the `gw:toc` event (`{ id }`), `.gw-callout` (`--note`, `--tip`, `--warning`, `__label`),
610
+ `.gw-card__media` (`--wide`, `--square`), `.gw-post-list` (`--compact`), `.gw-post` (`__title`), `.gw-pagination`
611
+ (`__status`), and the script's `.gw-prose__table` box with the `.is-wrapped` state on a prose table. One token:
612
+ `--gw-warning-soft`. No markup or class of 0.4.0 changes.
613
+
430
614
  ## Additions to the markup contract in 0.4.0
431
615
 
432
616
  The script: `init(root)` and `destroy(root)` (`window.gwWebsite`, or `js/website.mjs`), the `data-gw-ready` mark on