climaybe 3.4.7 → 3.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/README.md +82 -31
- package/bin/version.txt +1 -1
- package/package.json +3 -3
- package/src/commands/add-cursor-skill.js +11 -12
- package/src/commands/add-store.js +15 -0
- package/src/commands/app-init.js +8 -12
- package/src/commands/create-entrypoints.js +13 -3
- package/src/commands/ensure-branches.js +11 -0
- package/src/commands/init.js +114 -17
- package/src/commands/update-workflows.js +3 -2
- package/src/cursor/rules/00-rule-index.mdc +2 -1
- package/src/cursor/rules/cursor-rule-template.mdc +8 -7
- package/src/cursor/rules/figma-design-system.mdc +8 -8
- package/src/cursor/rules/global-rules-reference.mdc +2 -1
- package/src/cursor/rules/performance-guide.mdc +436 -0
- package/src/cursor/rules/snippets.mdc +1 -1
- package/src/cursor/skills/accessibility-pass/SKILL.md +2 -2
- package/src/cursor/skills/changelog-release/SKILL.md +2 -2
- package/src/cursor/skills/commit-in-groups/SKILL.md +2 -2
- package/src/cursor/skills/linear-create-task/SKILL.md +1 -1
- package/src/cursor/skills/liquid-doc-comments/SKILL.md +2 -2
- package/src/cursor/skills/locale-translation-prep/SKILL.md +2 -2
- package/src/cursor/skills/schema-section-change/SKILL.md +3 -3
- package/src/cursor/skills/section-from-spec/SKILL.md +6 -6
- package/src/cursor/skills/theme-check-fix/SKILL.md +4 -4
- package/src/index.js +3 -3
- package/src/lib/branch-protection.js +205 -0
- package/src/lib/config.js +11 -1
- package/src/lib/cursor-bundle.js +150 -12
- package/src/lib/git.js +12 -0
- package/src/lib/prompts.js +98 -4
- package/src/lib/theme-dev-kit.js +4 -0
- package/src/workflows/build/build-pipeline.yml +14 -0
- package/src/workflows/multi/pr-to-live.yml +1 -1
- package/src/workflows/preview/reusable-comment-on-pr.yml +6 -3
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Store performance architecture for our themes — CSS/JS tiering, third-party containment, images, Section API, and maintenance checklist
|
|
3
|
+
globs:
|
|
4
|
+
- "_scripts/**"
|
|
5
|
+
- "_styles/**"
|
|
6
|
+
- "snippets/_head*.liquid"
|
|
7
|
+
- "snippets/_body*.liquid"
|
|
8
|
+
- "layout/theme.liquid"
|
|
9
|
+
- "snippets/a--image*.liquid"
|
|
10
|
+
alwaysApply: false
|
|
11
|
+
---
|
|
12
|
+
# Store Performance Guide
|
|
13
|
+
|
|
14
|
+
Reference for how this theme optimizes storefront performance. Read this before adding scripts, third-party tags, CSS, or heavy Liquid to `<head>`.
|
|
15
|
+
|
|
16
|
+
## Goals & budgets
|
|
17
|
+
|
|
18
|
+
| Metric | Target | Primary levers |
|
|
19
|
+
|--------|--------|----------------|
|
|
20
|
+
| LCP | < 2.5s | Critical CSS, LCP preloads, font discipline, hero image sizing |
|
|
21
|
+
| INP / TBT | Low main-thread blocking | Deferred JS, idle third-parties, smaller `index.js` |
|
|
22
|
+
| CLS | Stable layout | Explicit image dimensions, `font-display: swap`, reserved space |
|
|
23
|
+
| Third-party cost | Contained | Resource blocker, `content_for_header` sanitization, deferred analytics |
|
|
24
|
+
|
|
25
|
+
**Source of truth for JS:** `_scripts/` → built to `assets/` via `npm run scripts:build`. Never edit `assets/*.js` directly.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Page load timeline
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
┌─ HEAD (critical path) ─────────────────────────────────────────────────────┐
|
|
33
|
+
│ 1. _head-resource-blocker Network + DOM patches (first script) │
|
|
34
|
+
│ 2. _head-urgent-script Geoblock / track-my-order redirect │
|
|
35
|
+
│ 3. _meta-tags, _head-seo Meta, favicons (low fetchpriority) │
|
|
36
|
+
│ 4. _product-preload-slider PDP: up to 5 slider images (portrait) │
|
|
37
|
+
│ 5. _index-preload-hero Homepage: mobile LCP hero preload │
|
|
38
|
+
│ 6. _head-style Fonts, :root tokens, critical.css, style.css │
|
|
39
|
+
│ 7. _script-variables window.theme, routes, icons SVG, Klaviyo cfg │
|
|
40
|
+
│ 8. debug-proxy (conditional) API proxy for preview/dev only │
|
|
41
|
+
│ 9. index.js [+ page bundles] Route-specific modules in head │
|
|
42
|
+
│10. speculationrules Conservative prerender for internal links │
|
|
43
|
+
│11. _head-console-filter Suppresses noisy third-party console (LH) │
|
|
44
|
+
│12. content_for_header Shopify apps — sanitized after capture │
|
|
45
|
+
│13. Post-header cleanup Removes blocked script/link nodes │
|
|
46
|
+
└────────────────────────────────────────────────────────────────────────────┘
|
|
47
|
+
┌─ BODY ─────────────────────────────────────────────────────────────────────┐
|
|
48
|
+
│ Main content (sections/snippets) │
|
|
49
|
+
│ _body-script → deferred.js (module, end of body) │
|
|
50
|
+
│ → scheduleIdle → deferred-integrations.js (conditional) │
|
|
51
|
+
│ → klaviyo-cart-tracking.js, hotjar-deferred.js │
|
|
52
|
+
└────────────────────────────────────────────────────────────────────────────┘
|
|
53
|
+
┌─ IDLE / INTERACTION ───────────────────────────────────────────────────────┐
|
|
54
|
+
│ Hotjar (8s idle or first scroll/click/touch/keydown) │
|
|
55
|
+
│ Rebuy product view analytics (PDP, 2s idle) │
|
|
56
|
+
│ Variant image prefetch (hover; touch: max 3 after 5s idle) │
|
|
57
|
+
│ cart.js injected when cart drawer opens │
|
|
58
|
+
│ electric-section lazy fetch (IntersectionObserver, often 1200px margin) │
|
|
59
|
+
└────────────────────────────────────────────────────────────────────────────┘
|
|
60
|
+
┌─ window.load ──────────────────────────────────────────────────────────────┐
|
|
61
|
+
│ AddShoppers referral widget (async) │
|
|
62
|
+
└────────────────────────────────────────────────────────────────────────────┘
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 1. CSS tiering
|
|
68
|
+
|
|
69
|
+
### Critical bundle (render-blocking)
|
|
70
|
+
|
|
71
|
+
- **Source:** `_styles/critical.css` → `assets/critical.css`
|
|
72
|
+
- **Scope:** Header + homepage hero shell only; narrow `@source` list (~12 Liquid files)
|
|
73
|
+
- **Loaded in:** `snippets/_head-style.liquid` via `stylesheet_tag`
|
|
74
|
+
|
|
75
|
+
When adding above-the-fold UI to header or index hero, ensure Tailwind classes are covered by critical `@source` paths or accept FOUC until full CSS loads.
|
|
76
|
+
|
|
77
|
+
### Full stylesheet (non-blocking)
|
|
78
|
+
|
|
79
|
+
- **Source:** `_styles/main.css` → `assets/style.css`
|
|
80
|
+
- **Pattern:** `media="print" onload="this.media='all'"` + `<noscript>` fallback
|
|
81
|
+
- **Also:** `rel="preload" as="style" fetchpriority="high"` for early discovery
|
|
82
|
+
|
|
83
|
+
Build: `npm run tailwind:build` or `tailwind:watch` (builds both critical + main).
|
|
84
|
+
|
|
85
|
+
### Theme tokens
|
|
86
|
+
|
|
87
|
+
- `_styles/theme-tokens.css` — shared `@theme` imported by both CSS entry points
|
|
88
|
+
- Inline `:root` variables in `_head-style.liquid` for fonts, spacing, buttons
|
|
89
|
+
|
|
90
|
+
### Disabled / deferred CSS ideas
|
|
91
|
+
|
|
92
|
+
- `content-visibility: auto` on sections — **commented out** in `_styles/main.css` (evaluate before enabling)
|
|
93
|
+
- Lazysizes CSS — removed; native `loading="lazy"` only
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## 2. Font strategy
|
|
98
|
+
|
|
99
|
+
### Self-hosted fonts (no Typekit / Google Fonts on storefront)
|
|
100
|
+
|
|
101
|
+
| Family | File | Preload? | Usage |
|
|
102
|
+
|--------|------|----------|-------|
|
|
103
|
+
| Grosa Medium | `grosa-medium.woff2` | **Yes** | Above-the-fold body emphasis |
|
|
104
|
+
| Ivy Presto Headline Light | `ivypresto-headline-light.woff2` | **Yes** | Headings (`iheadline`) |
|
|
105
|
+
| Grosa Regular | `grosa-regular.woff2` | No | Body text; loads via `@font-face` |
|
|
106
|
+
|
|
107
|
+
All use `font-display: swap`.
|
|
108
|
+
|
|
109
|
+
### Font blocking
|
|
110
|
+
|
|
111
|
+
`_head-resource-blocker.liquid` + `layout/theme.liquid` sanitization block:
|
|
112
|
+
|
|
113
|
+
- Adobe Typekit (`use.typekit.net`, `p.typekit.net`)
|
|
114
|
+
- Google Fonts
|
|
115
|
+
- Shopify Font CDN webfonts (`fonts.shopifycdn.com`, Nunito)
|
|
116
|
+
- Klaviyo legacy brand fonts (`kl-custom-fonts`, Shopify Files `.woff`)
|
|
117
|
+
- Rebuy onsite CDN (`cdn.rebuyengine.com`, `/onsite/`) — **API** (`rebuyengine.com/api/*`) still allowed
|
|
118
|
+
|
|
119
|
+
### Preconnect budget
|
|
120
|
+
|
|
121
|
+
- `_head-typography.liquid`: `cdn.shopify.com`, `cdn.shopifycloud.com`; dns-prefetch `v.shopify.com`
|
|
122
|
+
- Unused preconnects removed: `fonts.shopifycdn.com`, `shop.app`
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## 3. JavaScript architecture
|
|
127
|
+
|
|
128
|
+
### Build system
|
|
129
|
+
|
|
130
|
+
**File:** `.climaybe/build-scripts.js` (via `npm run scripts:build`)
|
|
131
|
+
|
|
132
|
+
| Entry (`_scripts/`) | Output (`assets/`) | Loaded |
|
|
133
|
+
|---------------------|-------------------|--------|
|
|
134
|
+
| `main.js` | `index.js` | All pages, `<head>` module |
|
|
135
|
+
| `deferred.js` | `deferred.js` | End of `<body>` |
|
|
136
|
+
| `deferred-integrations.js` | `deferred-integrations.js` | Idle inject when DOM matches |
|
|
137
|
+
| `productpage.js` | `productpage.js` | PDP `<head>` |
|
|
138
|
+
| `product--variant-radios.js` | `product--variant-radios.js` | PDP `<head>` |
|
|
139
|
+
| `debug-proxy.js` | `debug-proxy.js` | Conditional `<head>` |
|
|
140
|
+
|
|
141
|
+
**Also in head (not in bundler — manual sync risk):**
|
|
142
|
+
|
|
143
|
+
- `collectionpage.js` ← `_scripts/collectionpage.js`
|
|
144
|
+
- `cart.js` ← `_scripts/cart.js`
|
|
145
|
+
|
|
146
|
+
**Per-section assets** (loaded with `defer` / `type="module"` from sections): `wishlist-feed.js`, `irl.js`, `reviews-custom.js`, `product--form.js`, `product-model.js`, `loading-banner.js`, etc.
|
|
147
|
+
|
|
148
|
+
Production build strips JSDoc and `console.*` from bundled output.
|
|
149
|
+
|
|
150
|
+
### `index.js` (critical bundle)
|
|
151
|
+
|
|
152
|
+
**Entry:** `_scripts/main.js`
|
|
153
|
+
|
|
154
|
+
Includes: `core-components.js`, `header.js`, `electric-section.js`, `electric-slider.js`, `electric-search.js`, `cart-dynamic.js`, `electric-cart-upsell-tabs.js`, pagination, checkout spinner delegation.
|
|
155
|
+
|
|
156
|
+
**Keep lean.** New features belong in `deferred.js`, page bundles, or lazy-loaded section scripts unless needed for first paint.
|
|
157
|
+
|
|
158
|
+
### `deferred.js` (body bundle)
|
|
159
|
+
|
|
160
|
+
**Entry:** `_scripts/deferred.js`
|
|
161
|
+
|
|
162
|
+
Always loads: product card scripts, quick ATC modal, Klaviyo cart tracking, Hotjar deferred, chat button visibility.
|
|
163
|
+
|
|
164
|
+
**Conditionally loads** `deferred-integrations.js` when DOM contains:
|
|
165
|
+
`electric-wish`, `electric-wish-counter`, `promo-banner`, `electric-rebuy-simplify`, `footer-newsletter`, `[data-gorgias-widget]`, `.js-promo-banner-text`
|
|
166
|
+
|
|
167
|
+
Uses `scheduleIdle(..., { timeout: 3000 })` from `_scripts/utils/perf.js`.
|
|
168
|
+
|
|
169
|
+
### `productpage.js` (PDP bundle)
|
|
170
|
+
|
|
171
|
+
Includes: gallery, video player, variant preview, variant prefetch, Rebuy product view, gift card sync.
|
|
172
|
+
|
|
173
|
+
### Idle scheduling utility
|
|
174
|
+
|
|
175
|
+
**Canonical:** `_scripts/utils/perf.js` → `scheduleIdle(callback, { timeout })`
|
|
176
|
+
|
|
177
|
+
Falls back to `setTimeout(1)` when `requestIdleCallback` unavailable.
|
|
178
|
+
|
|
179
|
+
**Consumers:** `deferred.js`, `hotjar-deferred.js`, `rebuy-product-view.js`, `product-variant-prefetch.js`, `recently-viewed.js`
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## 4. Third-party containment
|
|
184
|
+
|
|
185
|
+
### Layer 1: Resource blocker (runtime)
|
|
186
|
+
|
|
187
|
+
`snippets/_head-resource-blocker.liquid` — **must stay first in `<head>`**
|
|
188
|
+
|
|
189
|
+
Patches: `fetch`, `XHR`, `createElement`, `setAttribute`, DOM insertion, inline style mutation, `MutationObserver` for late injections.
|
|
190
|
+
|
|
191
|
+
### Layer 2: Header sanitization (Liquid)
|
|
192
|
+
|
|
193
|
+
`layout/theme.liquid` captures `content_for_header`, replaces blocked host strings with `blocked.invalid/*`, then runs a cleanup script.
|
|
194
|
+
|
|
195
|
+
### Layer 3: Deferred / conditional loading
|
|
196
|
+
|
|
197
|
+
| Service | File | Strategy |
|
|
198
|
+
|---------|------|----------|
|
|
199
|
+
| Hotjar | `_scripts/hotjar-deferred.js` | Idle 8s or first user interaction |
|
|
200
|
+
| Klaviyo cart events | `_scripts/klaviyo-cart-tracking.js` | `deferred.js`; listens `cart:added` |
|
|
201
|
+
| Rebuy analytics (PDP view) | `_scripts/rebuy-product-view.js` | Idle 2s on product pages |
|
|
202
|
+
| Rebuy recommendations | `_scripts/electric-rebuy-simplify.js` | Integrations bundle; IO `rootMargin: 1200px` |
|
|
203
|
+
| AddShoppers | `_head-script.liquid` | `window.load`, async, `loadCss: false` |
|
|
204
|
+
| Affirm | `affirm-messaging` web component | Lazy on first product form |
|
|
205
|
+
| Kimonix | `_body-script.liquid` | Async only if `kimonix_void_script` in header |
|
|
206
|
+
| Gorgias | App embed + `gorgias-widget.js` | App via Shopify; triggers deferred |
|
|
207
|
+
|
|
208
|
+
### Layer 4: Console filter (Lighthouse only)
|
|
209
|
+
|
|
210
|
+
`_head-console-filter.liquid` — suppresses known third-party `console.error/warn` patterns. **Do not rely on this for debugging** — disable mentally when investigating app bugs.
|
|
211
|
+
|
|
212
|
+
### Shopify app embeds (`config/settings_data.json`)
|
|
213
|
+
|
|
214
|
+
| App | Status | Notes |
|
|
215
|
+
|-----|--------|-------|
|
|
216
|
+
| Elevar (GTM/dataLayer) | Enabled | Primary tag orchestration — audit in GTM, not theme |
|
|
217
|
+
| Klaviyo onsite embed | Enabled | Fonts may be blocked; onsite JS from Shopify |
|
|
218
|
+
| Gorgias | Enabled | Chat |
|
|
219
|
+
| Photolock | Enabled | Image protection |
|
|
220
|
+
| Okendo, Checkout Blocks | Disabled | — |
|
|
221
|
+
|
|
222
|
+
### Inactive / dead integrations
|
|
223
|
+
|
|
224
|
+
| File | Status |
|
|
225
|
+
|------|--------|
|
|
226
|
+
| `snippets/_script-blocker.liquid` | Fully commented out |
|
|
227
|
+
| `snippets/_head-rebuy-stylesheet-blocker.liquid` | Not rendered |
|
|
228
|
+
| `snippets/_head-csp.liquid` | Not rendered |
|
|
229
|
+
| `snippets/_criteo-tracking.liquid` | Not rendered |
|
|
230
|
+
| `snippets/shoplift.liquid` | Commented out in `theme.liquid` |
|
|
231
|
+
| instant.page | Removed; `data-instant-allow-query-string` on body is legacy |
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## 5. Images & LCP
|
|
236
|
+
|
|
237
|
+
### Snippets
|
|
238
|
+
|
|
239
|
+
| Snippet | Behavior |
|
|
240
|
+
|---------|----------|
|
|
241
|
+
| `a--image.liquid` | Responsive `srcset`; LCP: `fetchpriority="high"`, `loading="eager"`, `decoding="async"`; else `loading="lazy"`; auto-lazy after 2nd section/item |
|
|
242
|
+
| `a--image-responsive.liquid` | `<picture>` breakpoints; LCP path avoids desktop 2x retina |
|
|
243
|
+
|
|
244
|
+
### Preloads
|
|
245
|
+
|
|
246
|
+
| Snippet | When | What |
|
|
247
|
+
|---------|------|------|
|
|
248
|
+
| `_index-preload-hero.liquid` | `request.page_type == 'index'` | Mobile 420w hero from `settings.homepage_lcp_image` |
|
|
249
|
+
| `_product-preload-slider-images.liquid` | PDP | Up to 5 portrait slider images, `imagesrcset` 480/960 |
|
|
250
|
+
| `_head-seo.liquid` | All | Favicons `fetchpriority="low"` |
|
|
251
|
+
|
|
252
|
+
### No lazysizes
|
|
253
|
+
|
|
254
|
+
Theme uses **native `loading="lazy"`** only. `unveilLazyloadIn()` in `core-components.js` is a no-op kept for API compatibility.
|
|
255
|
+
|
|
256
|
+
### Variant image prefetch (PDP)
|
|
257
|
+
|
|
258
|
+
`_scripts/product-variant-prefetch.js`:
|
|
259
|
+
|
|
260
|
+
- **Desktop:** hover/focus → fetch `?section_id=api--product-images&variant={id}` → preload image URLs from JSON payload
|
|
261
|
+
- **Touch:** after 5s idle, max **3** variants, images section only (no `product--main` fetch)
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
## 6. Navigation & prefetch
|
|
266
|
+
|
|
267
|
+
### Speculation Rules (native prerender)
|
|
268
|
+
|
|
269
|
+
`snippets/_head-script.liquid` — `eagerness: "conservative"`
|
|
270
|
+
|
|
271
|
+
Prerenders same-origin links except account, cart, login. Do not add instant.page alongside this.
|
|
272
|
+
|
|
273
|
+
### electric-section (Section Rendering API)
|
|
274
|
+
|
|
275
|
+
`_scripts/electric-section.js`:
|
|
276
|
+
|
|
277
|
+
- Lazy load via `IntersectionObserver` (`data-onload`, configurable `data-onload-root-margin`)
|
|
278
|
+
- Fragment cache (max 10 entries)
|
|
279
|
+
- Events: `electric-section:prefetch`, `electric-section:fetch`
|
|
280
|
+
- Used for collection tabs, IRL, more-to-love, header fragments, etc.
|
|
281
|
+
|
|
282
|
+
### electric-pub (tab prefetch)
|
|
283
|
+
|
|
284
|
+
`_scripts/electric-pub.js` — prefetches tab content on hover/focus or intersection.
|
|
285
|
+
|
|
286
|
+
### Cart script on demand
|
|
287
|
+
|
|
288
|
+
`core-components.js` → `loadCartScriptOnce()` injects `cart.js` with `defer` when cart drawer opens (not on every page upfront).
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## 7. Shopify-specific patterns
|
|
293
|
+
|
|
294
|
+
### Route-conditional head scripts
|
|
295
|
+
|
|
296
|
+
From `_head-script.liquid`:
|
|
297
|
+
|
|
298
|
+
```liquid
|
|
299
|
+
index.js → all pages
|
|
300
|
+
productpage.js → product
|
|
301
|
+
product--variant-radios.js → product
|
|
302
|
+
collectionpage.js → collection, search
|
|
303
|
+
cart.js → cart template
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### Geoblock
|
|
307
|
+
|
|
308
|
+
When `settings.geoblock_enabled`:
|
|
309
|
+
|
|
310
|
+
- `html.geoblock-pending` hides body until `/browsing_context_suggestions.json` returns
|
|
311
|
+
- Currently **disabled** in `settings_data.json`
|
|
312
|
+
- **Caveat:** fetch failure only warns — body can stay hidden if enabled without a fallback
|
|
313
|
+
|
|
314
|
+
### Fabric cart restoration
|
|
315
|
+
|
|
316
|
+
Inline in `_head-script.liquid` — cart/product template logic for `_fabric` localStorage flow.
|
|
317
|
+
|
|
318
|
+
### Debug API proxy
|
|
319
|
+
|
|
320
|
+
`_scripts/debug-proxy.js` — loads only when debug cookie, `?debug_proxy*`, or Shopify design mode. Rewrites proxy API fetch URLs.
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## 8. Klaviyo & analytics data flow
|
|
325
|
+
|
|
326
|
+
### Cart tracking (deferred)
|
|
327
|
+
|
|
328
|
+
1. `product--form.js` dispatches `cart:added` with cart payload
|
|
329
|
+
2. `klaviyo-cart-tracking.js` waits for `_learnq`, pushes `Added to Cart v3` + legacy `Added to Cart`
|
|
330
|
+
3. Product page context from `window.theme.klaviyoCart` in `_script-variables.liquid`
|
|
331
|
+
4. Cart page replays `cart:added` from `sessionStorage cart:justAdded`
|
|
332
|
+
|
|
333
|
+
### Viewed Product (not deferred)
|
|
334
|
+
|
|
335
|
+
`sections/product--icons-model.liquid` — large inline Klaviyo script when comparison section renders. **Candidate for future deferral.**
|
|
336
|
+
|
|
337
|
+
### Rebuy
|
|
338
|
+
|
|
339
|
+
- Widget CDN blocked; custom `electric-rebuy-simplify` uses API
|
|
340
|
+
- Product view POST deferred via `rebuy-product-view.js`
|
|
341
|
+
- Global helpers in `_script-variables.liquid` (`rebuyTrackEvent`, session storage for added variants)
|
|
342
|
+
|
|
343
|
+
---
|
|
344
|
+
|
|
345
|
+
## 9. Adding new features — checklist
|
|
346
|
+
|
|
347
|
+
### New JavaScript
|
|
348
|
+
|
|
349
|
+
- [ ] Default to `_scripts/` source file, not `assets/`
|
|
350
|
+
- [ ] If needed on every page → consider `deferred.js` not `main.js`
|
|
351
|
+
- [ ] If third-party → defer (idle/interaction/load), never sync in head unless unavoidable
|
|
352
|
+
- [ ] If PDP-only → `productpage.js` or section `{% javascript %}`
|
|
353
|
+
- [ ] Add to `.climaybe/build-scripts.js` if new bundle entry
|
|
354
|
+
- [ ] Run `npm run scripts:build`
|
|
355
|
+
- [ ] Use `scheduleIdle` from `utils/perf.js` for non-critical init
|
|
356
|
+
- [ ] AbortController + cleanup in web components
|
|
357
|
+
|
|
358
|
+
### New third-party script
|
|
359
|
+
|
|
360
|
+
- [ ] Can it go through GTM with consent + idle trigger instead of theme?
|
|
361
|
+
- [ ] If app embed: expect `content_for_header` injection — add to blocker list if it conflicts (fonts, duplicate widgets)
|
|
362
|
+
- [ ] Add domain to `_head-console-filter` only if noise is unavoidable
|
|
363
|
+
- [ ] Never add sync analytics in `_head-script.liquid`
|
|
364
|
+
|
|
365
|
+
### New above-the-fold UI
|
|
366
|
+
|
|
367
|
+
- [ ] Extend `critical.css` `@source` if new classes needed at first paint
|
|
368
|
+
- [ ] LCP image: use `fetchpriority="high"`, explicit dimensions, preload in dedicated snippet
|
|
369
|
+
- [ ] Do not preload more than 2 fonts
|
|
370
|
+
|
|
371
|
+
### New section below fold
|
|
372
|
+
|
|
373
|
+
- [ ] `loading="lazy"` on images
|
|
374
|
+
- [ ] Consider `<electric-section data-onload>` instead of bundling in `index.js`
|
|
375
|
+
- [ ] Pass `lazyload: true` to product cards
|
|
376
|
+
|
|
377
|
+
---
|
|
378
|
+
|
|
379
|
+
## 10. Testing & measurement
|
|
380
|
+
|
|
381
|
+
### Before shipping perf changes
|
|
382
|
+
|
|
383
|
+
1. **Chrome DevTools** — Performance trace: LCP element, long tasks, third-party cost
|
|
384
|
+
2. **Network** — throttle Slow 4G; verify critical.css → first paint, style.css non-blocking
|
|
385
|
+
3. **Coverage** — how much of `index.js` executes on homepage vs PDP
|
|
386
|
+
4. **Block third-parties test** — block `googletagmanager.com`, `static.klaviyo.com`, `static.hotjar.com`; if TBT collapses, marketing stack is the bottleneck
|
|
387
|
+
5. **Theme Check** — `npm run lint:liquid`
|
|
388
|
+
6. **Build** — `npm run scripts:build && npm run tailwind:build`
|
|
389
|
+
|
|
390
|
+
### Debug modes
|
|
391
|
+
|
|
392
|
+
| URL param | Effect |
|
|
393
|
+
|-----------|--------|
|
|
394
|
+
| `?debug_typekit=1` | Typekit audit (`_head-typekit-debug`) |
|
|
395
|
+
| `?debug_rebuy=1` | Rebuy logging |
|
|
396
|
+
| `?debug_proxy=1` | API proxy prompt |
|
|
397
|
+
| `?debug_proxy_domain=` | Set proxy origin |
|
|
398
|
+
|
|
399
|
+
---
|
|
400
|
+
|
|
401
|
+
## 11. Known gaps & maintenance risks
|
|
402
|
+
|
|
403
|
+
1. **`collectionpage.js` / `cart.js` not in build targets** — `_scripts` edits may not reach `assets/` until manual copy or build update
|
|
404
|
+
2. **Many section scripts outside bundler** — verify `assets/` sync when editing `_scripts/wishlist-feed.js`, etc.
|
|
405
|
+
3. **Stale LiquidDoc** in `_head-script.liquid`, `_head-urgent-script.liquid` — docs mention Rebuy head prefetch, instant.page, promo anti-flash that moved or were removed
|
|
406
|
+
4. **`index.js` size (~340KB+)** — largest theme-controlled bottleneck; split `core-components.js` further if TBT regresses
|
|
407
|
+
5. **GTM / Elevar** — largest real-world cost; theme cannot fix container bloat
|
|
408
|
+
6. **`_head-console-filter`** — masks errors; misleading during app debugging
|
|
409
|
+
7. **Klaviyo Viewed Product inline** — still heavy on PDP with icons model section
|
|
410
|
+
|
|
411
|
+
---
|
|
412
|
+
|
|
413
|
+
## 12. File quick reference
|
|
414
|
+
|
|
415
|
+
| Concern | Primary files |
|
|
416
|
+
|---------|---------------|
|
|
417
|
+
| Load order | `layout/theme.liquid` |
|
|
418
|
+
| Resource blocking | `snippets/_head-resource-blocker.liquid` |
|
|
419
|
+
| CSS tiering | `snippets/_head-style.liquid`, `_styles/critical.css`, `_styles/main.css` |
|
|
420
|
+
| JS bootstrap | `snippets/_head-script.liquid`, `snippets/_body-script.liquid` |
|
|
421
|
+
| Globals | `snippets/_script-variables.liquid` |
|
|
422
|
+
| Build | `.climaybe/build-scripts.js`, `package.json` |
|
|
423
|
+
| Idle utils | `_scripts/utils/perf.js` |
|
|
424
|
+
| Images | `snippets/a--image.liquid`, `snippets/a--image-responsive.liquid` |
|
|
425
|
+
| LCP preloads | `snippets/_index-preload-hero.liquid`, `snippets/_product-preload-slider-images.liquid` |
|
|
426
|
+
| Section lazy load | `_scripts/electric-section.js` |
|
|
427
|
+
| Deferred 3P | `_scripts/hotjar-deferred.js`, `_scripts/klaviyo-cart-tracking.js`, `_scripts/rebuy-product-view.js` |
|
|
428
|
+
| App embeds | `config/settings_data.json` |
|
|
429
|
+
|
|
430
|
+
---
|
|
431
|
+
|
|
432
|
+
## 13. Related rules
|
|
433
|
+
|
|
434
|
+
- `javascript-standards.mdc` — web components, layout thrashing, `scheduleIdle` patterns
|
|
435
|
+
- `tailwindcss-rules.mdc` — static classes, `@source` for critical CSS
|
|
436
|
+
- `project-overview.mdc` — performance targets (< 16ms init, 60fps), build outputs vs source (`_scripts/` / `_styles/`, never `assets/` directly)
|
|
@@ -11,8 +11,8 @@ Runs a structured a11y audit on specified file(s) and reports findings with fix
|
|
|
11
11
|
|
|
12
12
|
Before auditing, read and apply:
|
|
13
13
|
|
|
14
|
-
1. `.
|
|
15
|
-
2. `.
|
|
14
|
+
1. `.config/ai/rules/00-rule-index.mdc` — rule index
|
|
15
|
+
2. `.config/ai/rules/accessibility-rules.mdc` — WCAG 2.1 AA, semantic HTML, ARIA, keyboard, focus, screen readers
|
|
16
16
|
|
|
17
17
|
## Workflow
|
|
18
18
|
|
|
@@ -11,8 +11,8 @@ Builds a changelog or release notes from commits since a ref (e.g. last tag), gr
|
|
|
11
11
|
|
|
12
12
|
When grouping and labeling commits, read and apply:
|
|
13
13
|
|
|
14
|
-
1. `.
|
|
15
|
-
2. `.
|
|
14
|
+
1. `.config/ai/rules/00-rule-index.mdc` — rule index
|
|
15
|
+
2. `.config/ai/rules/commit-rules.mdc` — commit types (fix, feat, refactor, style, etc.) and format
|
|
16
16
|
|
|
17
17
|
Use the same type labels for changelog sections so the output matches how the team writes commits.
|
|
18
18
|
|
|
@@ -13,8 +13,8 @@ Analyzes uncommitted changes, groups them into logical commits, and suggests one
|
|
|
13
13
|
|
|
14
14
|
Before suggesting any commit messages, read and apply:
|
|
15
15
|
|
|
16
|
-
1. `.
|
|
17
|
-
2. `.
|
|
16
|
+
1. `.config/ai/rules/00-rule-index.mdc` — rule index
|
|
17
|
+
2. `.config/ai/rules/commit-rules.mdc` — commit format (type + description), types (fix, feat, refactor, style, etc.), imperative mood, optional scope
|
|
18
18
|
|
|
19
19
|
Use the exact format and types from commit-rules; no period at end; lowercase description.
|
|
20
20
|
|
|
@@ -9,7 +9,7 @@ Creates a Linear issue in the **Voldt Redesign** project with a PRD-style descri
|
|
|
9
9
|
|
|
10
10
|
## Rules to Apply
|
|
11
11
|
|
|
12
|
-
Before creating a task, read `.
|
|
12
|
+
Before creating a task, read `.config/ai/rules/00-rule-index.mdc`. No other rule file is required; mention commit-rules only if the user wants a branch name convention.
|
|
13
13
|
|
|
14
14
|
## Linear Context
|
|
15
15
|
|
|
@@ -11,8 +11,8 @@ Adds or updates the `{%- doc -%}` block at the top of a snippet or block so it m
|
|
|
11
11
|
|
|
12
12
|
Before writing or editing doc blocks, read and apply:
|
|
13
13
|
|
|
14
|
-
1. `.
|
|
15
|
-
2. `.
|
|
14
|
+
1. `.config/ai/rules/00-rule-index.mdc` — rule index
|
|
15
|
+
2. `.config/ai/rules/liquid-doc-rules.mdc` — required structure, @param format, @example, types, placement
|
|
16
16
|
|
|
17
17
|
## Workflow
|
|
18
18
|
|
|
@@ -11,9 +11,9 @@ Compares the default locale with others and reports which keys are new or change
|
|
|
11
11
|
|
|
12
12
|
For context on how the project uses locales (e.g. in sections/snippets), the rule index is useful:
|
|
13
13
|
|
|
14
|
-
1. `.
|
|
14
|
+
1. `.config/ai/rules/00-rule-index.mdc` — rule index (schemas.mdc prefers translation keys over schema text; locales live in `locales/`)
|
|
15
15
|
|
|
16
|
-
No single "locale rules" file is required; this skill focuses on file comparison and reporting. To **generate** translations across locales after English changes, use the **theme-translator** subagent (`/theme-translator`), installed with the Cursor bundle under `.
|
|
16
|
+
No single "locale rules" file is required; this skill focuses on file comparison and reporting. To **generate** translations across locales after English changes, use the **theme-translator** subagent (`/theme-translator`), installed with the Cursor bundle under `.config/ai/agents/`.
|
|
17
17
|
|
|
18
18
|
## Workflow
|
|
19
19
|
|
|
@@ -11,9 +11,9 @@ Safely adds or changes a section setting: updates both the section Liquid and th
|
|
|
11
11
|
|
|
12
12
|
Before making changes, read and apply:
|
|
13
13
|
|
|
14
|
-
1. `.
|
|
15
|
-
2. `.
|
|
16
|
-
3. `.
|
|
14
|
+
1. `.config/ai/rules/00-rule-index.mdc` — rule index
|
|
15
|
+
2. `.config/ai/rules/schemas.mdc` — minimal settings, no redundancy, translation keys, max 5 settings, "question every setting"
|
|
16
|
+
3. `.config/ai/rules/sections.mdc` — section structure and schema requirement
|
|
17
17
|
|
|
18
18
|
## Workflow
|
|
19
19
|
|
|
@@ -11,12 +11,12 @@ Creates a new section (and optional snippet) from a user spec, following project
|
|
|
11
11
|
|
|
12
12
|
Before creating any section or snippet, read and apply (in order):
|
|
13
13
|
|
|
14
|
-
1. `.
|
|
15
|
-
2. `.
|
|
16
|
-
3. `.
|
|
17
|
-
4. `.
|
|
18
|
-
5. `.
|
|
19
|
-
6. `.
|
|
14
|
+
1. `.config/ai/rules/00-rule-index.mdc` — rule index
|
|
15
|
+
2. `.config/ai/rules/sections.mdc` — section structure, schema requirement, performance
|
|
16
|
+
3. `.config/ai/rules/snippets.mdc` — snippet patterns, LiquidDoc, parameter handling
|
|
17
|
+
4. `.config/ai/rules/schemas.mdc` — minimal settings, no redundancy, translation keys, max 5 settings
|
|
18
|
+
5. `.config/ai/rules/liquid.mdc` — Liquid syntax
|
|
19
|
+
6. `.config/ai/rules/liquid-doc-rules.mdc` — required `{% doc %}` block format for snippets
|
|
20
20
|
|
|
21
21
|
## Workflow
|
|
22
22
|
|
|
@@ -11,10 +11,10 @@ Runs theme linting (e.g. Shopify Theme Check) and maps each finding to project r
|
|
|
11
11
|
|
|
12
12
|
When interpreting results and suggesting fixes, read and apply:
|
|
13
13
|
|
|
14
|
-
1. `.
|
|
15
|
-
2. `.
|
|
16
|
-
3. `.
|
|
17
|
-
4. `.
|
|
14
|
+
1. `.config/ai/rules/00-rule-index.mdc` — rule index
|
|
15
|
+
2. `.config/ai/rules/liquid.mdc` — Liquid syntax and usage
|
|
16
|
+
3. `.config/ai/rules/sections.mdc` — section structure and schema
|
|
17
|
+
4. `.config/ai/rules/snippets.mdc` — snippet patterns
|
|
18
18
|
|
|
19
19
|
## Workflow
|
|
20
20
|
|
package/src/index.js
CHANGED
|
@@ -120,7 +120,7 @@ export function createProgram(version = '0.0.0', packageDir = '') {
|
|
|
120
120
|
program
|
|
121
121
|
.name('climaybe')
|
|
122
122
|
.description(
|
|
123
|
-
'Shopify CLI — theme CI/CD (workflows, branches, stores) and app repo helpers (commitlint,
|
|
123
|
+
'Shopify CLI — theme CI/CD (workflows, branches, stores) and app repo helpers (commitlint, AI ruleset)'
|
|
124
124
|
)
|
|
125
125
|
.version(versionDisplay);
|
|
126
126
|
|
|
@@ -134,7 +134,7 @@ export function createProgram(version = '0.0.0', packageDir = '') {
|
|
|
134
134
|
const app = program.command('app').description('Shopify app repo helpers (no theme workflows)');
|
|
135
135
|
app
|
|
136
136
|
.command('init')
|
|
137
|
-
.description('Set up commitlint,
|
|
137
|
+
.description('Set up commitlint, AI ruleset (rules/skills/agents), and project_type: app in climaybe.config.json')
|
|
138
138
|
.action(appInitCommand);
|
|
139
139
|
|
|
140
140
|
program
|
|
@@ -146,7 +146,7 @@ export function createProgram(version = '0.0.0', packageDir = '') {
|
|
|
146
146
|
.command('add-cursor')
|
|
147
147
|
.alias('add-cursor-skill')
|
|
148
148
|
.description(
|
|
149
|
-
'Install Electric Maybe
|
|
149
|
+
'Install Electric Maybe AI ruleset into .config/ai/ and bridge it to your editors',
|
|
150
150
|
)
|
|
151
151
|
.action(addCursorSkillCommand);
|
|
152
152
|
|