create-ollie-shop 1.1.0 → 1.3.1
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/.turbo/turbo-build.log +3 -3
- package/CHANGELOG.md +18 -0
- package/dist/index.js +52 -0
- package/dist/template/.mcp.json +8 -0
- package/dist/template/_package.json +2 -1
- package/package.json +3 -1
- package/src/create-project.ts +76 -0
- package/template/.mcp.json +8 -0
- package/template/_package.json +2 -1
- package/dist/template/.claude/agents/ollie_custom_components_frontend.md +0 -18
- package/dist/template/.claude/registry.json +0 -22
- package/dist/template/.claude/skills/agent.components.md +0 -72
- package/dist/template/.claude/skills/capability.component_architecture.md +0 -102
- package/dist/template/.claude/skills/capability.react.md +0 -40
- package/dist/template/.claude/skills/capability.sdk.md +0 -205
- package/dist/template/.claude/skills/core.constraints.md +0 -24
- package/dist/template/.claude/skills/core.identity.md +0 -34
- package/dist/template/.claude/skills/core.rules.md +0 -23
- package/template/.claude/agents/ollie_custom_components_frontend.md +0 -18
- package/template/.claude/registry.json +0 -22
- package/template/.claude/skills/agent.components.md +0 -72
- package/template/.claude/skills/capability.component_architecture.md +0 -102
- package/template/.claude/skills/capability.react.md +0 -40
- package/template/.claude/skills/capability.sdk.md +0 -205
- package/template/.claude/skills/core.constraints.md +0 -24
- package/template/.claude/skills/core.identity.md +0 -34
- package/template/.claude/skills/core.rules.md +0 -23
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> create-ollie-shop@1.1
|
|
2
|
+
> create-ollie-shop@1.3.1 build /home/runner/work/ollie-shop/ollie-shop/packages/create-ollie-shop
|
|
3
3
|
> tsup
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/index.ts
|
|
@@ -9,5 +9,5 @@
|
|
|
9
9
|
[34mCLI[39m Target: es2022
|
|
10
10
|
[34mCLI[39m Cleaning output folder
|
|
11
11
|
[34mESM[39m Build start
|
|
12
|
-
[32mESM[39m [1mdist/index.js [22m[
|
|
13
|
-
[32mESM[39m ⚡️ Build success in
|
|
12
|
+
[32mESM[39m [1mdist/index.js [22m[32m7.76 KB[39m
|
|
13
|
+
[32mESM[39m ⚡️ Build success in 176ms
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# create-ollie-shop
|
|
2
2
|
|
|
3
|
+
## 1.3.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 7c76974: Remove two orphaned files from `template/.claude/` that no longer have any consumer: `build-component.mjs` (one-shot esbuild wrapper used by the old `capability.studio_harness` skill) and `registry.json` (loading-order manifest for the old `.claude/skills/*.md` + `.claude/agents/*.md` files removed earlier). Both referenced content that lives in the standardized `@ollie-shop/skills` package now.
|
|
8
|
+
|
|
9
|
+
## 1.3.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- bca53ae: Install Ollie agent skills into the project on scaffolding. After copying the template, `create-ollie-shop` downloads the latest release tag of the public skill mirror at `github.com/ollie-shop/skills`, extracts `skills/ollie-shop/` into the new project's `.claude/skills/ollie-shop/` directory, and stamps `.claude/skills/ollie-shop/.version` with the installed version. The install path matches the default location of `npx skills add ollie-shop/skills` so customers see the same `.claude/skills/ollie-shop/` regardless of which onboarding path they choose. The stale `template/.claude/skills/` and `template/.claude/agents/` are removed in favor of the live download.
|
|
14
|
+
|
|
15
|
+
## 1.2.0
|
|
16
|
+
|
|
17
|
+
### Minor Changes
|
|
18
|
+
|
|
19
|
+
- bac681e: Scaffold an agentic Studio workflow into new projects: an `ollie_checkout_studio` agent plus `capability.design_reference` and `capability.studio_harness` skills, a server-less build helper (`.claude/build-component.mjs`), and a `chrome-devtools` MCP config. This lets an agent ingest a visual reference (a live site, Figma, or screenshot), build the component independently with esbuild, and inject its source into the store's real checkout via the hosted studio harness at `admin.ollie.shop/studio-harness.html` (same-site, so no cookie handling) — iterating from screenshots, then deploying.
|
|
20
|
+
|
|
3
21
|
## 1.1.0
|
|
4
22
|
|
|
5
23
|
### Minor Changes
|
package/dist/index.js
CHANGED
|
@@ -10,13 +10,21 @@ import { z } from "zod";
|
|
|
10
10
|
// src/create-project.ts
|
|
11
11
|
import { exec } from "child_process";
|
|
12
12
|
import fs from "fs/promises";
|
|
13
|
+
import os from "os";
|
|
13
14
|
import path from "path";
|
|
15
|
+
import { Readable } from "stream";
|
|
16
|
+
import { pipeline } from "stream/promises";
|
|
14
17
|
import { fileURLToPath } from "url";
|
|
15
18
|
import { promisify } from "util";
|
|
16
19
|
import fsExtra from "fs-extra";
|
|
17
20
|
import slugify from "slugify";
|
|
21
|
+
import * as tar from "tar";
|
|
18
22
|
var execAsync = promisify(exec);
|
|
19
23
|
var __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
24
|
+
var SKILLS_MIRROR_OWNER = "ollie-shop";
|
|
25
|
+
var SKILLS_MIRROR_REPO = "skills";
|
|
26
|
+
var SKILLS_API_BASE = `https://api.github.com/repos/${SKILLS_MIRROR_OWNER}/${SKILLS_MIRROR_REPO}`;
|
|
27
|
+
var SKILLS_TARBALL_BASE = `https://codeload.github.com/${SKILLS_MIRROR_OWNER}/${SKILLS_MIRROR_REPO}/tar.gz`;
|
|
20
28
|
async function copyWithTemplate(from, to, variables) {
|
|
21
29
|
const dirname = path.dirname(to);
|
|
22
30
|
await fsExtra.ensureDir(dirname);
|
|
@@ -66,6 +74,48 @@ async function copyTemplateDir(templateDir, targetDir, variables) {
|
|
|
66
74
|
}
|
|
67
75
|
}
|
|
68
76
|
}
|
|
77
|
+
async function fetchLatestSkillsTag() {
|
|
78
|
+
const res = await fetch(`${SKILLS_API_BASE}/tags`);
|
|
79
|
+
if (!res.ok) {
|
|
80
|
+
throw new Error(
|
|
81
|
+
`Failed to list tags from ${SKILLS_MIRROR_OWNER}/${SKILLS_MIRROR_REPO}: ${res.status} ${res.statusText}`
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
const tags = await res.json();
|
|
85
|
+
if (tags.length === 0) {
|
|
86
|
+
throw new Error(
|
|
87
|
+
`No release tags published on ${SKILLS_MIRROR_OWNER}/${SKILLS_MIRROR_REPO} yet.`
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
return tags[0].name;
|
|
91
|
+
}
|
|
92
|
+
async function installSkills(projectPath) {
|
|
93
|
+
const tag = await fetchLatestSkillsTag();
|
|
94
|
+
const version = tag.startsWith("v") ? tag.slice(1) : tag;
|
|
95
|
+
const tarballUrl = `${SKILLS_TARBALL_BASE}/refs/tags/${tag}`;
|
|
96
|
+
const res = await fetch(tarballUrl);
|
|
97
|
+
if (!res.ok || !res.body) {
|
|
98
|
+
throw new Error(
|
|
99
|
+
`Failed to download ${tarballUrl}: ${res.status} ${res.statusText}`
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "ollie-skills-"));
|
|
103
|
+
try {
|
|
104
|
+
await pipeline(
|
|
105
|
+
Readable.fromWeb(res.body),
|
|
106
|
+
tar.x({ cwd: tempDir })
|
|
107
|
+
);
|
|
108
|
+
const entries = await fs.readdir(tempDir);
|
|
109
|
+
const archiveRoot = path.join(tempDir, entries[0]);
|
|
110
|
+
const skillSrc = path.join(archiveRoot, "skills", "ollie-shop");
|
|
111
|
+
const skillDest = path.join(projectPath, ".claude", "skills", "ollie-shop");
|
|
112
|
+
await fsExtra.copy(skillSrc, skillDest);
|
|
113
|
+
await fs.writeFile(path.join(skillDest, ".version"), `${version}
|
|
114
|
+
`);
|
|
115
|
+
} finally {
|
|
116
|
+
await fs.rm(tempDir, { recursive: true, force: true });
|
|
117
|
+
}
|
|
118
|
+
}
|
|
69
119
|
async function createProject(projectPath, options) {
|
|
70
120
|
const { storeId, versionId } = options;
|
|
71
121
|
const projectName = slugify(path.basename(projectPath), { lower: true });
|
|
@@ -89,6 +139,8 @@ async function createProject(projectPath, options) {
|
|
|
89
139
|
ollieConfig.versionId = versionId;
|
|
90
140
|
await fs.writeFile(ollieConfigPath, JSON.stringify(ollieConfig, null, 2));
|
|
91
141
|
}
|
|
142
|
+
console.log("\u{1F9E0} Installing Ollie skills...");
|
|
143
|
+
await installSkills(projectPath);
|
|
92
144
|
console.log("\u{1F527} Initializing git repository...");
|
|
93
145
|
try {
|
|
94
146
|
await execAsync("git init", { cwd: projectPath });
|
|
@@ -8,9 +8,10 @@
|
|
|
8
8
|
},
|
|
9
9
|
"devDependencies": {
|
|
10
10
|
"@ollie-shop/cli": "latest",
|
|
11
|
-
"@ollie-shop/sdk": "
|
|
11
|
+
"@ollie-shop/sdk": "^1",
|
|
12
12
|
"@types/node": "^22.14.0",
|
|
13
13
|
"@types/react": "^19.2.7",
|
|
14
|
+
"esbuild": "^0.25.0",
|
|
14
15
|
"react": "^19.0.0",
|
|
15
16
|
"typescript": "^5.7.3"
|
|
16
17
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-ollie-shop",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"devDependencies": {
|
|
11
11
|
"@types/fs-extra": "^11.0.4",
|
|
12
12
|
"@types/node": "^22.14.0",
|
|
13
|
+
"@types/tar": "^6.1.13",
|
|
13
14
|
"tsup": "^8.4.0",
|
|
14
15
|
"typescript": "^5.7.3",
|
|
15
16
|
"vitest": "^3.0.4"
|
|
@@ -18,6 +19,7 @@
|
|
|
18
19
|
"fs-extra": "^11.3.0",
|
|
19
20
|
"meow": "^13.2.0",
|
|
20
21
|
"slugify": "^1.6.6",
|
|
22
|
+
"tar": "^7.4.3",
|
|
21
23
|
"zod": "^3.24.2"
|
|
22
24
|
},
|
|
23
25
|
"publishConfig": {
|
package/src/create-project.ts
CHANGED
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
import { exec } from "node:child_process";
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
|
+
import os from "node:os";
|
|
3
4
|
import path from "node:path";
|
|
5
|
+
import { Readable } from "node:stream";
|
|
6
|
+
import { pipeline } from "node:stream/promises";
|
|
4
7
|
import { fileURLToPath } from "node:url";
|
|
5
8
|
import { promisify } from "node:util";
|
|
6
9
|
import fsExtra from "fs-extra";
|
|
7
10
|
import slugify from "slugify";
|
|
11
|
+
import * as tar from "tar";
|
|
8
12
|
|
|
9
13
|
const execAsync = promisify(exec);
|
|
10
14
|
|
|
11
15
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
12
16
|
|
|
17
|
+
const SKILLS_MIRROR_OWNER = "ollie-shop";
|
|
18
|
+
const SKILLS_MIRROR_REPO = "skills";
|
|
19
|
+
const SKILLS_API_BASE = `https://api.github.com/repos/${SKILLS_MIRROR_OWNER}/${SKILLS_MIRROR_REPO}`;
|
|
20
|
+
const SKILLS_TARBALL_BASE = `https://codeload.github.com/${SKILLS_MIRROR_OWNER}/${SKILLS_MIRROR_REPO}/tar.gz`;
|
|
21
|
+
|
|
13
22
|
interface CreateProjectOptions {
|
|
14
23
|
storeId: string;
|
|
15
24
|
versionId?: string;
|
|
@@ -101,6 +110,68 @@ async function copyTemplateDir(
|
|
|
101
110
|
}
|
|
102
111
|
}
|
|
103
112
|
|
|
113
|
+
/**
|
|
114
|
+
* Ask the public mirror at github.com/ollie-shop/skills for its newest tag.
|
|
115
|
+
* Tags are created by the sync workflow on each release (vX.Y.Z); the GitHub
|
|
116
|
+
* API returns them ordered by creation date descending, so the first entry is
|
|
117
|
+
* the latest release.
|
|
118
|
+
*/
|
|
119
|
+
async function fetchLatestSkillsTag(): Promise<string> {
|
|
120
|
+
const res = await fetch(`${SKILLS_API_BASE}/tags`);
|
|
121
|
+
if (!res.ok) {
|
|
122
|
+
throw new Error(
|
|
123
|
+
`Failed to list tags from ${SKILLS_MIRROR_OWNER}/${SKILLS_MIRROR_REPO}: ${res.status} ${res.statusText}`,
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
const tags = (await res.json()) as Array<{ name: string }>;
|
|
127
|
+
if (tags.length === 0) {
|
|
128
|
+
throw new Error(
|
|
129
|
+
`No release tags published on ${SKILLS_MIRROR_OWNER}/${SKILLS_MIRROR_REPO} yet.`,
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
return tags[0].name;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Download the ollie-shop skill from the public mirror and install it into
|
|
137
|
+
* the new project's `.claude/skills/ollie-shop/` directory (the default
|
|
138
|
+
* install location the vercel-labs/skills CLI uses). The installed version
|
|
139
|
+
* is recorded in `.claude/skills/ollie-shop/.version` so future updates can
|
|
140
|
+
* detect drift.
|
|
141
|
+
*/
|
|
142
|
+
async function installSkills(projectPath: string): Promise<void> {
|
|
143
|
+
const tag = await fetchLatestSkillsTag();
|
|
144
|
+
const version = tag.startsWith("v") ? tag.slice(1) : tag;
|
|
145
|
+
|
|
146
|
+
const tarballUrl = `${SKILLS_TARBALL_BASE}/refs/tags/${tag}`;
|
|
147
|
+
const res = await fetch(tarballUrl);
|
|
148
|
+
if (!res.ok || !res.body) {
|
|
149
|
+
throw new Error(
|
|
150
|
+
`Failed to download ${tarballUrl}: ${res.status} ${res.statusText}`,
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "ollie-skills-"));
|
|
155
|
+
try {
|
|
156
|
+
// Extract the full tarball; the archive wraps everything in a single
|
|
157
|
+
// top-level directory like `ollie-shop-skills-<sha>/`.
|
|
158
|
+
await pipeline(
|
|
159
|
+
Readable.fromWeb(res.body as never),
|
|
160
|
+
tar.x({ cwd: tempDir }),
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
const entries = await fs.readdir(tempDir);
|
|
164
|
+
const archiveRoot = path.join(tempDir, entries[0]);
|
|
165
|
+
const skillSrc = path.join(archiveRoot, "skills", "ollie-shop");
|
|
166
|
+
const skillDest = path.join(projectPath, ".claude", "skills", "ollie-shop");
|
|
167
|
+
|
|
168
|
+
await fsExtra.copy(skillSrc, skillDest);
|
|
169
|
+
await fs.writeFile(path.join(skillDest, ".version"), `${version}\n`);
|
|
170
|
+
} finally {
|
|
171
|
+
await fs.rm(tempDir, { recursive: true, force: true });
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
104
175
|
/**
|
|
105
176
|
* Create a new Ollie Shop project
|
|
106
177
|
*/
|
|
@@ -144,6 +215,11 @@ export async function createProject(
|
|
|
144
215
|
await fs.writeFile(ollieConfigPath, JSON.stringify(ollieConfig, null, 2));
|
|
145
216
|
}
|
|
146
217
|
|
|
218
|
+
// Install Ollie skills from the public mirror into .claude/skills/ollie-shop/
|
|
219
|
+
// (the default location vercel-labs/skills CLI uses for `npx skills add`)
|
|
220
|
+
console.log("🧠 Installing Ollie skills...");
|
|
221
|
+
await installSkills(projectPath);
|
|
222
|
+
|
|
147
223
|
// Initialize git
|
|
148
224
|
console.log("🔧 Initializing git repository...");
|
|
149
225
|
try {
|
package/template/_package.json
CHANGED
|
@@ -8,9 +8,10 @@
|
|
|
8
8
|
},
|
|
9
9
|
"devDependencies": {
|
|
10
10
|
"@ollie-shop/cli": "latest",
|
|
11
|
-
"@ollie-shop/sdk": "
|
|
11
|
+
"@ollie-shop/sdk": "^1",
|
|
12
12
|
"@types/node": "^22.14.0",
|
|
13
13
|
"@types/react": "^19.2.7",
|
|
14
|
+
"esbuild": "^0.25.0",
|
|
14
15
|
"react": "^19.0.0",
|
|
15
16
|
"typescript": "^5.7.3"
|
|
16
17
|
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: ollie_custom_components_frontend
|
|
3
|
-
description: "Use this agent when the user asks to create, build, or implement a React UI component for Ollie Checkout — for example: 'create a coupon input component', 'build this component from the screenshot', or 'implement this Figma design as a component'."
|
|
4
|
-
model: sonnet
|
|
5
|
-
scope: component
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
Before doing anything else, use the Read tool to load your skill files in this exact order:
|
|
9
|
-
|
|
10
|
-
1. `.claude/skills/core.identity.md`
|
|
11
|
-
2. `.claude/skills/core.rules.md`
|
|
12
|
-
3. `.claude/skills/core.constraints.md`
|
|
13
|
-
4. `.claude/skills/agent.components.md`
|
|
14
|
-
5. `.claude/skills/capability.react.md`
|
|
15
|
-
6. `.claude/skills/capability.sdk.md`
|
|
16
|
-
7. `.claude/skills/capability.component_architecture.md`
|
|
17
|
-
|
|
18
|
-
After reading all files, follow the instructions defined in `agent.components.md` to assist the user.
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": "1.0.0",
|
|
3
|
-
"_maintenance": "Ollie Checkout Skill Runtime Registry. Defines the deterministic loading order for all skills. To add a new skill: create the .md file in skills/, add it here in the correct section, and reference it in the agent file.",
|
|
4
|
-
"_skillDescriptions": {
|
|
5
|
-
"core.identity": "Agent persona, priorities and communication style",
|
|
6
|
-
"core.rules": "Agent behavior rules and component code rules",
|
|
7
|
-
"core.constraints": "SDK usage rules, domain isolation, and hard limits for components",
|
|
8
|
-
"agent.components": "4-step workflow for component creation (inputs, questions, output, quality)",
|
|
9
|
-
"capability.react": "React/TypeScript standards: functional components, hooks, naming, prop patterns",
|
|
10
|
-
"capability.sdk": "Full @ollie-shop/sdk reference: hooks, types, action types, integration pattern",
|
|
11
|
-
"capability.component_architecture": "Folder structure, CSS naming convention, image handling, README template"
|
|
12
|
-
},
|
|
13
|
-
"core": ["core.identity", "core.rules", "core.constraints"],
|
|
14
|
-
"agents": {
|
|
15
|
-
"components": [
|
|
16
|
-
"agent.components",
|
|
17
|
-
"capability.react",
|
|
18
|
-
"capability.sdk",
|
|
19
|
-
"capability.component_architecture"
|
|
20
|
-
]
|
|
21
|
-
}
|
|
22
|
-
}
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: agent.components
|
|
3
|
-
type: agent
|
|
4
|
-
version: 1.0.0
|
|
5
|
-
description: >
|
|
6
|
-
Workflow for creating React UI components for Ollie Checkout. Defines the 4-step
|
|
7
|
-
process: required inputs → clarifying questions → generate files → run lint.
|
|
8
|
-
scope: component
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
# Agent: Components
|
|
12
|
-
|
|
13
|
-
## Mission
|
|
14
|
-
|
|
15
|
-
Help a designer build self-contained React UI components for the Ollie Checkout.
|
|
16
|
-
|
|
17
|
-
## Step 1 — Required Inputs (ask before coding)
|
|
18
|
-
|
|
19
|
-
Before writing any code, ask the user for:
|
|
20
|
-
|
|
21
|
-
1. **Component screenshot/print** — the exact UI to implement.
|
|
22
|
-
2. **A `.txt` file with CSS references extracted from Figma** — spacing, typography, colors, radii.
|
|
23
|
-
3. **The component name** — used as the folder name and CSS class prefix.
|
|
24
|
-
|
|
25
|
-
If any of these are missing, ask for them first.
|
|
26
|
-
|
|
27
|
-
## Step 2 — Clarifying Questions (ask after receiving inputs)
|
|
28
|
-
|
|
29
|
-
Ask about what you cannot infer from the screenshot alone. Group related questions together to avoid back-and-forth. Typical topics:
|
|
30
|
-
|
|
31
|
-
- **States & interactions**: Which states exist (loading, error, success, empty, disabled)? Are there hover/focus effects or animations?
|
|
32
|
-
- **Responsiveness**: Are there layout changes at specific breakpoints, or does it scale fluidly?
|
|
33
|
-
- **Icons**: Will the designer provide SVGs, or should you suggest an icon library?
|
|
34
|
-
|
|
35
|
-
Skip questions that are clearly answered by the screenshot or Figma file.
|
|
36
|
-
|
|
37
|
-
## Step 3 — Generate Output
|
|
38
|
-
|
|
39
|
-
Produce the full folder structure:
|
|
40
|
-
|
|
41
|
-
```
|
|
42
|
-
ComponentName/
|
|
43
|
-
index.tsx
|
|
44
|
-
ComponentName.module.css
|
|
45
|
-
README.md
|
|
46
|
-
components/
|
|
47
|
-
SubComponentName/
|
|
48
|
-
index.tsx
|
|
49
|
-
SubComponentName.module.css
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
See `capability.component_architecture` for structure rules and CSS naming.
|
|
53
|
-
See `capability.react` for React and TypeScript rules.
|
|
54
|
-
See `capability.sdk` for SDK integration patterns and how to document integration points.
|
|
55
|
-
|
|
56
|
-
## Step 4 — Quality
|
|
57
|
-
|
|
58
|
-
After generating all files, run `pnpm lint` to fix formatting issues. Only mention it to the designer if there were significant fixes or issues that need attention. Do not let linting block the designer's progress.
|
|
59
|
-
|
|
60
|
-
## Final Checklist
|
|
61
|
-
|
|
62
|
-
Before answering, verify:
|
|
63
|
-
|
|
64
|
-
- [ ] Screenshot/print, Figma CSS `.txt`, and component name were provided.
|
|
65
|
-
- [ ] Clarifying questions were asked about states, behaviors, responsiveness, and icons.
|
|
66
|
-
- [ ] Full folder structure generated (`index.tsx`, `styles.module.css`, README, subcomponents).
|
|
67
|
-
- [ ] Every `.tsx` file includes `import React from 'react';`.
|
|
68
|
-
- [ ] All CSS classes are in camelCase and correctly prefixed.
|
|
69
|
-
- [ ] Images referenced via dedicated `<img>` subcomponents.
|
|
70
|
-
- [ ] No direct use of `window` / `document` / `navigator`.
|
|
71
|
-
- [ ] README is in English with the defined structure, including SDK integration notes.
|
|
72
|
-
- [ ] `pnpm lint` was run.
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: capability.component_architecture
|
|
3
|
-
type: capability
|
|
4
|
-
version: 1.0.0
|
|
5
|
-
description: >
|
|
6
|
-
Rules for folder structure, file naming, CSS class naming, image handling,
|
|
7
|
-
README format, and accessibility guidelines.
|
|
8
|
-
loads_with:
|
|
9
|
-
- agent.components
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
# Capability: Component Architecture
|
|
13
|
-
|
|
14
|
-
## Folder Structure
|
|
15
|
-
|
|
16
|
-
```
|
|
17
|
-
ComponentName/
|
|
18
|
-
index.tsx ← parent component (named export)
|
|
19
|
-
ComponentName.module.css ← parent styles
|
|
20
|
-
README.md ← English docs
|
|
21
|
-
components/
|
|
22
|
-
SubComponentName/
|
|
23
|
-
index.tsx
|
|
24
|
-
SubComponentName.module.css
|
|
25
|
-
components/ ← only if SubComponentName has nested children
|
|
26
|
-
NestedSubComponent/
|
|
27
|
-
index.tsx
|
|
28
|
-
NestedSubComponent.module.css
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
- Parent file: always `index.tsx`, never `ComponentName.tsx`.
|
|
32
|
-
- Always create subcomponents — keep parent JSX readable and maintainable.
|
|
33
|
-
- Each subcomponent has its own `styles.module.css`.
|
|
34
|
-
|
|
35
|
-
## CSS Class Naming
|
|
36
|
-
|
|
37
|
-
All classes must be **camelCase** and **prefixed**:
|
|
38
|
-
|
|
39
|
-
- Each component uses its **own name** as the prefix → `freeShippingTopBannerRoot`, `messageRotatorRoot`
|
|
40
|
-
|
|
41
|
-
### Figma `.txt` References
|
|
42
|
-
|
|
43
|
-
- Use Figma values as source of truth for spacing, typography, colors, radii.
|
|
44
|
-
- Rename all Figma class names to match the prefix convention above.
|
|
45
|
-
- If values conflict, prefer the ones that match the screenshot.
|
|
46
|
-
|
|
47
|
-
## Styling Rules
|
|
48
|
-
|
|
49
|
-
- Use CSS Modules (`styles.module.css`) for all styles.
|
|
50
|
-
- Prefer HTML + CSS over JS-driven styling.
|
|
51
|
-
- Use flex, grid, gap, padding, margin, border, etc.
|
|
52
|
-
- Implement responsiveness with CSS media queries, not `isMobile` props.
|
|
53
|
-
|
|
54
|
-
## Images
|
|
55
|
-
|
|
56
|
-
If the component uses images, create a dedicated image subcomponent:
|
|
57
|
-
|
|
58
|
-
```tsx
|
|
59
|
-
// ComponentName/components/BrandLogoImage/index.tsx
|
|
60
|
-
import React from 'react';
|
|
61
|
-
import styles from './BrandLogoImage.module.css';
|
|
62
|
-
|
|
63
|
-
export type BrandLogoImageProps = { src: string; alt: string };
|
|
64
|
-
|
|
65
|
-
export function BrandLogoImage({ src, alt }: BrandLogoImageProps) {
|
|
66
|
-
return <img className={styles.brandLogoImageRoot} src={src} alt={alt} />;
|
|
67
|
-
}
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
- Use plain `<img>`. Do not assume Next.js `<Image />`.
|
|
71
|
-
- Pass `src` as a prop so integrators can wire real assets.
|
|
72
|
-
|
|
73
|
-
## README Structure
|
|
74
|
-
|
|
75
|
-
```md
|
|
76
|
-
# ComponentName
|
|
77
|
-
|
|
78
|
-
## Overview
|
|
79
|
-
Short description of what the component is and where it fits in the checkout flow.
|
|
80
|
-
|
|
81
|
-
## Props
|
|
82
|
-
List each prop, its type, and what it controls visually.
|
|
83
|
-
|
|
84
|
-
## States / Behaviors
|
|
85
|
-
Describe the main visual states (default, hover, focus, error, success, disabled, loading).
|
|
86
|
-
|
|
87
|
-
## Usage
|
|
88
|
-
Minimal example with fake data and handlers.
|
|
89
|
-
|
|
90
|
-
## Notes for Developers
|
|
91
|
-
Which props map to which SDK hooks/actions. See `capability.sdk` for the SDK reference.
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
## Accessibility
|
|
95
|
-
|
|
96
|
-
Good to have, not a blocker:
|
|
97
|
-
|
|
98
|
-
- `<button>` for clickable actions.
|
|
99
|
-
- `<label>` with `htmlFor` linked to inputs.
|
|
100
|
-
- `<ul>/<li>` for lists.
|
|
101
|
-
- `aria-invalid`, `aria-describedby` for form fields when natural.
|
|
102
|
-
- Basic keyboard support for complex interactive elements.
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: capability.react
|
|
3
|
-
type: capability
|
|
4
|
-
version: 1.0.0
|
|
5
|
-
description: >
|
|
6
|
-
React and TypeScript standards for generated components. Covers functional components,
|
|
7
|
-
named exports, hook usage, and prop naming conventions.
|
|
8
|
-
loads_with:
|
|
9
|
-
- agent.components
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
# Capability: React
|
|
13
|
-
|
|
14
|
-
## Rules
|
|
15
|
-
|
|
16
|
-
- **Functional components only.** No class components.
|
|
17
|
-
- **TypeScript required.** All files are `.tsx` with explicit types.
|
|
18
|
-
- **Named exports only.** No default exports for components.
|
|
19
|
-
- **Every `.tsx` file must start with:** `import React from 'react';`
|
|
20
|
-
- This includes `index.tsx` and all subcomponent files.
|
|
21
|
-
|
|
22
|
-
## Internal State
|
|
23
|
-
|
|
24
|
-
- `useState` is allowed for UI-only state (focused, open, hovered, animations).
|
|
25
|
-
- `useEffect` is allowed only for visual concerns (focus management, animations).
|
|
26
|
-
- No `useEffect` for data fetching or business logic.
|
|
27
|
-
|
|
28
|
-
## Naming
|
|
29
|
-
|
|
30
|
-
- Components: PascalCase (e.g., `CouponInput`)
|
|
31
|
-
- Props interface: `<ComponentName>Props` (e.g., `CouponInputProps`)
|
|
32
|
-
- Handler props: `on<Action>` (e.g., `onApply`, `onChange`)
|
|
33
|
-
- Boolean props: `is<State>` or `has<Feature>` (e.g., `isLoading`, `isDisabled`)
|
|
34
|
-
|
|
35
|
-
## Props Patterns
|
|
36
|
-
|
|
37
|
-
- Inputs/fields: `value`, `onChange`, optional `placeholder`, `label`, `helperText`, `errorMessage`, `isDisabled`
|
|
38
|
-
- Actions: `onApplyCoupon`, `onRemoveItem`, `onToggle` — callbacks only, parent decides behavior
|
|
39
|
-
- Async UI: `isLoading`, `errorMessage`, `successMessage` — toggle visuals only
|
|
40
|
-
- Lists: `items` (array), `onSelectItem`, `onRemoveItem`
|