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
package/src/commands/init.js
CHANGED
|
@@ -5,21 +5,26 @@ import {
|
|
|
5
5
|
promptStoreLoop,
|
|
6
6
|
promptPreviewWorkflows,
|
|
7
7
|
promptBuildWorkflows,
|
|
8
|
+
promptLighthouseWorkflows,
|
|
8
9
|
promptDevKit,
|
|
9
10
|
promptVSCodeDevTasks,
|
|
10
11
|
promptProjectName,
|
|
11
12
|
promptCommitlint,
|
|
13
|
+
promptBranchProtection,
|
|
12
14
|
promptCursorSkills,
|
|
15
|
+
promptAiEditors,
|
|
13
16
|
promptConfigureCISecrets,
|
|
17
|
+
promptNoRemoteAction,
|
|
18
|
+
promptOwnerRepo,
|
|
14
19
|
promptUpdateExistingSecrets,
|
|
15
20
|
promptSecretValue,
|
|
16
21
|
} from '../lib/prompts.js';
|
|
17
22
|
import { readConfig, writeConfig, getProjectType, readPkg } from '../lib/config.js';
|
|
18
|
-
import { ensureGitRepo, ensureInitialCommit, ensureStagingBranch, createStoreBranches, getSuggestedTagForRelease } from '../lib/git.js';
|
|
23
|
+
import { ensureGitRepo, ensureInitialCommit, ensureStagingBranch, createStoreBranches, getSuggestedTagForRelease, addOriginRemote } from '../lib/git.js';
|
|
19
24
|
import { scaffoldWorkflows } from '../lib/workflows.js';
|
|
20
25
|
import { createStoreDirectories } from '../lib/store-sync.js';
|
|
21
26
|
import { scaffoldCommitlint } from '../lib/commit-tooling.js';
|
|
22
|
-
import {
|
|
27
|
+
import { scaffoldAiConfig, logAiConfigResult } from '../lib/cursor-bundle.js';
|
|
23
28
|
import { getMissingBuildWorkflowRequirements, ensureBuildWorkflowDefaults } from '../lib/build-workflows.js';
|
|
24
29
|
import { getDevKitExistingFiles, scaffoldThemeDevKit } from '../lib/theme-dev-kit.js';
|
|
25
30
|
import {
|
|
@@ -36,6 +41,7 @@ import {
|
|
|
36
41
|
setSecret,
|
|
37
42
|
setGitLabVariable,
|
|
38
43
|
} from '../lib/github-secrets.js';
|
|
44
|
+
import { logBranchProtectionResult, syncBranchProtection } from '../lib/branch-protection.js';
|
|
39
45
|
|
|
40
46
|
function installThemeDependencies(cwd = process.cwd()) {
|
|
41
47
|
try {
|
|
@@ -48,23 +54,72 @@ function installThemeDependencies(cwd = process.cwd()) {
|
|
|
48
54
|
}
|
|
49
55
|
}
|
|
50
56
|
|
|
57
|
+
const DOCS_BASE = 'https://github.com/electricmaybe/climaybe#';
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Print a short description (and optional docs link) as a preamble to the next prompt.
|
|
61
|
+
* A leading blank line detaches it from the previous answer, and there is no leading
|
|
62
|
+
* glyph, so the text reads as an intro to the question that follows — not a trailing
|
|
63
|
+
* note on the question above it.
|
|
64
|
+
* @param {string} text - one sentence, what the answer is for / what it should look like
|
|
65
|
+
* @param {string} [anchor] - README heading anchor (e.g. 'theme-dev-kit')
|
|
66
|
+
*/
|
|
67
|
+
function hint(text, anchor) {
|
|
68
|
+
console.log('');
|
|
69
|
+
console.log(pc.dim(text));
|
|
70
|
+
if (anchor) console.log(pc.cyan(` ${DOCS_BASE}${anchor}`));
|
|
71
|
+
}
|
|
72
|
+
|
|
51
73
|
/**
|
|
52
74
|
* Run the full init flow: prompts, config write, git, branches, workflows.
|
|
53
75
|
* Used by both init (when not already inited or user confirms reinit) and reinit.
|
|
54
76
|
*/
|
|
55
77
|
async function runInitFlow() {
|
|
56
78
|
const hasPackageJson = !!readPkg();
|
|
57
|
-
|
|
79
|
+
let projectName;
|
|
80
|
+
if (!hasPackageJson) {
|
|
81
|
+
hint("Used only when this repo has no package.json yet — the repo/folder name is usually fine.");
|
|
82
|
+
projectName = await promptProjectName();
|
|
83
|
+
}
|
|
58
84
|
|
|
59
85
|
// 1. Collect stores from user
|
|
86
|
+
hint('Enter a Shopify subdomain (e.g. voldt-staging) or full domain; add 2+ stores for multi-store mode.');
|
|
60
87
|
const stores = await promptStoreLoop();
|
|
61
88
|
const mode = stores.length > 1 ? 'multi' : 'single';
|
|
89
|
+
|
|
90
|
+
hint('CI that publishes a preview theme per PR and cleans it up on close.', 'preview-and-cleanup-workflows');
|
|
62
91
|
const enablePreviewWorkflows = await promptPreviewWorkflows();
|
|
92
|
+
|
|
93
|
+
hint('CI that bundles _scripts JS and compiles Tailwind on push. Yes if the theme uses _scripts/_styles.', 'build-and-lighthouse-workflows');
|
|
63
94
|
const enableBuildWorkflows = await promptBuildWorkflows();
|
|
95
|
+
|
|
96
|
+
let enableLighthouseWorkflows = false;
|
|
97
|
+
if (enableBuildWorkflows) {
|
|
98
|
+
hint('Runs Lighthouse performance + a11y budgets on the staging branch (inside the build pipeline).', 'build-and-lighthouse-workflows');
|
|
99
|
+
enableLighthouseWorkflows = await promptLighthouseWorkflows();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
hint('Local config + ignore defaults for theme work (Theme Check, Prettier, Lighthouse, gitignore).', 'theme-dev-kit');
|
|
64
103
|
const enableDevKit = await promptDevKit();
|
|
65
|
-
|
|
104
|
+
let enableVSCodeTasks = false;
|
|
105
|
+
if (enableDevKit) {
|
|
106
|
+
hint('Adds a VS Code task that runs `climaybe serve`. Only useful if you use VS Code.');
|
|
107
|
+
enableVSCodeTasks = await promptVSCodeDevTasks();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
hint('Checks commit messages locally so they follow conventional commits (feat:, fix:, …).');
|
|
66
111
|
const enableCommitlint = await promptCommitlint();
|
|
112
|
+
|
|
113
|
+
hint('Requires PRs on production branches (main, or each live-<alias>). Skips cleanly without GitHub/gh.', 'branch-protection');
|
|
114
|
+
const enableBranchProtection = await promptBranchProtection();
|
|
115
|
+
|
|
116
|
+
hint('Electric Maybe rules/skills/subagents installed to a single .config/ai/ source of truth.', 'ai-ruleset');
|
|
67
117
|
const enableCursorSkills = await promptCursorSkills();
|
|
118
|
+
let aiEditors = [];
|
|
119
|
+
if (enableCursorSkills) {
|
|
120
|
+
hint('Pick the editors to bridge to .config/ai/ — only the ones you select get a bridge file.', 'ai-ruleset');
|
|
121
|
+
aiEditors = await promptAiEditors();
|
|
122
|
+
}
|
|
68
123
|
|
|
69
124
|
console.log(pc.dim(`\n Mode: ${mode}-store (${stores.length} store(s))`));
|
|
70
125
|
|
|
@@ -102,11 +157,13 @@ async function runInitFlow() {
|
|
|
102
157
|
default_store: stores[0].domain,
|
|
103
158
|
preview_workflows: enablePreviewWorkflows,
|
|
104
159
|
build_workflows: enableBuildWorkflows,
|
|
160
|
+
lighthouse_workflows: enableBuildWorkflows ? enableLighthouseWorkflows : undefined,
|
|
105
161
|
build_entrypoints_ready: enableBuildWorkflows ? missingBuildFiles?.length === 0 : undefined,
|
|
106
162
|
dev_kit: enableDevKit,
|
|
107
163
|
vscode_tasks: enableVSCodeTasks,
|
|
108
164
|
commitlint: enableCommitlint,
|
|
109
165
|
cursor_skills: enableCursorSkills,
|
|
166
|
+
ai_editors: enableCursorSkills ? aiEditors : undefined,
|
|
110
167
|
stores: {},
|
|
111
168
|
};
|
|
112
169
|
|
|
@@ -134,13 +191,31 @@ async function runInitFlow() {
|
|
|
134
191
|
}
|
|
135
192
|
}
|
|
136
193
|
|
|
194
|
+
if (enableBranchProtection) {
|
|
195
|
+
const protection = syncBranchProtection({
|
|
196
|
+
mode,
|
|
197
|
+
aliases: stores.map((s) => s.alias),
|
|
198
|
+
cwd: process.cwd(),
|
|
199
|
+
});
|
|
200
|
+
logBranchProtectionResult(protection, mode);
|
|
201
|
+
if (protection.applied.length > 0 || protection.removed.length > 0) {
|
|
202
|
+
console.log(
|
|
203
|
+
pc.dim(
|
|
204
|
+
' Rule: PR required on protected branches; live-* bypass allowed for shopify[bot], github-actions[bot], actions-user.'
|
|
205
|
+
)
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
} else {
|
|
209
|
+
console.log(pc.dim(' Branch protection: skipped (declined at prompt).'));
|
|
210
|
+
}
|
|
211
|
+
|
|
137
212
|
// 6. Scaffold workflows
|
|
138
213
|
scaffoldWorkflows(mode, {
|
|
139
214
|
includePreview: enablePreviewWorkflows,
|
|
140
215
|
includeBuild: enableBuildWorkflows,
|
|
141
216
|
});
|
|
142
217
|
|
|
143
|
-
// 7. Optional commitlint + Husky and
|
|
218
|
+
// 7. Optional commitlint + Husky and the AI ruleset (rules, skills, agents + editor bridges)
|
|
144
219
|
if (enableCommitlint) {
|
|
145
220
|
console.log(pc.dim(' Setting up commitlint + Husky...'));
|
|
146
221
|
if (scaffoldCommitlint()) {
|
|
@@ -150,14 +225,8 @@ async function runInitFlow() {
|
|
|
150
225
|
}
|
|
151
226
|
}
|
|
152
227
|
if (enableCursorSkills) {
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
console.log(
|
|
156
|
-
pc.green(' Electric Maybe Cursor bundle → .cursor/rules, .cursor/skills, .cursor/agents'),
|
|
157
|
-
);
|
|
158
|
-
} else {
|
|
159
|
-
console.log(pc.yellow(' Cursor bundle not found in package (skipped).'));
|
|
160
|
-
}
|
|
228
|
+
const aiResult = scaffoldAiConfig(process.cwd(), { editors: aiEditors });
|
|
229
|
+
logAiConfigResult(aiResult, { pc });
|
|
161
230
|
}
|
|
162
231
|
|
|
163
232
|
if (enableDevKit) {
|
|
@@ -190,12 +259,19 @@ async function runInitFlow() {
|
|
|
190
259
|
}
|
|
191
260
|
console.log(pc.dim(` Preview workflows: ${enablePreviewWorkflows ? 'enabled' : 'disabled'}`));
|
|
192
261
|
console.log(pc.dim(` Build workflows: ${enableBuildWorkflows ? 'enabled' : 'disabled'}`));
|
|
262
|
+
if (enableBuildWorkflows) {
|
|
263
|
+
console.log(pc.dim(` Lighthouse CI: ${enableLighthouseWorkflows ? 'enabled' : 'disabled'}`));
|
|
264
|
+
}
|
|
193
265
|
console.log(pc.dim(` Theme dev kit: ${enableDevKit ? 'enabled' : 'disabled'}`));
|
|
194
266
|
if (enableDevKit) {
|
|
195
267
|
console.log(pc.dim(` VS Code tasks: ${enableVSCodeTasks ? 'enabled' : 'disabled'}`));
|
|
196
268
|
}
|
|
197
269
|
console.log(pc.dim(` commitlint + Husky: ${enableCommitlint ? 'enabled' : 'disabled'}`));
|
|
198
|
-
console.log(
|
|
270
|
+
console.log(
|
|
271
|
+
pc.dim(
|
|
272
|
+
` AI ruleset: ${enableCursorSkills ? `installed (${aiEditors.join(', ') || 'cursor'})` : 'skipped'}`
|
|
273
|
+
)
|
|
274
|
+
);
|
|
199
275
|
|
|
200
276
|
const suggestedTag = getSuggestedTagForRelease();
|
|
201
277
|
const tagLabel = suggestedTag === 'v1.0.0' ? 'Tag your first release' : 'Tag your next release';
|
|
@@ -239,9 +315,30 @@ async function runInitFlow() {
|
|
|
239
315
|
return;
|
|
240
316
|
}
|
|
241
317
|
if (!setter.checkRemote()) {
|
|
242
|
-
console.log(pc.yellow(
|
|
243
|
-
|
|
244
|
-
|
|
318
|
+
console.log(pc.yellow(` This folder has no ${setter.name} "origin" remote yet.`));
|
|
319
|
+
const action = await promptNoRemoteAction(setter.name);
|
|
320
|
+
if (action !== 'add') {
|
|
321
|
+
console.log(pc.dim(' Skipping CI secrets. Add a remote later, then re-run "climaybe init" or set them in the repo Settings.\n'));
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
const slug = await promptOwnerRepo(setter.name);
|
|
325
|
+
if (!slug) {
|
|
326
|
+
console.log(pc.dim(' No repository entered; skipping CI secrets for now.\n'));
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
try {
|
|
330
|
+
const url = addOriginRemote(slug, ciHost, process.cwd());
|
|
331
|
+
console.log(pc.green(` Added origin → ${url}`));
|
|
332
|
+
console.log(pc.dim(' Create the repo on ' + setter.name + ' and "git push -u origin --all" when ready.'));
|
|
333
|
+
} catch (err) {
|
|
334
|
+
console.log(pc.red(` Could not add origin remote: ${err.message}`));
|
|
335
|
+
console.log(pc.dim(' Add it manually with "git remote add origin <url>", then re-run "climaybe init".\n'));
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
if (!setter.checkRemote()) {
|
|
339
|
+
console.log(pc.dim(' Remote added, but it is not recognized as a ' + setter.name + ' URL; skipping CI secrets.\n'));
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
245
342
|
}
|
|
246
343
|
|
|
247
344
|
const existingNames =
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
isBuildWorkflowsEnabled,
|
|
5
5
|
isCommitlintEnabled,
|
|
6
6
|
isCursorSkillsEnabled,
|
|
7
|
+
getAiEditors,
|
|
7
8
|
isPreviewWorkflowsEnabled,
|
|
8
9
|
readConfig,
|
|
9
10
|
} from '../lib/config.js';
|
|
@@ -11,7 +12,7 @@ import { scaffoldWorkflows } from '../lib/workflows.js';
|
|
|
11
12
|
import { requireThemeProject } from '../lib/theme-guard.js';
|
|
12
13
|
import { scaffoldThemeDevKit } from '../lib/theme-dev-kit.js';
|
|
13
14
|
import { scaffoldCommitlint } from '../lib/commit-tooling.js';
|
|
14
|
-
import {
|
|
15
|
+
import { scaffoldAiConfig } from '../lib/cursor-bundle.js';
|
|
15
16
|
|
|
16
17
|
export async function updateCommand() {
|
|
17
18
|
console.log(pc.bold('\n climaybe — Update\n'));
|
|
@@ -38,7 +39,7 @@ export async function updateCommand() {
|
|
|
38
39
|
scaffoldCommitlint(process.cwd(), { skipInstall: true });
|
|
39
40
|
}
|
|
40
41
|
if (isCursorSkillsEnabled()) {
|
|
41
|
-
|
|
42
|
+
scaffoldAiConfig(process.cwd(), { editors: getAiEditors() });
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
scaffoldWorkflows(mode, { includePreview, includeBuild });
|
|
@@ -6,13 +6,14 @@ alwaysApply: true
|
|
|
6
6
|
---
|
|
7
7
|
# Rule Index
|
|
8
8
|
|
|
9
|
-
When you perform any of the following, **read and apply** the corresponding rule file from `.
|
|
9
|
+
When you perform any of the following, **read and apply** the corresponding rule file from `.config/ai/rules/`:
|
|
10
10
|
|
|
11
11
|
- **Editing `assets/*.js` or `assets/style.css`, build outputs vs source, where to edit JS/CSS** → `project-overview.mdc` (Build Outputs vs Source — edit `_scripts/`/`_styles/`, never the generated `assets/` files)
|
|
12
12
|
- **Git commits, commit messages** → `commit-rules.mdc`
|
|
13
13
|
- **Accessibility, a11y, focus, WCAG, UI behavior** → `accessibility-rules.mdc`
|
|
14
14
|
- **JavaScript, web components, _scripts/, *.js** → `javascript-standards.mdc`
|
|
15
15
|
- **Tailwind CSS, theme tokens, Liquid/CSS classes, _styles/** → `tailwindcss-rules.mdc`
|
|
16
|
+
- **Store performance, LCP/INP/CLS, head scripts, third-party tags, CSS/JS tiering, images, _head*/_body* snippets** → `performance-guide.mdc`
|
|
16
17
|
- **Liquid syntax and usage** → `liquid.mdc`
|
|
17
18
|
- **Section files (sections/*.liquid)** → `sections.mdc`
|
|
18
19
|
- **Snippets (snippets/*.liquid)** → `snippets.mdc`
|
|
@@ -7,9 +7,9 @@ alwaysApply: false
|
|
|
7
7
|
|
|
8
8
|
How to add new cursor rules to the project
|
|
9
9
|
|
|
10
|
-
1. Always place rule files in PROJECT_ROOT/.
|
|
10
|
+
1. Always place rule files in PROJECT_ROOT/.config/ai/rules/:
|
|
11
11
|
```
|
|
12
|
-
.
|
|
12
|
+
.config/ai/rules/
|
|
13
13
|
├── your-rule-name.mdc
|
|
14
14
|
├── another-rule.mdc
|
|
15
15
|
└── ...
|
|
@@ -23,16 +23,17 @@ How to add new cursor rules to the project
|
|
|
23
23
|
3. Directory structure:
|
|
24
24
|
```
|
|
25
25
|
PROJECT_ROOT/
|
|
26
|
-
├── .
|
|
27
|
-
│ └──
|
|
28
|
-
│
|
|
29
|
-
│
|
|
26
|
+
├── .config/
|
|
27
|
+
│ └── ai/
|
|
28
|
+
│ └── rules/
|
|
29
|
+
│ ├── your-rule-name.mdc
|
|
30
|
+
│ └── ...
|
|
30
31
|
└── ...
|
|
31
32
|
```
|
|
32
33
|
|
|
33
34
|
4. Never place rule files:
|
|
34
35
|
- In the project root
|
|
35
|
-
- In subdirectories outside .
|
|
36
|
+
- In subdirectories outside .config/ai/rules
|
|
36
37
|
- In any other location
|
|
37
38
|
|
|
38
39
|
5. Cursor rules have the following structure:
|
|
@@ -56,13 +56,13 @@ This document defines how to translate Figma designs into code for this project.
|
|
|
56
56
|
|
|
57
57
|
- No React/Vue. UI is Liquid (sections + snippets) plus native JS web components.
|
|
58
58
|
- New UI from Figma: prefer adding or composing existing snippets/sections; add new snippets/sections only when no fit exists.
|
|
59
|
-
- Sections must have a valid `{% schema %}` and semantic HTML; snippets must have LiquidDoc `{%- doc -%}` and follow `.
|
|
59
|
+
- Sections must have a valid `{% schema %}` and semantic HTML; snippets must have LiquidDoc `{%- doc -%}` and follow `.config/ai/rules/snippets.mdc` and `.config/ai/rules/liquid.mdc`.
|
|
60
60
|
|
|
61
61
|
### 1.3 Frameworks & Libraries
|
|
62
62
|
|
|
63
63
|
- **Templating:** Liquid only (Shopify theme).
|
|
64
64
|
- **Styling:** Tailwind CSS v4. Entry: `_styles/main.css` (imports Tailwind, tokens, component CSS). Compiled output: `assets/style.css`.
|
|
65
|
-
- **Script:** Native JS only (no React/Vue). Web components with `#` private fields, AbortController for listeners, JSDoc; see `.
|
|
65
|
+
- **Script:** Native JS only (no React/Vue). Web components with `#` private fields, AbortController for listeners, JSDoc; see `.config/ai/rules/javascript-standards.mdc`.
|
|
66
66
|
- **Build:** Tailwind processes `_styles/main.css`; content sources (for class scanning) are listed in `_styles/main.css` (`@source` for layout, blocks, sections, snippets, templates, assets).
|
|
67
67
|
|
|
68
68
|
### 1.4 Asset Management
|
|
@@ -127,8 +127,8 @@ config/ # Theme settings
|
|
|
127
127
|
- **Reuse existing snippets/sections** from `snippets/` and `sections/` instead of duplicating (e.g. buttons → `a--button`, icons → `a--icon`, cards → `m--*` cards, modals → `m--modal` / electric-modal).
|
|
128
128
|
- Use the project’s **color system** (semantic tokens from `02.02_colors.css`), **typography** (`02.03_typography.css`, utilities), and **spacing/sizes** (`02.01_sizes.css`, Tailwind utilities that use them).
|
|
129
129
|
- **Tailwind:** Only static class names; map Figma colors to semantic tokens (e.g. `bg-surface`, `text-primary`); use project breakpoints and spacing scale.
|
|
130
|
-
- Respect **accessibility** (WCAG 2.1 AA): semantic HTML, ARIA where needed, keyboard and screen reader support; see `.
|
|
131
|
-
- Respect **JS standards**: no new dependencies; if adding behavior, use native JS/web components per `.
|
|
130
|
+
- Respect **accessibility** (WCAG 2.1 AA): semantic HTML, ARIA where needed, keyboard and screen reader support; see `.config/ai/rules/accessibility-rules.mdc`.
|
|
131
|
+
- Respect **JS standards**: no new dependencies; if adding behavior, use native JS/web components per `.config/ai/rules/javascript-standards.mdc`.
|
|
132
132
|
- Aim for **1:1 visual parity** with the Figma design and validate with the screenshot.
|
|
133
133
|
|
|
134
134
|
### 2.3 Asset Handling
|
|
@@ -144,16 +144,16 @@ config/ # Theme settings
|
|
|
144
144
|
|
|
145
145
|
### 3.1 Liquid
|
|
146
146
|
|
|
147
|
-
- Follow `.
|
|
148
|
-
- Use `{%- doc -%}` and LiquidDoc for all new snippets; document params and examples per `.
|
|
147
|
+
- Follow `.config/ai/rules/liquid.mdc`: e.g. assign computed values before passing to `render`; no inline `append` in `render` parameters; valid tags/filters only.
|
|
148
|
+
- Use `{%- doc -%}` and LiquidDoc for all new snippets; document params and examples per `.config/ai/rules/liquid-doc-rules.mdc` and `.config/ai/rules/snippets.mdc`.
|
|
149
149
|
|
|
150
150
|
### 3.2 Sections
|
|
151
151
|
|
|
152
|
-
- Every section: valid `{% schema %}`, semantic HTML, section-scoped classes. Follow `.
|
|
152
|
+
- Every section: valid `{% schema %}`, semantic HTML, section-scoped classes. Follow `.config/ai/rules/sections.mdc` and `.config/ai/rules/schemas.mdc` for schema definitions.
|
|
153
153
|
|
|
154
154
|
### 3.3 Accessibility
|
|
155
155
|
|
|
156
|
-
- Semantic structure, ARIA where needed, keyboard and focus behavior, WCAG 2.1 AA. See `.
|
|
156
|
+
- Semantic structure, ARIA where needed, keyboard and focus behavior, WCAG 2.1 AA. See `.config/ai/rules/accessibility-rules.mdc`. Use the accessibility-pass skill when asked for an a11y audit.
|
|
157
157
|
|
|
158
158
|
### 3.4 Performance
|
|
159
159
|
|
|
@@ -6,7 +6,7 @@ alwaysApply: false
|
|
|
6
6
|
---
|
|
7
7
|
# Global Rules Reference
|
|
8
8
|
|
|
9
|
-
This project uses global rules from ~/.claude/rules/ (when using Claude). **In Cursor, project rules live in `.
|
|
9
|
+
This project uses global rules from ~/.claude/rules/ (when using Claude). **In Cursor, project rules live in `.config/ai/rules/` and are applied per the rule index (`00-rule-index.mdc`).**
|
|
10
10
|
|
|
11
11
|
## Global Rules Location
|
|
12
12
|
All reusable rules are stored in:
|
|
@@ -52,6 +52,7 @@ These rules are synced from ~/.claude/rules/:
|
|
|
52
52
|
### Project-Specific Rules
|
|
53
53
|
These rules are unique to this project:
|
|
54
54
|
- `project-overview.mdc` - Electric Maybe theme overview
|
|
55
|
+
- `performance-guide.mdc` - Store performance architecture (CSS/JS tiering, third-party containment, LCP)
|
|
55
56
|
- `js-refactor-tasks.mdc` - Current refactoring tasks
|
|
56
57
|
|
|
57
58
|
## Important Notes
|