@gemboss/website-ui 0.0.0-stage → 0.1.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/AGENTS.md +174 -0
- package/CHANGELOG.md +19 -0
- package/README.md +117 -2
- package/bin/gemboss-website.mjs +78 -0
- package/bin/lib/check.mjs +642 -0
- package/bin/lib/gap.mjs +189 -0
- package/bin/lib/init.mjs +99 -0
- package/bin/lib/upgrade.mjs +155 -0
- package/bin/lib/util.mjs +147 -0
- package/css/base.css +107 -0
- package/css/components.css +236 -0
- package/css/footer.css +53 -0
- package/css/header.css +231 -0
- package/css/layout.css +59 -0
- package/css/sections.css +173 -0
- package/css/tokens.css +198 -0
- package/demo/index.html +629 -0
- package/demo/theme-example.html +133 -0
- package/docs/components.md +299 -0
- package/docs/markup-contract.md +115 -0
- package/docs/philosophy.md +69 -0
- package/docs/theming.md +95 -0
- package/js/website.js +149 -0
- package/package.json +50 -4
- package/skill/SKILL.md +48 -0
- package/system.json +120 -0
- package/templates/footer.html +40 -0
- package/templates/header.html +60 -0
- package/templates/page.html +134 -0
- package/templates/sections/cta.html +15 -0
- package/templates/sections/faq.html +24 -0
- package/templates/sections/features.html +32 -0
- package/templates/sections/hero.html +25 -0
- package/templates/sections/logos.html +15 -0
- package/templates/sections/pricing.html +39 -0
- package/templates/sections/quote.html +13 -0
- package/templates/sections/showcase.html +24 -0
- package/templates/sections/split.html +25 -0
- package/templates/sections/stats.html +26 -0
- package/templates/sections/steps.html +17 -0
- package/website.css +1064 -0
- package/website.min.css +1 -0
|
@@ -0,0 +1,133 @@
|
|
|
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>Theme example · website UI kit</title>
|
|
7
|
+
<meta name="description" content="The same kit markup with a GemPages-style accent: only the --gw-accent variables change.">
|
|
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
|
+
<style>
|
|
14
|
+
/* The whole brand theme: the accent family, light and dark, in one :root block (docs/theming.md).
|
|
15
|
+
Contrast checked: #1e5eff on #ffffff is 5.1:1, #6b98ff on #0d0d12 is 7.0:1. */
|
|
16
|
+
:root {
|
|
17
|
+
--gw-accent-light: #1e5eff;
|
|
18
|
+
--gw-accent-strong-light: #1547d1;
|
|
19
|
+
--gw-accent-soft-light: #eaf0ff;
|
|
20
|
+
--gw-accent-dark: #6b98ff;
|
|
21
|
+
--gw-accent-strong-dark: #a8c0ff;
|
|
22
|
+
--gw-accent-soft-dark: #16213d;
|
|
23
|
+
}
|
|
24
|
+
</style>
|
|
25
|
+
</head>
|
|
26
|
+
<body class="gw-page">
|
|
27
|
+
<a class="gw-skip" href="#main">Skip to content</a>
|
|
28
|
+
|
|
29
|
+
<div class="gw-announce" role="region" aria-label="Announcement">Theme example: the markup of the GemBoss demo, with only the accent changed. <a href="index.html">Back to the full demo</a></div>
|
|
30
|
+
<header class="gw-header" data-gw-header>
|
|
31
|
+
<div class="gw-wrap gw-header__bar">
|
|
32
|
+
<a class="gw-brand" href="index.html"><svg class="gw-brand__mark" viewBox="0 0 26 26" aria-hidden="true"><rect width="26" height="26" rx="6" style="fill:var(--gw-accent)"/><path d="M8 8h10M8 13h10M8 18h6" fill="none" stroke="#ffffff" stroke-width="2" stroke-linecap="round"/></svg><span class="gw-brand__name">GemPages</span></a>
|
|
33
|
+
<nav class="gw-nav" aria-label="Main">
|
|
34
|
+
<ul class="gw-nav__list">
|
|
35
|
+
<li class="gw-nav__item"><a class="gw-nav__link" href="https://gemboss.ai/gempages" aria-current="page">Page builder</a></li>
|
|
36
|
+
<li class="gw-nav__item"><a class="gw-nav__link" href="https://gemboss.ai/gemthemes">Section library</a></li>
|
|
37
|
+
<li class="gw-nav__item"><a class="gw-nav__link" href="https://gemboss.ai/pricing">Pricing</a></li>
|
|
38
|
+
</ul>
|
|
39
|
+
</nav>
|
|
40
|
+
<div class="gw-header__actions">
|
|
41
|
+
<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>
|
|
42
|
+
<a class="gw-nav__link gw-header__signin" href="https://admin.gemboss.ai/login">Sign in</a>
|
|
43
|
+
<a class="gw-btn gw-btn--secondary gw-btn--sm" href="https://gemboss.ai/contact">Book a demo</a>
|
|
44
|
+
<a class="gw-btn gw-btn--sm" href="https://admin.gemboss.ai/signup">Start free</a>
|
|
45
|
+
<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>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
<div class="gw-mobile-menu" id="gw-mobile-menu" hidden>
|
|
49
|
+
<nav class="gw-wrap" aria-label="Main, mobile">
|
|
50
|
+
<a class="gw-mobile-menu__top" href="https://gemboss.ai/gempages" aria-current="page">Page builder</a>
|
|
51
|
+
<a class="gw-mobile-menu__top" href="https://gemboss.ai/gemthemes">Section library</a>
|
|
52
|
+
<a class="gw-mobile-menu__top" href="https://gemboss.ai/pricing">Pricing</a>
|
|
53
|
+
<div class="gw-mobile-menu__actions">
|
|
54
|
+
<a class="gw-btn gw-btn--block" href="https://admin.gemboss.ai/signup">Start free</a>
|
|
55
|
+
<a class="gw-btn gw-btn--secondary gw-btn--block" href="https://gemboss.ai/contact">Book a demo</a>
|
|
56
|
+
<a class="gw-mobile-menu__link" href="https://admin.gemboss.ai/login">Sign in</a>
|
|
57
|
+
</div>
|
|
58
|
+
</nav>
|
|
59
|
+
</div>
|
|
60
|
+
</header>
|
|
61
|
+
|
|
62
|
+
<main id="main">
|
|
63
|
+
<section class="gw-hero" aria-labelledby="hero-h">
|
|
64
|
+
<div class="gw-hero__wash" aria-hidden="true"></div>
|
|
65
|
+
<div class="gw-wrap">
|
|
66
|
+
<p class="gw-label">Page builder</p>
|
|
67
|
+
<h1 id="hero-h"><span class="gw-dim">Describe it. Watch the page change.</span> Ship it.</h1>
|
|
68
|
+
<p class="gw-lead">The page builder in GemBoss is a chat beside your live page: ask for a section, a headline or a photo, and watch it change. Nothing reaches shoppers until you press Publish live.</p>
|
|
69
|
+
<div class="gw-actions">
|
|
70
|
+
<a class="gw-btn" href="https://admin.gemboss.ai/signup">Start free</a>
|
|
71
|
+
<a class="gw-btn gw-btn--secondary" href="https://gemboss.ai/contact">Book a demo</a>
|
|
72
|
+
</div>
|
|
73
|
+
</div>
|
|
74
|
+
</section>
|
|
75
|
+
|
|
76
|
+
<section class="gw-section gw-section--soft" aria-labelledby="how-h">
|
|
77
|
+
<div class="gw-wrap">
|
|
78
|
+
<div class="gw-section__head">
|
|
79
|
+
<p class="gw-label">How a change happens</p>
|
|
80
|
+
<h2 id="how-h"><span class="gw-dim">Ask, watch, publish.</span> You are the one who ships.</h2>
|
|
81
|
+
<div class="gw-actions">
|
|
82
|
+
<button class="gw-chip" type="button" aria-pressed="true">New section</button>
|
|
83
|
+
<button class="gw-chip" type="button" aria-pressed="false">Copy</button>
|
|
84
|
+
<button class="gw-chip" type="button" aria-pressed="false">Media</button>
|
|
85
|
+
<span class="gw-badge gw-badge--accent">Draft, not live yet</span>
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
<div class="gw-grid--3">
|
|
89
|
+
<div class="gw-card">
|
|
90
|
+
<h3>Ask</h3>
|
|
91
|
+
<p>Type it in plain words, or click a section and ask about that one.</p>
|
|
92
|
+
</div>
|
|
93
|
+
<div class="gw-card">
|
|
94
|
+
<h3>Watch</h3>
|
|
95
|
+
<p>It edits the page in front of you and checks how it looks.</p>
|
|
96
|
+
</div>
|
|
97
|
+
<a class="gw-card gw-card--link" href="https://gemboss.ai/gempages">
|
|
98
|
+
<h3>Publish</h3>
|
|
99
|
+
<p>Changes stay a draft until you press Publish live. Undo any step.</p>
|
|
100
|
+
<span class="gw-link gw-link--arrow">See the page builder</span>
|
|
101
|
+
</a>
|
|
102
|
+
</div>
|
|
103
|
+
</div>
|
|
104
|
+
</section>
|
|
105
|
+
|
|
106
|
+
<section class="gw-section gw-band--night" aria-labelledby="cta-h">
|
|
107
|
+
<div class="gw-wrap gw-cta">
|
|
108
|
+
<p class="gw-label">One engine underneath</p>
|
|
109
|
+
<h2 id="cta-h">Looks like your store. Because it is built from it.</h2>
|
|
110
|
+
<p class="gw-lead">Every page uses your storefront's sections and brand settings. Read the <a href="https://gemboss.ai/docs">docs</a> for the MCP tools.</p>
|
|
111
|
+
<div class="gw-actions">
|
|
112
|
+
<a class="gw-btn" href="https://admin.gemboss.ai/signup">Start free</a>
|
|
113
|
+
<a class="gw-btn gw-btn--secondary" href="https://gemboss.ai/contact">Book a demo</a>
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
</section>
|
|
117
|
+
</main>
|
|
118
|
+
|
|
119
|
+
<footer class="gw-footer">
|
|
120
|
+
<div class="gw-wrap">
|
|
121
|
+
<div class="gw-footer__bottom">
|
|
122
|
+
<span>© 2026 GemBoss. All rights reserved.</span>
|
|
123
|
+
<ul aria-label="Legal">
|
|
124
|
+
<li><a href="https://gemboss.ai/privacy">Privacy</a></li>
|
|
125
|
+
<li><a href="https://gemboss.ai/terms">Terms</a></li>
|
|
126
|
+
</ul>
|
|
127
|
+
</div>
|
|
128
|
+
</div>
|
|
129
|
+
</footer>
|
|
130
|
+
|
|
131
|
+
<script src="../js/website.js" defer></script>
|
|
132
|
+
</body>
|
|
133
|
+
</html>
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
# Components and sections
|
|
2
|
+
|
|
3
|
+
Every class in `website.css`, what it is for, its variants, a minimal example and what not to do with it. Open
|
|
4
|
+
`demo/index.html` to see all of them on one page, and start pages from `templates/`. The markup that the script
|
|
5
|
+
(`js/website.js`) relies on is fixed in `docs/markup-contract.md`; this file follows it.
|
|
6
|
+
|
|
7
|
+
Conventions: kit classes start with `gw-`, variants are `--name`, parts are `__name`, states set by the script are
|
|
8
|
+
`is-*`. Never style a `.gw-*` class in your site's CSS: if the kit's version is wrong for you, that is a gap
|
|
9
|
+
(`AGENTS.md` section 9).
|
|
10
|
+
|
|
11
|
+
Spacing between the children of text blocks is automatic: inside `.gw-section__head`, the hero, a split column,
|
|
12
|
+
`.gw-cta`, `.gw-card`, `.gw-feature` and `.gw-plan`, each child is 16px below the previous one, a `.gw-actions` row
|
|
13
|
+
32px, a `.gw-list--check` 24px. Do not add margins to fix rhythm; reorder or remove content instead.
|
|
14
|
+
|
|
15
|
+
## Page
|
|
16
|
+
|
|
17
|
+
| class | for |
|
|
18
|
+
|---|---|
|
|
19
|
+
| `.gw-page` | on `<body>`: the footer stays at the bottom of a short page |
|
|
20
|
+
| `.gw-skip` | the first element in `<body>`: "Skip to content", visible only on keyboard focus |
|
|
21
|
+
|
|
22
|
+
```html
|
|
23
|
+
<body class="gw-page">
|
|
24
|
+
<a class="gw-skip" href="#main">Skip to content</a>
|
|
25
|
+
…
|
|
26
|
+
<main id="main">…</main>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Don't remove the skip link, and don't leave out `id="main"`.
|
|
30
|
+
|
|
31
|
+
## Type and text
|
|
32
|
+
|
|
33
|
+
| class | for |
|
|
34
|
+
|---|---|
|
|
35
|
+
| `h1`, `h2` (and `.gw-h1`, `.gw-h2`) | display sizes: h1 `clamp(40px, 4.6vw, 68px)`, h2 `clamp(32px, 3.4vw, 52px)`, weight 600, tracking −0.03em |
|
|
36
|
+
| `h3`, `h4` (and `.gw-h3`, `.gw-h4`) | 24px / 650 and 20px / 600 |
|
|
37
|
+
| `.gw-dim` | the muted first sentence of the house headline shape |
|
|
38
|
+
| `.gw-label` | the label above a heading: 13px, muted, led by the 8px accent square |
|
|
39
|
+
| `.gw-lead` | the one or two lines under a heading (18px, 20px in the hero, muted, max 60ch) |
|
|
40
|
+
| `.gw-note` | a short reassurance under actions (14px, muted) |
|
|
41
|
+
| `.gw-link` | an inline link in the accent, underlined |
|
|
42
|
+
| `.gw-link--arrow` | a standalone "go there" link with a → that moves 2px on hover |
|
|
43
|
+
|
|
44
|
+
```html
|
|
45
|
+
<p class="gw-label">How it works</p>
|
|
46
|
+
<h2><span class="gw-dim">Give it a product.</span> Watch the engine work.</h2>
|
|
47
|
+
<p class="gw-lead">One or two lines, no more.</p>
|
|
48
|
+
<a class="gw-link gw-link--arrow" href="/funnel">See the funnel builder</a>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Plain links inside `p`, `dd`, `td`, `figcaption` and check-list items get the link style without a class.
|
|
52
|
+
`.gw-h1`…`.gw-h4` exist so the visual size can differ from the heading level: keep one `<h1>` per page and headings in
|
|
53
|
+
order, then choose the look.
|
|
54
|
+
|
|
55
|
+
Don't: uppercase or letter-spaced labels; a label longer than a few words; the accent as body text; "Learn more" or
|
|
56
|
+
"Click here" as the whole link text; more than two lines under a heading.
|
|
57
|
+
|
|
58
|
+
## Layout
|
|
59
|
+
|
|
60
|
+
| class | for |
|
|
61
|
+
|---|---|
|
|
62
|
+
| `.gw-wrap` | content width: 1120px max with 22px gutters |
|
|
63
|
+
| `.gw-wrap--narrow` | 780px max, for FAQ and long reading; use alone or with `.gw-wrap` |
|
|
64
|
+
| `.gw-section` | a section's vertical rhythm (`--gw-space-section`) |
|
|
65
|
+
| `.gw-section--soft` | on `--gw-bg-soft`, to separate a section without a line |
|
|
66
|
+
| `.gw-section--tight` | less padding (40px, 64px from 768px), for proof strips and follow-on tables |
|
|
67
|
+
| `.gw-section__head` | label + h2 + lead, max 660px; 40–48px above the content |
|
|
68
|
+
| `.gw-section__head--center` | the same, centred |
|
|
69
|
+
| `.gw-grid`, `.gw-grid--2`, `.gw-grid--3`, `.gw-grid--4` | equal columns: one on phones; 2 and 3 from 768px; 4 is 2 from 480px and 4 from 1080px |
|
|
70
|
+
| `.gw-actions` | a row of actions that wraps; on phones the hero and CTA buttons go full width |
|
|
71
|
+
| `.gw-band--night` | a dark band: the dark palette on the night ground, in both themes |
|
|
72
|
+
|
|
73
|
+
```html
|
|
74
|
+
<section class="gw-section gw-section--soft">
|
|
75
|
+
<div class="gw-wrap">
|
|
76
|
+
<div class="gw-section__head">…</div>
|
|
77
|
+
<div class="gw-grid--3">…</div>
|
|
78
|
+
</div>
|
|
79
|
+
</section>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Don't: more than three night bands on a page (the closing CTA does not count), or two in a row; a grey or cream page background (white or
|
|
83
|
+
`--gw-bg-soft` only); a grid with a single item (use a narrower wrap instead); fixed widths in px on content.
|
|
84
|
+
|
|
85
|
+
## Components
|
|
86
|
+
|
|
87
|
+
### Buttons `.gw-btn`
|
|
88
|
+
|
|
89
|
+
40px tall, radius 8, 14px/600, sentence case, ink fill. Variants: `--secondary` (hairline, transparent), `--ghost`
|
|
90
|
+
(no frame), `--on-night` (light fill for a dark surface that is not a `.gw-band--night`), `--sm` (36px, with a 44px
|
|
91
|
+
hit area), `--lg` (48px, 16px type), `--block` (full width). On touch screens every button is at least 44px tall and
|
|
92
|
+
its label may wrap. Inside a night band the default button turns light by itself.
|
|
93
|
+
|
|
94
|
+
```html
|
|
95
|
+
<div class="gw-actions">
|
|
96
|
+
<a class="gw-btn" href="/signup">Start free</a>
|
|
97
|
+
<a class="gw-btn gw-btn--secondary" href="/contact">Book a demo</a>
|
|
98
|
+
</div>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Don't: an accent, gradient or wash fill; pill-shaped buttons; uppercase; two filled buttons side by side (one
|
|
102
|
+
`.gw-btn` per view, the second is `--secondary` or a link); a `<div>` with a click handler instead of `<a>`/`<button>`.
|
|
103
|
+
|
|
104
|
+
### Chips `.gw-chip`
|
|
105
|
+
|
|
106
|
+
A small selectable token, a pill. Active: `.is-active`, `aria-pressed="true"` or `aria-selected="true"` (accent
|
|
107
|
+
hairline on accent-soft). As a `<button>`, `<a>` or `<label>` it is 44px tall on touch screens.
|
|
108
|
+
|
|
109
|
+
```html
|
|
110
|
+
<button class="gw-chip" type="button" aria-pressed="true">Serum</button>
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Don't: use a chip as the page's action; square it; more than about six in a row.
|
|
114
|
+
|
|
115
|
+
### Badges `.gw-badge`
|
|
116
|
+
|
|
117
|
+
Small status, a pill, 12px. Variants: `--accent` (a test, the recommended plan), `--success` and `--warning` (state:
|
|
118
|
+
a coloured dot, ink words, because the state hues fail 4.5:1 as small text on a tint).
|
|
119
|
+
|
|
120
|
+
```html
|
|
121
|
+
<span class="gw-badge gw-badge--success">Live</span>
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Don't: make a badge clickable; write a sentence in it; use success or warning for anything but state.
|
|
125
|
+
|
|
126
|
+
### Cards `.gw-card`
|
|
127
|
+
|
|
128
|
+
A white box with a 1px hairline, radius 12, the resting shadow `--gw-shadow` (as the dashboard's cards), 24px padding
|
|
129
|
+
(32px from 768px). It sits: no hover lift. `--soft` is a tint and has no shadow.
|
|
130
|
+
Variants: `--soft` (on `--gw-bg-soft`), `--link` (the whole card is one `<a>`; the border darkens on hover).
|
|
131
|
+
|
|
132
|
+
```html
|
|
133
|
+
<a class="gw-card gw-card--link" href="/mcp">
|
|
134
|
+
<h3>Open to your team and agents</h3>
|
|
135
|
+
<p>100+ MCP tools, so your team, your agency or your own AI can drive the engine.</p>
|
|
136
|
+
<span class="gw-link gw-link--arrow">See MCP and agents</span>
|
|
137
|
+
</a>
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Don't: put links or buttons inside a `--link` card (one card, one destination); a bigger shadow or a hover lift; radius
|
|
141
|
+
other than 12 (16 is for large panels: plans, quote).
|
|
142
|
+
|
|
143
|
+
### Window `.gw-window`
|
|
144
|
+
|
|
145
|
+
A framed screen: `__bar` (three dots and where the screen lives) and `__body` (16px padding, none around a single
|
|
146
|
+
`<img>`). Use it around real product screenshots, or around a drawn mock-up built in the site's CSS with the tokens.
|
|
147
|
+
|
|
148
|
+
```html
|
|
149
|
+
<div class="gw-window">
|
|
150
|
+
<div class="gw-window__bar">Funnels / Radiance Serum</div>
|
|
151
|
+
<div class="gw-window__body"><img src="/img/funnels.webp" alt="The funnel list with four steps" width="1200" height="750"></div>
|
|
152
|
+
</div>
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Don't: put interactive controls inside a mock-up; show made-up numbers without "Illustrative" under them.
|
|
156
|
+
|
|
157
|
+
### Icon `.gw-icon`
|
|
158
|
+
|
|
159
|
+
A 20px box for an inline stroke SVG (1.7–2px stroke, `currentColor`, `aria-hidden="true"`). Inside `.gw-feature` it
|
|
160
|
+
becomes a 40px tile with a hairline.
|
|
161
|
+
|
|
162
|
+
```html
|
|
163
|
+
<span class="gw-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7">…</svg></span>
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Don't: emoji as icons; filled multi-colour icons; icon-only buttons without `aria-label`.
|
|
167
|
+
|
|
168
|
+
### Check list `.gw-list--check`
|
|
169
|
+
|
|
170
|
+
A `<ul>` whose items are led by an accent check mark.
|
|
171
|
+
|
|
172
|
+
```html
|
|
173
|
+
<ul class="gw-list--check"><li>Checkout stays on Shopify</li><li>No overage fees</li></ul>
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Don't: more than five or six items; full paragraphs as items.
|
|
177
|
+
|
|
178
|
+
### Table `.gw-table`
|
|
179
|
+
|
|
180
|
+
A wrapper around a plain `<table>`: hairline, radius 12, and it scrolls inside its own box when the table is wider
|
|
181
|
+
than the screen. `--compare`: centred values, a 640px minimum width and a sticky first column, for plan comparisons.
|
|
182
|
+
Give the wrapper `role="region"`, an accessible name and `tabindex="0"` so keyboard users can scroll it.
|
|
183
|
+
|
|
184
|
+
```html
|
|
185
|
+
<div class="gw-table gw-table--compare" role="region" aria-labelledby="compare-h" tabindex="0">
|
|
186
|
+
<table>
|
|
187
|
+
<thead><tr><th scope="col">Plan</th><th scope="col">Starter</th></tr></thead>
|
|
188
|
+
<tbody><tr><th scope="row">Price a month</th><td>$49</td></tr></tbody>
|
|
189
|
+
</table>
|
|
190
|
+
</div>
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Don't: put the class on the `<table>` itself; tables for layout; colour cells to show "yes".
|
|
194
|
+
|
|
195
|
+
### FAQ `.gw-faq`
|
|
196
|
+
|
|
197
|
+
Native `<details class="gw-faq__item">` with a `<summary>`, no script. The + turns into × when open.
|
|
198
|
+
|
|
199
|
+
```html
|
|
200
|
+
<div class="gw-faq">
|
|
201
|
+
<details class="gw-faq__item"><summary>Does GemBoss run my ads?</summary><p>No. …</p></details>
|
|
202
|
+
</div>
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
Don't: hide content a reader needs to decide (prices, terms) only inside a closed answer; more than eight questions.
|
|
206
|
+
|
|
207
|
+
### Not in 0.1.0
|
|
208
|
+
|
|
209
|
+
`.gw-tabs` does not exist yet. If a page needs tabs, build a stopgap (`kitgap-tabs`) and report the gap.
|
|
210
|
+
|
|
211
|
+
## Header
|
|
212
|
+
|
|
213
|
+
| class | for |
|
|
214
|
+
|---|---|
|
|
215
|
+
| `.gw-announce` | optional one-sentence bar above the header, with one link |
|
|
216
|
+
| `.gw-header` (`data-gw-header`) | the sticky, flat 64px bar with one hairline; `.is-scrolled` darkens the hairline |
|
|
217
|
+
| `.gw-header__bar` | the row inside (`.gw-wrap gw-header__bar`) |
|
|
218
|
+
| `.gw-brand`, `__mark`, `__name` | logo (26px) and name, linking home |
|
|
219
|
+
| `.gw-nav`, `__list`, `__item`, `__trigger`, `__link` | the desktop nav (from 1080px); `__trigger` opens a mega panel, `__link` is a plain link; `aria-current="page"` underlines it in the accent |
|
|
220
|
+
| `.gw-mega`, `__grid`, `__col`, `__heading`, `__link`, `__icon`, `__feature` | a floating card centred under the bar (radius 20, raised shadow, as on gemboss.ai): columns of links with an icon and one line each, and at most one feature card |
|
|
221
|
+
| `.gw-header__actions` | theme toggle, Sign in, Book a demo, Start free, menu button |
|
|
222
|
+
| `.gw-header__signin` | with `.gw-nav__link`: hidden below 1080px (it moves into the mobile menu) |
|
|
223
|
+
| `.gw-theme-toggle` | icon button (`data-gw-theme-toggle`), 40px, 44px on touch |
|
|
224
|
+
| `.gw-menu-toggle`, `__open`, `__close` | the menu button below 1080px; it shows `__open` or `__close` from `aria-expanded` |
|
|
225
|
+
| `.gw-mobile-menu` | the full-height sheet under the bar (`hidden` until opened); `html.is-menu-open` locks the page |
|
|
226
|
+
| `.gw-mobile-menu__group` | a `<details>` group with a `<summary>` row |
|
|
227
|
+
| `.gw-mobile-menu__list`, `__link` | the links inside a group, 44px rows |
|
|
228
|
+
| `.gw-mobile-menu__top` | a top-level row without a group (Pricing) |
|
|
229
|
+
| `.gw-mobile-menu__actions` | the buttons and Sign in at the end of the sheet |
|
|
230
|
+
|
|
231
|
+
Header buttons: the secondary one shows from 768px, the primary one from 480px; below that they live in the mobile
|
|
232
|
+
menu. Full markup: `templates/header.html`.
|
|
233
|
+
|
|
234
|
+
Don't: a floating, rounded or blurred header; more than five top-level items; a second filled button in the bar; a
|
|
235
|
+
hero pulled up under the header.
|
|
236
|
+
|
|
237
|
+
## Footer
|
|
238
|
+
|
|
239
|
+
| class | for |
|
|
240
|
+
|---|---|
|
|
241
|
+
| `.gw-footer` | the footer: one hairline on top, white like the page |
|
|
242
|
+
| `.gw-footer__grid` | brand block and link columns: 2 columns on phones, 3 from 768px, one row from 1080px |
|
|
243
|
+
| `.gw-footer__brand` | the brand and one sentence, full width on phones |
|
|
244
|
+
| `.gw-footer__col`, `__heading` | a `<nav>` column: a sentence-case heading and a `<ul>` of links |
|
|
245
|
+
| `.gw-footer__bottom` | copyright, legal links, social links; alone (no grid above), it drops its top rule |
|
|
246
|
+
|
|
247
|
+
Full markup: `templates/footer.html`. Don't: uppercase column headings; a newsletter form that stores nothing.
|
|
248
|
+
|
|
249
|
+
## Sections
|
|
250
|
+
|
|
251
|
+
| class | for |
|
|
252
|
+
|---|---|
|
|
253
|
+
| `.gw-hero` | the first screen and the only `<h1>`; `.gw-dim` in its h1 sits on its own line |
|
|
254
|
+
| `.gw-hero__wash` | an empty `aria-hidden` div, first in the hero: the soft colour wash (the one place for wash hues) |
|
|
255
|
+
| `.gw-hero--center`, `--compact` | centred; less height and an h2-sized h1 for subpages |
|
|
256
|
+
| `.gw-logos` | a proof strip: a short line and a `<ul>` of logos (28px tall) or wordmarks |
|
|
257
|
+
| `.gw-stats`, `__item`, `__value`, `__label`, `__source` | three or four facts, each with its source |
|
|
258
|
+
| `.gw-features` + `.gw-feature` | with a `.gw-grid--*`: icon, title, one or two lines |
|
|
259
|
+
| `.gw-split`, `--reverse` | words beside a figure; two columns from 768px, words first on phones |
|
|
260
|
+
| `.gw-showcase` | a night band with one large `.gw-window` and two or three `.gw-feature` points |
|
|
261
|
+
| `.gw-steps` | an `<ol>` of three or four steps, numbered by the list |
|
|
262
|
+
| `.gw-quote` | one real testimonial: `<figure>`, `<blockquote>`, `<figcaption>` with name, role, company |
|
|
263
|
+
| `.gw-pricing` + `.gw-plan`, `--featured`, `__price` | plan cards; the featured one has an accent hairline and its badge sits on the top edge |
|
|
264
|
+
| `.gw-cta` | the closing call to action, centred; put it in a night band or a soft section |
|
|
265
|
+
|
|
266
|
+
```html
|
|
267
|
+
<section class="gw-section">
|
|
268
|
+
<div class="gw-wrap">
|
|
269
|
+
<ul class="gw-stats">
|
|
270
|
+
<li class="gw-stats__item">
|
|
271
|
+
<p class="gw-stats__value">2.1 s</p>
|
|
272
|
+
<p class="gw-stats__label">Largest Contentful Paint on mobile</p>
|
|
273
|
+
<p class="gw-stats__source">Live GemBoss store, simulated 4G, median of 8 Lighthouse runs, 10 Oct 2026</p>
|
|
274
|
+
</li>
|
|
275
|
+
</ul>
|
|
276
|
+
</div>
|
|
277
|
+
</section>
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
One snippet per section, with its limits in a comment, is in `templates/sections/`.
|
|
281
|
+
|
|
282
|
+
Don't: a number without a source; logos or quotes you do not have permission for; a filled button on every plan
|
|
283
|
+
(only the featured one); a hero without a real first line of content above the fold on a 390px phone.
|
|
284
|
+
|
|
285
|
+
## Motion
|
|
286
|
+
|
|
287
|
+
| class | for |
|
|
288
|
+
|---|---|
|
|
289
|
+
| `.gw-reveal` | fades and rises 24px into place when 15% visible (the script adds `.is-in`); shown anyway after 2.5s, and still under `prefers-reduced-motion` |
|
|
290
|
+
|
|
291
|
+
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
|
|
292
|
+
the first screen, and don't animate anything but `transform` and `opacity`.
|
|
293
|
+
|
|
294
|
+
## Additions to the markup contract in 0.1.0
|
|
295
|
+
|
|
296
|
+
The contract names the classes the script relies on; these CSS-only helpers were added with it: `.gw-page`
|
|
297
|
+
(sticky footer), `.gw-h1`…`.gw-h4`, `.gw-lead`, `.gw-note`, `.gw-actions`, `.gw-footer__brand`,
|
|
298
|
+
`.gw-stats__source`, `.gw-plan__price`, `.gw-menu-toggle__open` / `__close`, and the mobile menu parts
|
|
299
|
+
`__group`, `__list`, `__link`, `__top`, `__actions`. `.gw-table` is the scrolling wrapper around a `<table>`.
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Markup contract (CSS ↔ JS ↔ templates)
|
|
2
|
+
|
|
3
|
+
The full class list, including the CSS-only helpers added while building 0.1.0 (`.gw-h1`–`.gw-h4`, `.gw-lead`,
|
|
4
|
+
`.gw-note`, `.gw-actions`, `.gw-stats__source`, `.gw-plan__price`, the mobile menu parts…), is `docs/components.md`.
|
|
5
|
+
|
|
6
|
+
The CSS (`css/*.css`), the script (`js/website.js`) and the templates (`templates/`) agree on exactly this. Change it
|
|
7
|
+
here first, then in all three.
|
|
8
|
+
|
|
9
|
+
Prefixes: kit classes `gw-`, kit CSS variables `--gw-`, state classes `is-` (set by the script), hooks `data-gw-*`.
|
|
10
|
+
BEM-ish: `.gw-block`, `.gw-block__part`, `.gw-block--variant`.
|
|
11
|
+
|
|
12
|
+
## Page
|
|
13
|
+
|
|
14
|
+
```html
|
|
15
|
+
<html lang="en" data-theme?="light|dark"> <!-- absent = follow the system; the toggle sets it -->
|
|
16
|
+
<body class="gw-page">
|
|
17
|
+
<a class="gw-skip" href="#main">Skip to content</a>
|
|
18
|
+
<div class="gw-announce" role="region" aria-label="Announcement">…<a href="…">…</a></div> <!-- optional -->
|
|
19
|
+
<header class="gw-header" data-gw-header> … </header>
|
|
20
|
+
<main id="main"> sections </main>
|
|
21
|
+
<footer class="gw-footer"> … </footer>
|
|
22
|
+
<script src="…/website.js" defer></script>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Header
|
|
26
|
+
|
|
27
|
+
```html
|
|
28
|
+
<header class="gw-header" data-gw-header>
|
|
29
|
+
<div class="gw-wrap gw-header__bar">
|
|
30
|
+
<a class="gw-brand" href="/"><img class="gw-brand__mark" src="…" alt="" width="26" height="26"><span class="gw-brand__name">GemBoss</span></a>
|
|
31
|
+
<nav class="gw-nav" aria-label="Main">
|
|
32
|
+
<ul class="gw-nav__list">
|
|
33
|
+
<li class="gw-nav__item">
|
|
34
|
+
<button class="gw-nav__trigger" type="button" aria-expanded="false" aria-controls="gw-mega-product" data-gw-mega="gw-mega-product">Product</button>
|
|
35
|
+
<div class="gw-mega" id="gw-mega-product" hidden>
|
|
36
|
+
<div class="gw-wrap gw-mega__grid">
|
|
37
|
+
<div class="gw-mega__col"><p class="gw-mega__heading">Build</p>
|
|
38
|
+
<a class="gw-mega__link" href="…"><span class="gw-mega__icon" aria-hidden="true">svg</span><span><b>Title</b><i>One line</i></span></a>
|
|
39
|
+
</div>
|
|
40
|
+
<a class="gw-mega__feature" href="…">…</a> <!-- optional card on the right -->
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
</li>
|
|
44
|
+
<li class="gw-nav__item"><a class="gw-nav__link" href="/pricing" aria-current?="page">Pricing</a></li>
|
|
45
|
+
</ul>
|
|
46
|
+
</nav>
|
|
47
|
+
<div class="gw-header__actions">
|
|
48
|
+
<button class="gw-theme-toggle" type="button" data-gw-theme-toggle aria-label="Switch to dark theme">svg</button>
|
|
49
|
+
<a class="gw-nav__link gw-header__signin" href="…">Sign in</a>
|
|
50
|
+
<a class="gw-btn gw-btn--secondary gw-btn--sm" href="…">Book a demo</a>
|
|
51
|
+
<a class="gw-btn gw-btn--sm" href="…">Start free</a>
|
|
52
|
+
<button class="gw-menu-toggle" type="button" aria-expanded="false" aria-controls="gw-mobile-menu" data-gw-menu-toggle aria-label="Open menu">svg</button>
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
<div class="gw-mobile-menu" id="gw-mobile-menu" hidden> …the same links as lists, and the actions… </div>
|
|
56
|
+
</header>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Script behaviour:
|
|
60
|
+
- **Mega menu**: click on a trigger toggles its panel (`hidden` removed, `aria-expanded="true"`, `.is-open` on the
|
|
61
|
+
`.gw-nav__item`). Hover opens on fine pointers after 80ms and closes 160ms after leaving item and panel. Only one
|
|
62
|
+
open at a time. `Escape` closes and returns focus to the trigger. A click outside closes. Arrow keys are not required.
|
|
63
|
+
- **Mobile menu** (below 1080px the `.gw-nav` and sign-in hide, `.gw-menu-toggle` shows): the toggle flips `hidden`
|
|
64
|
+
on `#gw-mobile-menu`, `aria-expanded`, `.is-menu-open` on `<html>` (the CSS locks scroll), and its `aria-label`
|
|
65
|
+
(Open menu / Close menu). `Escape` closes. Resizing above 1080px closes it.
|
|
66
|
+
- **Labels in other languages**: the script never writes English over a translated page. Give the toggles their
|
|
67
|
+
words with `data-gw-label-open` / `data-gw-label-close` (menu toggle) and `data-gw-label-dark` /
|
|
68
|
+
`data-gw-label-light` (theme toggle); without them it keeps the markup's own `aria-label`, then falls back to English.
|
|
69
|
+
- **Theme toggle**: cycles light ↔ dark by setting `data-theme` on `<html>`, stores the choice in `localStorage`
|
|
70
|
+
(`gw-theme`, every access in try/catch), updates `aria-label`. On load, a stored choice is applied before paint by a
|
|
71
|
+
one-line inline script in `<head>` that the template carries (`templates/page.html`).
|
|
72
|
+
- **Reveal**: elements with `.gw-reveal` get `.is-in` when 15% visible (IntersectionObserver, once). Failsafe: after
|
|
73
|
+
2.5s, or if IntersectionObserver is missing, all get `.is-in`. Under `prefers-reduced-motion` the CSS shows them
|
|
74
|
+
without motion.
|
|
75
|
+
- **Header**: `.is-scrolled` on `[data-gw-header]` once the page scrolled more than 8px (the CSS may use it for the
|
|
76
|
+
hairline only; the bar does not change height or colour).
|
|
77
|
+
- **Current page**: the script marks `aria-current="page"` on `.gw-nav__link` / `.gw-mega__link` whose `href`
|
|
78
|
+
pathname equals `location.pathname` (when the markup did not already).
|
|
79
|
+
|
|
80
|
+
## Components (CSS only)
|
|
81
|
+
|
|
82
|
+
| class | what |
|
|
83
|
+
|---|---|
|
|
84
|
+
| `.gw-btn` (+ `--secondary`, `--ghost`, `--on-night`, `--sm`, `--lg`, `--block`) | actions; rectangle 8px, ink fill by default |
|
|
85
|
+
| `.gw-link` (+ `--arrow`) | inline text link in the accent; `--arrow` adds → that moves 2px on hover |
|
|
86
|
+
| `.gw-label` | the label above a heading: 13px muted, 8px accent square before it |
|
|
87
|
+
| `.gw-dim` | the muted first sentence inside a headline |
|
|
88
|
+
| `.gw-chip` (+ `.is-active`) | selectable token, pill |
|
|
89
|
+
| `.gw-badge` (+ `--accent`, `--success`, `--warning`) | small status, pill |
|
|
90
|
+
| `.gw-card` (+ `--soft`, `--link`) | white box, 1px hairline, radius 12; `--link` makes the whole card an `<a>` |
|
|
91
|
+
| `.gw-window` (+ `__bar`, `__body`) | a framed screenshot/mock-up, like a browser or app window |
|
|
92
|
+
| `.gw-icon` | 20px inline stroke SVG wrapper |
|
|
93
|
+
| `.gw-list--check` | list with check marks |
|
|
94
|
+
| `.gw-table` (+ `--compare`) | data / comparison table; scrolls inside its box on phones |
|
|
95
|
+
| `.gw-faq` (`<details class="gw-faq__item"><summary>`) | FAQ accordion with no script |
|
|
96
|
+
| `.gw-tabs` (`role="tablist"`) | NOT in 0.1.0 (a reported gap would add it) |
|
|
97
|
+
|
|
98
|
+
## Sections
|
|
99
|
+
|
|
100
|
+
| class | what |
|
|
101
|
+
|---|---|
|
|
102
|
+
| `.gw-section` (+ `--soft`, `--tight`) | vertical rhythm; `--soft` on `--gw-bg-soft` |
|
|
103
|
+
| `.gw-band--night` | a dark band (max three per page plus the closing CTA, never adjacent) |
|
|
104
|
+
| `.gw-section__head` (+ `--center`) | label + h2 + one or two lines, max 660px |
|
|
105
|
+
| `.gw-hero` (+ `__wash`, `--center`, `--compact`) | first screen; `__wash` is the soft colour wash behind it |
|
|
106
|
+
| `.gw-logos` | proof strip of customer or partner logos (real ones only) |
|
|
107
|
+
| `.gw-stats` (`__item`, `__value`, `__label`) | 3–4 facts in a row, each with its source |
|
|
108
|
+
| `.gw-features` (`.gw-grid--3` of `.gw-feature`) | icon, title, one or two lines |
|
|
109
|
+
| `.gw-split` (+ `--reverse`) | text beside a figure; stacks on phones |
|
|
110
|
+
| `.gw-showcase` | night band with a large screen and two or three points |
|
|
111
|
+
| `.gw-steps` (`<ol>`) | numbered steps, how it works |
|
|
112
|
+
| `.gw-quote` | one real testimonial with name, role, company |
|
|
113
|
+
| `.gw-pricing` (`.gw-plan`, `--featured`) | plan cards; the featured one has a hairline in the accent, not a fill |
|
|
114
|
+
| `.gw-cta` | closing call to action band |
|
|
115
|
+
| `.gw-footer` (`__grid`, `__col`, `__heading`, `__bottom`) | footer columns + bottom row |
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Why the kit looks the way it does
|
|
2
|
+
|
|
3
|
+
`AGENTS.md` says what to do. This page says why, so that when a case is not covered you can decide in the same
|
|
4
|
+
spirit. Each rule came from measuring real pages, not from taste alone.
|
|
5
|
+
|
|
6
|
+
## One language for the site and the product
|
|
7
|
+
|
|
8
|
+
A visitor crosses from the website into the product in one click. If the two disagree (a cream site and a white app,
|
|
9
|
+
a purple button outside and a black one inside), the seam is exactly where trust is decided. So the website uses the
|
|
10
|
+
product's language: white canvas, ink actions, one accent, hairlines, almost no shadow.
|
|
11
|
+
|
|
12
|
+
## The thing you click is ink
|
|
13
|
+
|
|
14
|
+
A page has one thing it wants you to do. Near-black is the strongest mark on white and stays readable in every
|
|
15
|
+
light; the accent colour is louder but weaker as an instruction, and a page full of accent-coloured buttons has no
|
|
16
|
+
hierarchy left. The accent marks where you are and what is interactive in text: links, focus, the active item, the
|
|
17
|
+
small square before a label.
|
|
18
|
+
|
|
19
|
+
## Shapes carry meaning
|
|
20
|
+
|
|
21
|
+
Rectangles act, pills choose. When every button is a rectangle and every chip is a pill, people stop reading the
|
|
22
|
+
shape and read the words. A radius scale with seven steps means two cards side by side never differ by 2px, which is
|
|
23
|
+
the kind of drift that makes a page feel assembled rather than designed.
|
|
24
|
+
|
|
25
|
+
## Separation by line and space, light only at rest
|
|
26
|
+
|
|
27
|
+
A shadow says "this floats above". Cards on a page do not float; they sit on it. A 1px hairline and the dashboard's
|
|
28
|
+
resting shadow (two faint pixels) separate a card and keep the page calm; nothing lifts on hover. Larger light is
|
|
29
|
+
spent where it means something: a popover such as the mega menu, an illustration that lights itself.
|
|
30
|
+
|
|
31
|
+
## Scales instead of eyeballing
|
|
32
|
+
|
|
33
|
+
On gemboss.ai, before the scales, the four most common paddings were 9, 5, 12 and 15 pixels: spacing tuned by eye,
|
|
34
|
+
one element at a time. 1,291 of 2,076 spacing values belonged to no scale. Nobody sees one 15px; everybody feels a
|
|
35
|
+
page made of hundreds of them. The scales (4px base, the type steps) make "a bit more space" a choice between two
|
|
36
|
+
real values.
|
|
37
|
+
|
|
38
|
+
## Sentence case and a quiet label
|
|
39
|
+
|
|
40
|
+
Uppercase tracked labels ("FEATURES") shout and say nothing. A label in sentence case, muted, led by a small accent
|
|
41
|
+
square, tells the reader where they are and lets the headline do the talking. The house headline shape, a muted
|
|
42
|
+
first sentence and an ink second one, gives every section the same rhythm: context, then the point.
|
|
43
|
+
|
|
44
|
+
## One idea per section
|
|
45
|
+
|
|
46
|
+
Visitors scan. A section that makes one point, with one action, survives scanning; a section with three ideas loses
|
|
47
|
+
all three. Fewer, clearer sections beat a long page of everything.
|
|
48
|
+
|
|
49
|
+
## Real words, or a visible gap
|
|
50
|
+
|
|
51
|
+
A made-up number or a fake testimonial is found out, and then every other claim on the page is doubted. A visible
|
|
52
|
+
`[PRICE]` is honest and gets filled; an invented one ships.
|
|
53
|
+
|
|
54
|
+
## Motion that does not cost
|
|
55
|
+
|
|
56
|
+
Only `transform` and `opacity` move, because they do not re-layout the page and stay at 60 fps on a cheap phone.
|
|
57
|
+
Everything stops for people who ask the system for reduced motion. Motion explains (a panel opens from its
|
|
58
|
+
trigger, a section arrives as you reach it); it never decorates.
|
|
59
|
+
|
|
60
|
+
## Phones first in the checking, not just in the CSS
|
|
61
|
+
|
|
62
|
+
Most visitors from ads arrive on a phone. A label that fits at 1366px and overflows at 320px is a broken page for
|
|
63
|
+
most of them. That is why the kit is checked at 320, 390, 768 and 1366px, and why translated labels must not grow.
|
|
64
|
+
|
|
65
|
+
## When the kit is not enough
|
|
66
|
+
|
|
67
|
+
A kit that people work around stops being a kit. The workaround is allowed, in the site, with the tokens, under a
|
|
68
|
+
`kitgap-` name, and it is reported. The next version of the kit gets the real thing, every site gets it, and the
|
|
69
|
+
workaround is deleted. That loop, not the first release, is what keeps all GemCommerce websites one family.
|