@olonjs/cli 3.0.87 → 3.0.89
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/assets/src_tenant_alpha.sh +2139 -378
- package/assets/templates/agritourism/src_tenant.sh +1 -1
- package/assets/templates/alpha/src_tenant.sh +2139 -378
- package/package.json +1 -1
|
@@ -3,555 +3,1600 @@ set -e
|
|
|
3
3
|
|
|
4
4
|
echo "Starting project reconstruction..."
|
|
5
5
|
|
|
6
|
-
mkdir -p "
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
mkdir -p ".cursor"
|
|
7
|
+
mkdir -p ".cursor/skills-cursor"
|
|
8
|
+
mkdir -p ".cursor/skills-cursor/create-rule"
|
|
9
|
+
echo "Creating .cursor/skills-cursor/create-rule/SKILL.md..."
|
|
10
|
+
cat << 'END_OF_FILE_CONTENT' > ".cursor/skills-cursor/create-rule/SKILL.md"
|
|
11
|
+
---
|
|
12
|
+
name: create-rule
|
|
13
|
+
description: >-
|
|
14
|
+
Create Cursor rules for persistent AI guidance. Use when you want to create a
|
|
15
|
+
rule, add coding standards, set up project conventions, configure
|
|
16
|
+
file-specific patterns, create RULE.md files, or asks about .cursor/rules/ or
|
|
17
|
+
AGENTS.md.
|
|
18
|
+
---
|
|
19
|
+
# Creating Cursor Rules
|
|
10
20
|
|
|
11
|
-
|
|
21
|
+
Create project rules in `.cursor/rules/` to provide persistent context for the AI agent.
|
|
12
22
|
|
|
13
|
-
|
|
23
|
+
## Gather Requirements
|
|
14
24
|
|
|
15
|
-
|
|
25
|
+
Before creating a rule, determine:
|
|
26
|
+
|
|
27
|
+
1. **Purpose**: What should this rule enforce or teach?
|
|
28
|
+
2. **Scope**: Should it always apply, or only for specific files?
|
|
29
|
+
3. **File patterns**: If file-specific, which glob patterns?
|
|
30
|
+
|
|
31
|
+
### Inferring from Context
|
|
32
|
+
|
|
33
|
+
If you have previous conversation context, infer rules from what was discussed. You can create multiple rules if the conversation covers distinct topics or patterns. Don't ask redundant questions if the context already provides the answers.
|
|
16
34
|
|
|
17
|
-
|
|
35
|
+
### Required Questions
|
|
18
36
|
|
|
19
|
-
|
|
20
|
-
-
|
|
37
|
+
If the user hasn't specified scope, ask:
|
|
38
|
+
- "Should this rule always apply, or only when working with specific files?"
|
|
21
39
|
|
|
22
|
-
|
|
40
|
+
If they mentioned specific files and haven't provided concrete patterns, ask:
|
|
41
|
+
- "Which file patterns should this rule apply to?" (e.g., `**/*.ts`, `backend/**/*.py`)
|
|
42
|
+
|
|
43
|
+
It's very important that we get clarity on the file patterns.
|
|
44
|
+
|
|
45
|
+
Use the AskQuestion tool when available to gather this efficiently.
|
|
23
46
|
|
|
24
47
|
---
|
|
25
48
|
|
|
26
|
-
##
|
|
49
|
+
## Rule File Format
|
|
27
50
|
|
|
28
|
-
|
|
29
|
-
- **`src/data/config/menu.json`** — Menu (es. `{ main: [{ label, href }] }`).
|
|
30
|
-
- **`src/data/config/theme.json`** — (Opzionale) Token tema (colori, font, radius).
|
|
31
|
-
- **`src/data/pages/<slug>.json`** — Una pagina = `slug`, `meta`, `sections[]` (array di blocchi `id`, `type`, `data`, `settings`). **Per creare una nuova pagina** basta aggiungere un file `<slug>.json` in `src/data/pages/`; lo slug del nome file diventa il path della pagina (es. `chi-siamo.json` → `/chi-siamo`).
|
|
32
|
-
- **`src/components/<sectionType>/`** — Una cartella per tipo di blocco (hero, header, footer, feature-grid, …).
|
|
33
|
-
- **`src/App.tsx`** — Carica site, menu, theme, pages; costruisce la config; renderizza **`<JsonPagesEngine config={config} />` *(from `@olonjs/core`, legacy alias: `@jsonpages/core`)***.
|
|
51
|
+
Rules are `.mdc` files in `.cursor/rules/` with YAML frontmatter:
|
|
34
52
|
|
|
35
|
-
|
|
53
|
+
```
|
|
54
|
+
.cursor/rules/
|
|
55
|
+
typescript-standards.mdc
|
|
56
|
+
react-patterns.mdc
|
|
57
|
+
api-conventions.mdc
|
|
58
|
+
```
|
|
36
59
|
|
|
37
|
-
|
|
60
|
+
### File Structure
|
|
38
61
|
|
|
62
|
+
```markdown
|
|
63
|
+
---
|
|
64
|
+
description: Brief description of what this rule does
|
|
65
|
+
globs: **/*.ts # File pattern for file-specific rules
|
|
66
|
+
alwaysApply: false # Set to true if rule should always apply
|
|
39
67
|
---
|
|
40
68
|
|
|
41
|
-
|
|
69
|
+
# Rule Title
|
|
42
70
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
- **Stili:** Puoi usare classi Tailwind "libere" o un set di variabili CSS (es. `--local-bg`, `--local-text`) per coerenza. Le spec CIP (solo variabili, niente utility nude) sono per il percorso governance; qui puoi adattare alle tue convenzioni.
|
|
46
|
-
- **Asset:** Se il Core espone `resolveAssetUrl(path, tenantId)`, usalo per le immagini; altrimenti path relativi o URL assoluti.
|
|
71
|
+
Your rule content here...
|
|
72
|
+
```
|
|
47
73
|
|
|
48
|
-
|
|
74
|
+
### Frontmatter Fields
|
|
75
|
+
|
|
76
|
+
| Field | Type | Description |
|
|
77
|
+
|-------|------|-------------|
|
|
78
|
+
| `description` | string | What the rule does (shown in rule picker) |
|
|
79
|
+
| `globs` | string | File pattern - rule applies when matching files are open |
|
|
80
|
+
| `alwaysApply` | boolean | If true, applies to every session |
|
|
49
81
|
|
|
50
82
|
---
|
|
51
83
|
|
|
52
|
-
##
|
|
84
|
+
## Rule Configurations
|
|
85
|
+
|
|
86
|
+
### Always Apply
|
|
87
|
+
|
|
88
|
+
For universal standards that should apply to every conversation:
|
|
53
89
|
|
|
54
|
-
|
|
90
|
+
```yaml
|
|
91
|
+
---
|
|
92
|
+
description: Core coding standards for the project
|
|
93
|
+
alwaysApply: true
|
|
94
|
+
---
|
|
95
|
+
```
|
|
55
96
|
|
|
56
|
-
|
|
57
|
-
- **View:** Per il `src` dell'immagine usa **`resolveAssetUrl(data.image.url, tenantId)`**; sul nodo che rappresenta l'immagine imposta **`data-jp-field="image"`** (così l'Inspector lega correttamente il campo).
|
|
97
|
+
### Apply to Specific Files
|
|
58
98
|
|
|
59
|
-
|
|
99
|
+
For rules that apply when working with certain file types:
|
|
60
100
|
|
|
101
|
+
```yaml
|
|
61
102
|
---
|
|
103
|
+
description: TypeScript conventions for this project
|
|
104
|
+
globs: **/*.ts
|
|
105
|
+
alwaysApply: false
|
|
106
|
+
---
|
|
107
|
+
```
|
|
62
108
|
|
|
63
|
-
|
|
109
|
+
---
|
|
64
110
|
|
|
65
|
-
|
|
66
|
-
- **CMS esterno / API:** Invece di importare i JSON, fai fetch (o SSR) e costruisci gli stessi oggetti (siteConfig, menuConfig, pages) e li passi a `JsonPagesEngine`. La forma delle pagine resta: `{ slug, meta?, sections[] }`; ogni section: `{ id, type, data, settings? }`.
|
|
67
|
-
- **Ibrido:** Header/footer da `site.json`, body da API o da altro CMS: costruisci un unico `pages[slug]` con `sections` che rispettano i tipi di blocco che hai nel registry.
|
|
111
|
+
## Best Practices
|
|
68
112
|
|
|
69
|
-
|
|
113
|
+
### Keep Rules Concise
|
|
70
114
|
|
|
71
|
-
**
|
|
115
|
+
- **Under 50 lines**: Rules should be concise and to the point
|
|
116
|
+
- **One concern per rule**: Split large rules into focused pieces
|
|
117
|
+
- **Actionable**: Write like clear internal docs
|
|
118
|
+
- **Concrete examples**: Ideally provide concrete examples of how to fix issues
|
|
72
119
|
|
|
73
120
|
---
|
|
74
121
|
|
|
75
|
-
##
|
|
122
|
+
## Example Rules
|
|
76
123
|
|
|
77
|
-
|
|
78
|
-
- **Config da passare a JsonPagesEngine:**
|
|
79
|
-
`tenantId`, `registry`, `pages`, `siteConfig`, `menuConfig`, `themeConfig` (o oggetto vuoto), `themeCss: { tenant: cssString }`.
|
|
80
|
-
Se **non** usi Studio, **schemas** e **addSection** possono essere placeholder (oggetto vuoto / no-op) se il Core lo permette; altrimenti fornisci il minimo (es. schemas = `{}`, addSection = `{ addableSectionTypes: [], sectionTypeLabels: {}, getDefaultSectionData: () => ({}) }`) per non rompere l'engine.
|
|
124
|
+
### TypeScript Standards
|
|
81
125
|
|
|
82
|
-
|
|
126
|
+
```markdown
|
|
127
|
+
---
|
|
128
|
+
description: TypeScript coding standards
|
|
129
|
+
globs: **/*.ts
|
|
130
|
+
alwaysApply: false
|
|
131
|
+
---
|
|
83
132
|
|
|
84
|
-
|
|
133
|
+
# Error Handling
|
|
85
134
|
|
|
135
|
+
\`\`\`typescript
|
|
136
|
+
// ❌ BAD
|
|
137
|
+
try {
|
|
138
|
+
await fetchData();
|
|
139
|
+
} catch (e) {}
|
|
140
|
+
|
|
141
|
+
// ✅ GOOD
|
|
142
|
+
try {
|
|
143
|
+
await fetchData();
|
|
144
|
+
} catch (e) {
|
|
145
|
+
logger.error('Failed to fetch', { error: e });
|
|
146
|
+
throw new DataFetchError('Unable to retrieve data', { cause: e });
|
|
147
|
+
}
|
|
148
|
+
\`\`\`
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### React Patterns
|
|
152
|
+
|
|
153
|
+
```markdown
|
|
154
|
+
---
|
|
155
|
+
description: React component patterns
|
|
156
|
+
globs: **/*.tsx
|
|
157
|
+
alwaysApply: false
|
|
86
158
|
---
|
|
87
159
|
|
|
88
|
-
|
|
160
|
+
# React Patterns
|
|
89
161
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
| **Registry** | Mappare ogni tipo di blocco usato nei JSON al componente corrispondente. |
|
|
95
|
-
| **Header / menu** | Header component riceve `data`, `settings`, `menu`; `menu` viene da `menuConfig` (es. `menuConfig.main`). |
|
|
96
|
-
| **Pagine** | Ogni pagina = un entry in `pages` con `sections[]`; ogni section ha `id`, `type`, `data`, `settings?`. |
|
|
97
|
-
| **Nuova pagina** | Aggiungere un file `<slug>.json` in `src/data/pages/` (lo slug diventa il path della pagina). |
|
|
98
|
-
| **Image (se schema)** | Campo immagine = oggetto `{ url, alt? }` con schema `.describe('ui:image-picker')`; View usa `resolveAssetUrl` e `data-jp-field="image"`. |
|
|
99
|
-
| **Studio / ICE** | Non usati: niente schema obbligatori, niente data-jp-*, niente overlay CSS, niente Add Section. |
|
|
162
|
+
- Use functional components
|
|
163
|
+
- Extract custom hooks for reusable logic
|
|
164
|
+
- Colocate styles with components
|
|
165
|
+
```
|
|
100
166
|
|
|
101
167
|
---
|
|
102
168
|
|
|
103
|
-
##
|
|
169
|
+
## Checklist
|
|
104
170
|
|
|
105
|
-
|
|
171
|
+
- [ ] File is `.mdc` format in `.cursor/rules/`
|
|
172
|
+
- [ ] Frontmatter configured correctly
|
|
173
|
+
- [ ] Content under 500 lines
|
|
174
|
+
- [ ] Includes concrete examples
|
|
106
175
|
|
|
107
176
|
END_OF_FILE_CONTENT
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
177
|
+
mkdir -p ".cursor/skills-cursor/create-skill"
|
|
178
|
+
echo "Creating .cursor/skills-cursor/create-skill/SKILL.md..."
|
|
179
|
+
cat << 'END_OF_FILE_CONTENT' > ".cursor/skills-cursor/create-skill/SKILL.md"
|
|
180
|
+
---
|
|
181
|
+
name: create-skill
|
|
182
|
+
description: >-
|
|
183
|
+
Guides users through creating effective Agent Skills for Cursor. Use when you
|
|
184
|
+
want to create, write, or author a new skill, or asks about skill structure,
|
|
185
|
+
best practices, or SKILL.md format.
|
|
186
|
+
---
|
|
187
|
+
# Creating Skills in Cursor
|
|
111
188
|
|
|
189
|
+
This skill guides you through creating effective Agent Skills for Cursor. Skills are markdown files that teach the agent how to perform specific tasks: reviewing PRs using team standards, generating commit messages in a preferred format, querying database schemas, or any specialized workflow.
|
|
112
190
|
|
|
191
|
+
## Before You Begin: Gather Requirements
|
|
113
192
|
|
|
114
|
-
|
|
193
|
+
Before creating a skill, gather essential information from the user about:
|
|
115
194
|
|
|
116
|
-
|
|
195
|
+
1. **Purpose and scope**: What specific task or workflow should this skill help with?
|
|
196
|
+
2. **Target location**: Should this be a personal skill (~/.cursor/skills/) or project skill (.cursor/skills/)?
|
|
197
|
+
3. **Trigger scenarios**: When should the agent automatically apply this skill?
|
|
198
|
+
4. **Key domain knowledge**: What specialized information does the agent need that it wouldn't already know?
|
|
199
|
+
5. **Output format preferences**: Are there specific templates, formats, or styles required?
|
|
200
|
+
6. **Existing patterns**: Are there existing examples or conventions to follow?
|
|
117
201
|
|
|
118
|
-
|
|
202
|
+
### Inferring from Context
|
|
119
203
|
|
|
120
|
-
|
|
204
|
+
If you have previous conversation context, infer the skill from what was discussed. You can create skills based on workflows, patterns, or domain knowledge that emerged in the conversation.
|
|
205
|
+
|
|
206
|
+
### Gathering Additional Information
|
|
121
207
|
|
|
122
|
-
|
|
208
|
+
If you need clarification, use the AskQuestion tool when available:
|
|
123
209
|
|
|
124
|
-
|
|
125
|
-
|
|
210
|
+
```
|
|
211
|
+
Example AskQuestion usage:
|
|
212
|
+
- "Where should this skill be stored?" with options like ["Personal (~/.cursor/skills/)", "Project (.cursor/skills/)"]
|
|
213
|
+
- "Should this skill include executable scripts?" with options like ["Yes", "No"]
|
|
214
|
+
```
|
|
126
215
|
|
|
127
|
-
|
|
216
|
+
If the AskQuestion tool is not available, ask these questions conversationally.
|
|
128
217
|
|
|
129
218
|
---
|
|
130
219
|
|
|
131
|
-
##
|
|
220
|
+
## Skill File Structure
|
|
221
|
+
|
|
222
|
+
### Directory Layout
|
|
132
223
|
|
|
133
|
-
|
|
134
|
-
- **`src/data/config/menu.json`** — Menu (e.g., `{ main: [{ label, href }] }`).
|
|
135
|
-
- **`src/data/config/theme.json`** — (Optional) Theme tokens (colors, fonts, radius).
|
|
136
|
-
- **`src/data/pages/<slug>.json`** — One page = `slug`, `meta`, `sections[]` (array of blocks `id`, `type`, `data`, `settings`). **To create a new page**, simply add a `<slug>.json` file in `src/data/pages/`; the filename slug becomes the page path (e.g., `about-us.json` → `/about-us`).
|
|
137
|
-
- **`src/components/<sectionType>/`** — One folder per block type (hero, header, footer, feature-grid, …).
|
|
138
|
-
- **`src/App.tsx`** — Loads site, menu, theme, pages; builds the config; renders **`<JsonPagesEngine config={config} />`**.
|
|
224
|
+
Skills are stored as directories containing a `SKILL.md` file:
|
|
139
225
|
|
|
140
|
-
|
|
226
|
+
```
|
|
227
|
+
skill-name/
|
|
228
|
+
├── SKILL.md # Required - main instructions
|
|
229
|
+
├── reference.md # Optional - detailed documentation
|
|
230
|
+
├── examples.md # Optional - usage examples
|
|
231
|
+
└── scripts/ # Optional - utility scripts
|
|
232
|
+
├── validate.py
|
|
233
|
+
└── helper.sh
|
|
234
|
+
```
|
|
141
235
|
|
|
142
|
-
|
|
236
|
+
### Storage Locations
|
|
143
237
|
|
|
144
|
-
|
|
238
|
+
| Type | Path | Scope |
|
|
239
|
+
|------|------|-------|
|
|
240
|
+
| Personal | ~/.cursor/skills/skill-name/ | Available across all your projects |
|
|
241
|
+
| Project | .cursor/skills/skill-name/ | Shared with anyone using the repository |
|
|
145
242
|
|
|
146
|
-
|
|
243
|
+
**IMPORTANT**: Never create skills in `~/.cursor/skills-cursor/`. This directory is reserved for Cursor's internal built-in skills and is managed automatically by the system.
|
|
147
244
|
|
|
148
|
-
|
|
149
|
-
- **No "Full Capsule" requirement:** you can have just `View.tsx` (and maybe an `index.ts` exporting the View). Zod schemas and types are only needed if you want dev-time type-safety or plan to activate the CMS later.
|
|
150
|
-
- **Styles:** You can use "free" Tailwind classes or a set of CSS variables (e.g., `--local-bg`, `--local-text`) for consistency. CIP specs (variables only, no naked utilities) are for the Governance path; here you can adapt to your conventions.
|
|
151
|
-
- **Assets:** If the Core exposes `resolveAssetUrl(path, tenantId)`, use it for images; otherwise, use relative paths or absolute URLs.
|
|
245
|
+
### SKILL.md Structure
|
|
152
246
|
|
|
153
|
-
|
|
247
|
+
Every skill requires a `SKILL.md` file with YAML frontmatter and markdown body:
|
|
154
248
|
|
|
249
|
+
```markdown
|
|
155
250
|
---
|
|
251
|
+
name: your-skill-name
|
|
252
|
+
description: Brief description of what this skill does and when to use it
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
# Your Skill Name
|
|
156
256
|
|
|
157
|
-
##
|
|
257
|
+
## Instructions
|
|
258
|
+
Clear, step-by-step guidance for the agent.
|
|
158
259
|
|
|
159
|
-
|
|
260
|
+
## Examples
|
|
261
|
+
Concrete examples of using this skill.
|
|
262
|
+
```
|
|
160
263
|
|
|
161
|
-
|
|
162
|
-
- **View:** For the image `src`, use **`resolveAssetUrl(data.image.url, tenantId)`**; on the node representing the image, set **`data-jp-field="image"`** (so the Inspector binds the field correctly).
|
|
264
|
+
### Required Metadata Fields
|
|
163
265
|
|
|
164
|
-
|
|
266
|
+
| Field | Requirements | Purpose |
|
|
267
|
+
|-------|--------------|---------|
|
|
268
|
+
| `name` | Max 64 chars, lowercase letters/numbers/hyphens only | Unique identifier for the skill |
|
|
269
|
+
| `description` | Max 1024 chars, non-empty | Helps agent decide when to apply the skill |
|
|
165
270
|
|
|
166
271
|
---
|
|
167
272
|
|
|
168
|
-
##
|
|
273
|
+
## Writing Effective Descriptions
|
|
169
274
|
|
|
170
|
-
|
|
171
|
-
- **External CMS / API:** Instead of importing JSONs, fetch (or SSR) and build the same objects (siteConfig, menuConfig, pages) and pass them to `JsonPagesEngine`. The page shape remains: `{ slug, meta?, sections[] }`; each section: `{ id, type, data, settings? }`.
|
|
172
|
-
- **Hybrid:** Header/footer from `site.json`, body from API or another CMS: build a single `pages[slug]` with `sections` that respect the block types you have in the registry.
|
|
275
|
+
The description is **critical** for skill discovery. The agent uses it to decide when to apply your skill.
|
|
173
276
|
|
|
174
|
-
|
|
277
|
+
### Description Best Practices
|
|
175
278
|
|
|
176
|
-
**
|
|
279
|
+
1. **Write in third person** (the description is injected into the system prompt):
|
|
280
|
+
- ✅ Good: "Processes Excel files and generates reports"
|
|
281
|
+
- ❌ Avoid: "I can help you process Excel files"
|
|
282
|
+
- ❌ Avoid: "You can use this to process Excel files"
|
|
177
283
|
|
|
178
|
-
|
|
284
|
+
2. **Be specific and include trigger terms**:
|
|
285
|
+
- ✅ Good: "Extract text and tables from PDF files, fill forms, merge documents. Use when working with PDF files or when the user mentions PDFs, forms, or document extraction."
|
|
286
|
+
- ❌ Vague: "Helps with documents"
|
|
287
|
+
|
|
288
|
+
3. **Include both WHAT and WHEN**:
|
|
289
|
+
- WHAT: What the skill does (specific capabilities)
|
|
290
|
+
- WHEN: When the agent should use it (trigger scenarios)
|
|
179
291
|
|
|
180
|
-
|
|
292
|
+
### Description Examples
|
|
181
293
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
If you are **not** using Studio, **schemas** and **addSection** can be placeholders (empty object / no-op) if the Core allows it; otherwise, provide the minimum (e.g., schemas = `{}`, addSection = `{ addableSectionTypes: [], sectionTypeLabels: {}, getDefaultSectionData: () => ({}) }`) to prevent engine errors.
|
|
294
|
+
```yaml
|
|
295
|
+
# PDF Processing
|
|
296
|
+
description: Extract text and tables from PDF files, fill forms, merge documents. Use when working with PDF files or when the user mentions PDFs, forms, or document extraction.
|
|
186
297
|
|
|
187
|
-
|
|
298
|
+
# Excel Analysis
|
|
299
|
+
description: Analyze Excel spreadsheets, create pivot tables, generate charts. Use when analyzing Excel files, spreadsheets, tabular data, or .xlsx files.
|
|
188
300
|
|
|
189
|
-
|
|
301
|
+
# Git Commit Helper
|
|
302
|
+
description: Generate descriptive commit messages by analyzing git diffs. Use when the user asks for help writing commit messages or reviewing staged changes.
|
|
303
|
+
|
|
304
|
+
# Code Review
|
|
305
|
+
description: Review code for quality, security, and best practices following team standards. Use when reviewing pull requests, code changes, or when the user asks for a code review.
|
|
306
|
+
```
|
|
190
307
|
|
|
191
308
|
---
|
|
192
309
|
|
|
193
|
-
##
|
|
310
|
+
## Core Authoring Principles
|
|
311
|
+
|
|
312
|
+
### 1. Concise is Key
|
|
313
|
+
|
|
314
|
+
The context window is shared with conversation history, other skills, and requests. Every token competes for space.
|
|
315
|
+
|
|
316
|
+
**Default assumption**: The agent is already very smart. Only add context it doesn't already have.
|
|
317
|
+
|
|
318
|
+
Challenge each piece of information:
|
|
319
|
+
- "Does the agent really need this explanation?"
|
|
320
|
+
- "Can I assume the agent knows this?"
|
|
321
|
+
- "Does this paragraph justify its token cost?"
|
|
322
|
+
|
|
323
|
+
**Good (concise)**:
|
|
324
|
+
```markdown
|
|
325
|
+
## Extract PDF text
|
|
326
|
+
|
|
327
|
+
Use pdfplumber for text extraction:
|
|
328
|
+
|
|
329
|
+
\`\`\`python
|
|
330
|
+
import pdfplumber
|
|
331
|
+
|
|
332
|
+
with pdfplumber.open("file.pdf") as pdf:
|
|
333
|
+
text = pdf.pages[0].extract_text()
|
|
334
|
+
\`\`\`
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
**Bad (verbose)**:
|
|
338
|
+
```markdown
|
|
339
|
+
## Extract PDF text
|
|
340
|
+
|
|
341
|
+
PDF (Portable Document Format) files are a common file format that contains
|
|
342
|
+
text, images, and other content. To extract text from a PDF, you'll need to
|
|
343
|
+
use a library. There are many libraries available for PDF processing, but we
|
|
344
|
+
recommend pdfplumber because it's easy to use and handles most cases well...
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### 2. Keep SKILL.md Under 500 Lines
|
|
348
|
+
|
|
349
|
+
For optimal performance, the main SKILL.md file should be concise. Use progressive disclosure for detailed content.
|
|
350
|
+
|
|
351
|
+
### 3. Progressive Disclosure
|
|
352
|
+
|
|
353
|
+
Put essential information in SKILL.md; detailed reference material in separate files that the agent reads only when needed.
|
|
354
|
+
|
|
355
|
+
```markdown
|
|
356
|
+
# PDF Processing
|
|
357
|
+
|
|
358
|
+
## Quick start
|
|
359
|
+
[Essential instructions here]
|
|
360
|
+
|
|
361
|
+
## Additional resources
|
|
362
|
+
- For complete API details, see [reference.md](reference.md)
|
|
363
|
+
- For usage examples, see [examples.md](examples.md)
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
**Keep references one level deep** - link directly from SKILL.md to reference files. Deeply nested references may result in partial reads.
|
|
367
|
+
|
|
368
|
+
### 4. Set Appropriate Degrees of Freedom
|
|
369
|
+
|
|
370
|
+
Match specificity to the task's fragility:
|
|
194
371
|
|
|
195
|
-
|
|
|
196
|
-
|
|
197
|
-
| **
|
|
198
|
-
| **
|
|
199
|
-
| **
|
|
200
|
-
| **Header / Menu** | Header component receives `data`, `settings`, `menu`; `menu` comes from `menuConfig` (e.g., `menuConfig.main`). |
|
|
201
|
-
| **Pages** | Each page = one entry in `pages` with `sections[]`; each section has `id`, `type`, `data`, `settings?`. |
|
|
202
|
-
| **New Page** | Add a `<slug>.json` file in `src/data/pages/` (slug becomes page path). |
|
|
203
|
-
| **Image (if schema)** | Image field = object `{ url, alt? }` with schema `.describe('ui:image-picker')`; View uses `resolveAssetUrl` and `data-jp-field="image"`. |
|
|
204
|
-
| **Studio / ICE** | Not used: no mandatory schemas, no data-jp-*, no overlay CSS, no Add Section. |
|
|
372
|
+
| Freedom Level | When to Use | Example |
|
|
373
|
+
|---------------|-------------|---------|
|
|
374
|
+
| **High** (text instructions) | Multiple valid approaches, context-dependent | Code review guidelines |
|
|
375
|
+
| **Medium** (pseudocode/templates) | Preferred pattern with acceptable variation | Report generation |
|
|
376
|
+
| **Low** (specific scripts) | Fragile operations, consistency critical | Database migrations |
|
|
205
377
|
|
|
206
378
|
---
|
|
207
379
|
|
|
208
|
-
##
|
|
380
|
+
## Common Patterns
|
|
209
381
|
|
|
210
|
-
|
|
382
|
+
### Template Pattern
|
|
211
383
|
|
|
384
|
+
Provide output format templates:
|
|
212
385
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
386
|
+
```markdown
|
|
387
|
+
## Report structure
|
|
388
|
+
|
|
389
|
+
Use this template:
|
|
390
|
+
|
|
391
|
+
\`\`\`markdown
|
|
392
|
+
# [Analysis Title]
|
|
393
|
+
|
|
394
|
+
## Executive summary
|
|
395
|
+
[One-paragraph overview of key findings]
|
|
396
|
+
|
|
397
|
+
## Key findings
|
|
398
|
+
- Finding 1 with supporting data
|
|
399
|
+
- Finding 2 with supporting data
|
|
400
|
+
|
|
401
|
+
## Recommendations
|
|
402
|
+
1. Specific actionable recommendation
|
|
403
|
+
2. Specific actionable recommendation
|
|
404
|
+
\`\`\`
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
### Examples Pattern
|
|
408
|
+
|
|
409
|
+
For skills where output quality depends on seeing examples:
|
|
410
|
+
|
|
411
|
+
```markdown
|
|
412
|
+
## Commit message format
|
|
413
|
+
|
|
414
|
+
**Example 1:**
|
|
415
|
+
Input: Added user authentication with JWT tokens
|
|
416
|
+
Output:
|
|
417
|
+
\`\`\`
|
|
418
|
+
feat(auth): implement JWT-based authentication
|
|
419
|
+
|
|
420
|
+
Add login endpoint and token validation middleware
|
|
421
|
+
\`\`\`
|
|
422
|
+
|
|
423
|
+
**Example 2:**
|
|
424
|
+
Input: Fixed bug where dates displayed incorrectly
|
|
425
|
+
Output:
|
|
426
|
+
\`\`\`
|
|
427
|
+
fix(reports): correct date formatting in timezone conversion
|
|
428
|
+
|
|
429
|
+
Use UTC timestamps consistently across report generation
|
|
430
|
+
\`\`\`
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
### Workflow Pattern
|
|
434
|
+
|
|
435
|
+
Break complex operations into clear steps with checklists:
|
|
436
|
+
|
|
437
|
+
```markdown
|
|
438
|
+
## Form filling workflow
|
|
439
|
+
|
|
440
|
+
Copy this checklist and track progress:
|
|
216
441
|
|
|
217
|
-
|
|
442
|
+
\`\`\`
|
|
443
|
+
Task Progress:
|
|
444
|
+
- [ ] Step 1: Analyze the form
|
|
445
|
+
- [ ] Step 2: Create field mapping
|
|
446
|
+
- [ ] Step 3: Validate mapping
|
|
447
|
+
- [ ] Step 4: Fill the form
|
|
448
|
+
- [ ] Step 5: Verify output
|
|
449
|
+
\`\`\`
|
|
218
450
|
|
|
219
|
-
**
|
|
451
|
+
**Step 1: Analyze the form**
|
|
452
|
+
Run: \`python scripts/analyze_form.py input.pdf\`
|
|
453
|
+
...
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
### Conditional Workflow Pattern
|
|
457
|
+
|
|
458
|
+
Guide through decision points:
|
|
459
|
+
|
|
460
|
+
```markdown
|
|
461
|
+
## Document modification workflow
|
|
462
|
+
|
|
463
|
+
1. Determine the modification type:
|
|
464
|
+
|
|
465
|
+
**Creating new content?** → Follow "Creation workflow" below
|
|
466
|
+
**Editing existing content?** → Follow "Editing workflow" below
|
|
220
467
|
|
|
221
|
-
|
|
468
|
+
2. Creation workflow:
|
|
469
|
+
- Use docx-js library
|
|
470
|
+
- Build document from scratch
|
|
471
|
+
...
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
### Feedback Loop Pattern
|
|
475
|
+
|
|
476
|
+
For quality-critical tasks, implement validation loops:
|
|
477
|
+
|
|
478
|
+
```markdown
|
|
479
|
+
## Document editing process
|
|
480
|
+
|
|
481
|
+
1. Make your edits
|
|
482
|
+
2. **Validate immediately**: \`python scripts/validate.py output/\`
|
|
483
|
+
3. If validation fails:
|
|
484
|
+
- Review the error message
|
|
485
|
+
- Fix the issues
|
|
486
|
+
- Run validation again
|
|
487
|
+
4. **Only proceed when validation passes**
|
|
488
|
+
```
|
|
222
489
|
|
|
223
490
|
---
|
|
224
491
|
|
|
225
|
-
##
|
|
492
|
+
## Utility Scripts
|
|
226
493
|
|
|
227
|
-
-
|
|
228
|
-
-
|
|
229
|
-
-
|
|
230
|
-
-
|
|
231
|
-
-
|
|
494
|
+
Pre-made scripts offer advantages over generated code:
|
|
495
|
+
- More reliable than generated code
|
|
496
|
+
- Save tokens (no code in context)
|
|
497
|
+
- Save time (no code generation)
|
|
498
|
+
- Ensure consistency across uses
|
|
232
499
|
|
|
233
|
-
|
|
500
|
+
```markdown
|
|
501
|
+
## Utility scripts
|
|
502
|
+
|
|
503
|
+
**analyze_form.py**: Extract all form fields from PDF
|
|
504
|
+
\`\`\`bash
|
|
505
|
+
python scripts/analyze_form.py input.pdf > fields.json
|
|
506
|
+
\`\`\`
|
|
507
|
+
|
|
508
|
+
**validate.py**: Check for errors
|
|
509
|
+
\`\`\`bash
|
|
510
|
+
python scripts/validate.py fields.json
|
|
511
|
+
# Returns: "OK" or lists conflicts
|
|
512
|
+
\`\`\`
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
Make clear whether the agent should **execute** the script (most common) or **read** it as reference.
|
|
234
516
|
|
|
235
517
|
---
|
|
236
518
|
|
|
237
|
-
##
|
|
519
|
+
## Anti-Patterns to Avoid
|
|
520
|
+
|
|
521
|
+
### 1. Windows-Style Paths
|
|
522
|
+
- ✅ Use: `scripts/helper.py`
|
|
523
|
+
- ❌ Avoid: `scripts\helper.py`
|
|
524
|
+
|
|
525
|
+
### 2. Too Many Options
|
|
526
|
+
```markdown
|
|
527
|
+
# Bad - confusing
|
|
528
|
+
"You can use pypdf, or pdfplumber, or PyMuPDF, or..."
|
|
238
529
|
|
|
239
|
-
|
|
530
|
+
# Good - provide a default with escape hatch
|
|
531
|
+
"Use pdfplumber for text extraction.
|
|
532
|
+
For scanned PDFs requiring OCR, use pdf2image with pytesseract instead."
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
### 3. Time-Sensitive Information
|
|
536
|
+
```markdown
|
|
537
|
+
# Bad - will become outdated
|
|
538
|
+
"If you're doing this before August 2025, use the old API."
|
|
539
|
+
|
|
540
|
+
# Good - use an "old patterns" section
|
|
541
|
+
## Current method
|
|
542
|
+
Use the v2 API endpoint.
|
|
543
|
+
|
|
544
|
+
## Old patterns (deprecated)
|
|
545
|
+
<details>
|
|
546
|
+
<summary>Legacy v1 API</summary>
|
|
547
|
+
...
|
|
548
|
+
</details>
|
|
549
|
+
```
|
|
240
550
|
|
|
241
|
-
|
|
551
|
+
### 4. Inconsistent Terminology
|
|
552
|
+
Choose one term and use it throughout:
|
|
553
|
+
- ✅ Always "API endpoint" (not mixing "URL", "route", "path")
|
|
554
|
+
- ✅ Always "field" (not mixing "box", "element", "control")
|
|
242
555
|
|
|
243
|
-
|
|
556
|
+
### 5. Vague Skill Names
|
|
557
|
+
- ✅ Good: `processing-pdfs`, `analyzing-spreadsheets`
|
|
558
|
+
- ❌ Avoid: `helper`, `utils`, `tools`
|
|
244
559
|
|
|
245
560
|
---
|
|
246
561
|
|
|
247
|
-
##
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
562
|
+
## Skill Creation Workflow
|
|
563
|
+
|
|
564
|
+
When helping a user create a skill, follow this process:
|
|
565
|
+
|
|
566
|
+
### Phase 1: Discovery
|
|
567
|
+
|
|
568
|
+
Gather information about:
|
|
569
|
+
1. The skill's purpose and primary use case
|
|
570
|
+
2. Storage location (personal vs project)
|
|
571
|
+
3. Trigger scenarios
|
|
572
|
+
4. Any specific requirements or constraints
|
|
573
|
+
5. Existing examples or patterns to follow
|
|
574
|
+
|
|
575
|
+
If you have access to the AskQuestion tool, use it for efficient structured gathering. Otherwise, ask conversationally.
|
|
576
|
+
|
|
577
|
+
### Phase 2: Design
|
|
578
|
+
|
|
579
|
+
1. Draft the skill name (lowercase, hyphens, max 64 chars)
|
|
580
|
+
2. Write a specific, third-person description
|
|
581
|
+
3. Outline the main sections needed
|
|
582
|
+
4. Identify if supporting files or scripts are needed
|
|
583
|
+
|
|
584
|
+
### Phase 3: Implementation
|
|
585
|
+
|
|
586
|
+
1. Create the directory structure
|
|
587
|
+
2. Write the SKILL.md file with frontmatter
|
|
588
|
+
3. Create any supporting reference files
|
|
589
|
+
4. Create any utility scripts if needed
|
|
590
|
+
|
|
591
|
+
### Phase 4: Verification
|
|
592
|
+
|
|
593
|
+
1. Verify the SKILL.md is under 500 lines
|
|
594
|
+
2. Check that the description is specific and includes trigger terms
|
|
595
|
+
3. Ensure consistent terminology throughout
|
|
596
|
+
4. Verify all file references are one level deep
|
|
597
|
+
5. Test that the skill can be discovered and applied
|
|
261
598
|
|
|
262
599
|
---
|
|
263
600
|
|
|
264
|
-
##
|
|
601
|
+
## Complete Example
|
|
265
602
|
|
|
266
|
-
|
|
267
|
-
- **View:** Receives `data` and `settings` (and `menu` for header). Does not import Zod. Uses **only** CSS variables for colors/radii (e.g., `bg-[var(--local-bg)]`), root section with `z-index` ≤ 1.
|
|
268
|
-
- **IDAC (ICE):** On every editable scalar field: **`data-jp-field="<fieldKey>"`**. On every editable array item: **`data-jp-item-id="<stableId>"`** and **`data-jp-item-field="<arrayKey>"`**. This allows the Inspector to bind selection and forms to the correct paths.
|
|
269
|
-
- **Schema:** Use UI vocabulary (ECIP): `.describe('ui:text')`, `ui:textarea`, `ui:select`, `ui:number`, `ui:list`, `ui:icon-picker`, **`ui:image-picker`** (see §3.1). Editable object arrays: every object must have an `id` (BaseArrayItem).
|
|
603
|
+
Here's a complete example of a well-structured skill:
|
|
270
604
|
|
|
271
|
-
**
|
|
605
|
+
**Directory structure:**
|
|
606
|
+
```
|
|
607
|
+
code-review/
|
|
608
|
+
├── SKILL.md
|
|
609
|
+
├── STANDARDS.md
|
|
610
|
+
└── examples.md
|
|
611
|
+
```
|
|
272
612
|
|
|
613
|
+
**SKILL.md:**
|
|
614
|
+
```markdown
|
|
615
|
+
---
|
|
616
|
+
name: code-review
|
|
617
|
+
description: Review code for quality, security, and maintainability following team standards. Use when reviewing pull requests, examining code changes, or when the user asks for a code review.
|
|
273
618
|
---
|
|
274
619
|
|
|
275
|
-
|
|
620
|
+
# Code Review
|
|
276
621
|
|
|
277
|
-
|
|
622
|
+
## Quick Start
|
|
278
623
|
|
|
279
|
-
|
|
624
|
+
When reviewing code:
|
|
280
625
|
|
|
281
|
-
|
|
282
|
-
|
|
626
|
+
1. Check for correctness and potential bugs
|
|
627
|
+
2. Verify security best practices
|
|
628
|
+
3. Assess code readability and maintainability
|
|
629
|
+
4. Ensure tests are adequate
|
|
283
630
|
|
|
284
|
-
|
|
631
|
+
## Review Checklist
|
|
285
632
|
|
|
286
|
-
|
|
633
|
+
- [ ] Logic is correct and handles edge cases
|
|
634
|
+
- [ ] No security vulnerabilities (SQL injection, XSS, etc.)
|
|
635
|
+
- [ ] Code follows project style conventions
|
|
636
|
+
- [ ] Functions are appropriately sized and focused
|
|
637
|
+
- [ ] Error handling is comprehensive
|
|
638
|
+
- [ ] Tests cover the changes
|
|
287
639
|
|
|
288
|
-
|
|
289
|
-
import { z } from 'zod';
|
|
290
|
-
import { BaseSectionData } from '@/lib/base-schemas';
|
|
640
|
+
## Providing Feedback
|
|
291
641
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
})
|
|
297
|
-
.describe('ui:image-picker');
|
|
642
|
+
Format feedback as:
|
|
643
|
+
- 🔴 **Critical**: Must fix before merge
|
|
644
|
+
- 🟡 **Suggestion**: Consider improving
|
|
645
|
+
- 🟢 **Nice to have**: Optional enhancement
|
|
298
646
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
});
|
|
647
|
+
## Additional Resources
|
|
648
|
+
|
|
649
|
+
- For detailed coding standards, see [STANDARDS.md](STANDARDS.md)
|
|
650
|
+
- For example reviews, see [examples.md](examples.md)
|
|
304
651
|
```
|
|
305
652
|
|
|
306
|
-
|
|
307
|
-
- The **`image`** field in the section data uses that schema (with default), so the Inspector shows the Image Picker widget for `image`.
|
|
653
|
+
---
|
|
308
654
|
|
|
309
|
-
|
|
655
|
+
## Summary Checklist
|
|
310
656
|
|
|
311
|
-
|
|
312
|
-
- On the node representing the image (e.g., the `<img>` or a wrapper): **`data-jp-field="image"`** so the Stage click binds the Inspector to the `image` field.
|
|
313
|
-
- Other editable fields (caption, label) with **`data-jp-field="caption"`** and **`data-jp-field="label"`** where appropriate.
|
|
657
|
+
Before finalizing a skill, verify:
|
|
314
658
|
|
|
315
|
-
|
|
659
|
+
### Core Quality
|
|
660
|
+
- [ ] Description is specific and includes key terms
|
|
661
|
+
- [ ] Description includes both WHAT and WHEN
|
|
662
|
+
- [ ] Written in third person
|
|
663
|
+
- [ ] SKILL.md body is under 500 lines
|
|
664
|
+
- [ ] Consistent terminology throughout
|
|
665
|
+
- [ ] Examples are concrete, not abstract
|
|
316
666
|
|
|
317
|
-
###
|
|
667
|
+
### Structure
|
|
668
|
+
- [ ] File references are one level deep
|
|
669
|
+
- [ ] Progressive disclosure used appropriately
|
|
670
|
+
- [ ] Workflows have clear steps
|
|
671
|
+
- [ ] No time-sensitive information
|
|
318
672
|
|
|
319
|
-
|
|
320
|
-
-
|
|
673
|
+
### If Including Scripts
|
|
674
|
+
- [ ] Scripts solve problems rather than punt
|
|
675
|
+
- [ ] Required packages are documented
|
|
676
|
+
- [ ] Error handling is explicit and helpful
|
|
677
|
+
- [ ] No Windows-style paths
|
|
321
678
|
|
|
679
|
+
END_OF_FILE_CONTENT
|
|
680
|
+
mkdir -p ".cursor/skills-cursor/create-subagent"
|
|
681
|
+
echo "Creating .cursor/skills-cursor/create-subagent/SKILL.md..."
|
|
682
|
+
cat << 'END_OF_FILE_CONTENT' > ".cursor/skills-cursor/create-subagent/SKILL.md"
|
|
322
683
|
---
|
|
684
|
+
name: create-subagent
|
|
685
|
+
description: >-
|
|
686
|
+
Create custom subagents for specialized AI tasks. Use when you want to create
|
|
687
|
+
a new type of subagent, set up task-specific agents, configure code reviewers,
|
|
688
|
+
debuggers, or domain-specific assistants with custom prompts.
|
|
689
|
+
disable-model-invocation: true
|
|
690
|
+
---
|
|
691
|
+
# Creating Custom Subagents
|
|
323
692
|
|
|
324
|
-
|
|
693
|
+
This skill guides you through creating custom subagents for Cursor. Subagents are specialized AI assistants that run in isolated contexts with custom system prompts.
|
|
325
694
|
|
|
326
|
-
|
|
327
|
-
- **Studio** updates the Working Draft; sync with the iframe and "Bake" use the same structure. Therefore, data passed to JsonPagesEngine (siteConfig, menuConfig, pages) must be compatible with what the editor modifies.
|
|
695
|
+
## When to Use Subagents
|
|
328
696
|
|
|
329
|
-
|
|
697
|
+
Subagents help you:
|
|
698
|
+
- **Preserve context** by isolating exploration from your main conversation
|
|
699
|
+
- **Specialize behavior** with focused system prompts for specific domains
|
|
700
|
+
- **Reuse configurations** across projects with user-level subagents
|
|
330
701
|
|
|
331
|
-
|
|
702
|
+
### Inferring from Context
|
|
703
|
+
|
|
704
|
+
If you have previous conversation context, infer the subagent's purpose and behavior from what was discussed. Create the subagent based on specialized tasks or workflows that emerged in the conversation.
|
|
332
705
|
|
|
333
|
-
##
|
|
706
|
+
## Subagent Locations
|
|
334
707
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
708
|
+
| Location | Scope | Priority |
|
|
709
|
+
|----------|-------|----------|
|
|
710
|
+
| `.cursor/agents/` | Current project | Higher |
|
|
711
|
+
| `~/.cursor/agents/` | All your projects | Lower |
|
|
339
712
|
|
|
340
|
-
|
|
713
|
+
When multiple subagents share the same name, the higher-priority location wins.
|
|
341
714
|
|
|
715
|
+
**Project subagents** (`.cursor/agents/`): Ideal for codebase-specific agents. Check into version control to share with your team.
|
|
716
|
+
|
|
717
|
+
**User subagents** (`~/.cursor/agents/`): Personal agents available across all your projects.
|
|
718
|
+
|
|
719
|
+
## Subagent File Format
|
|
720
|
+
|
|
721
|
+
Create a `.md` file with YAML frontmatter and a markdown body (the system prompt):
|
|
722
|
+
|
|
723
|
+
```markdown
|
|
724
|
+
---
|
|
725
|
+
name: code-reviewer
|
|
726
|
+
description: Reviews code for quality and best practices
|
|
342
727
|
---
|
|
343
728
|
|
|
344
|
-
|
|
729
|
+
You are a code reviewer. When invoked, analyze the code and provide
|
|
730
|
+
specific, actionable feedback on quality, security, and best practices.
|
|
731
|
+
```
|
|
732
|
+
|
|
733
|
+
### Required Fields
|
|
734
|
+
|
|
735
|
+
| Field | Description |
|
|
736
|
+
|-------|-------------|
|
|
737
|
+
| `name` | Unique identifier (lowercase letters and hyphens only) |
|
|
738
|
+
| `description` | When to delegate to this subagent (be specific!) |
|
|
739
|
+
|
|
740
|
+
## Writing Effective Descriptions
|
|
741
|
+
|
|
742
|
+
The description is **critical** - the AI uses it to decide when to delegate.
|
|
743
|
+
|
|
744
|
+
```yaml
|
|
745
|
+
# ❌ Too vague
|
|
746
|
+
description: Helps with code
|
|
747
|
+
|
|
748
|
+
# ✅ Specific and actionable
|
|
749
|
+
description: Expert code review specialist. Proactively reviews code for quality, security, and maintainability. Use immediately after writing or modifying code.
|
|
750
|
+
```
|
|
751
|
+
|
|
752
|
+
Include "use proactively" to encourage automatic delegation.
|
|
753
|
+
|
|
754
|
+
## Example Subagents
|
|
755
|
+
|
|
756
|
+
### Code Reviewer
|
|
345
757
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
758
|
+
```markdown
|
|
759
|
+
---
|
|
760
|
+
name: code-reviewer
|
|
761
|
+
description: Expert code review specialist. Proactively reviews code for quality, security, and maintainability. Use immediately after writing or modifying code.
|
|
762
|
+
---
|
|
350
763
|
|
|
351
|
-
|
|
764
|
+
You are a senior code reviewer ensuring high standards of code quality and security.
|
|
765
|
+
|
|
766
|
+
When invoked:
|
|
767
|
+
1. Run git diff to see recent changes
|
|
768
|
+
2. Focus on modified files
|
|
769
|
+
3. Begin review immediately
|
|
770
|
+
|
|
771
|
+
Review checklist:
|
|
772
|
+
- Code is clear and readable
|
|
773
|
+
- Functions and variables are well-named
|
|
774
|
+
- No duplicated code
|
|
775
|
+
- Proper error handling
|
|
776
|
+
- No exposed secrets or API keys
|
|
777
|
+
- Input validation implemented
|
|
778
|
+
- Good test coverage
|
|
779
|
+
- Performance considerations addressed
|
|
780
|
+
|
|
781
|
+
Provide feedback organized by priority:
|
|
782
|
+
- Critical issues (must fix)
|
|
783
|
+
- Warnings (should fix)
|
|
784
|
+
- Suggestions (consider improving)
|
|
785
|
+
|
|
786
|
+
Include specific examples of how to fix issues.
|
|
787
|
+
```
|
|
352
788
|
|
|
353
|
-
|
|
789
|
+
### Debugger
|
|
354
790
|
|
|
791
|
+
```markdown
|
|
355
792
|
---
|
|
793
|
+
name: debugger
|
|
794
|
+
description: Debugging specialist for errors, test failures, and unexpected behavior. Use proactively when encountering any issues.
|
|
795
|
+
---
|
|
796
|
+
|
|
797
|
+
You are an expert debugger specializing in root cause analysis.
|
|
798
|
+
|
|
799
|
+
When invoked:
|
|
800
|
+
1. Capture error message and stack trace
|
|
801
|
+
2. Identify reproduction steps
|
|
802
|
+
3. Isolate the failure location
|
|
803
|
+
4. Implement minimal fix
|
|
804
|
+
5. Verify solution works
|
|
805
|
+
|
|
806
|
+
Debugging process:
|
|
807
|
+
- Analyze error messages and logs
|
|
808
|
+
- Check recent code changes
|
|
809
|
+
- Form and test hypotheses
|
|
810
|
+
- Add strategic debug logging
|
|
811
|
+
- Inspect variable states
|
|
812
|
+
|
|
813
|
+
For each issue, provide:
|
|
814
|
+
- Root cause explanation
|
|
815
|
+
- Evidence supporting the diagnosis
|
|
816
|
+
- Specific code fix
|
|
817
|
+
- Testing approach
|
|
818
|
+
- Prevention recommendations
|
|
819
|
+
|
|
820
|
+
Focus on fixing the underlying issue, not the symptoms.
|
|
821
|
+
```
|
|
356
822
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
| Item | Action |
|
|
360
|
-
|------|--------|
|
|
361
|
-
| **Layout / Visuals** | View with `--local-*` variables, z-index ≤ 1, no naked utilities. |
|
|
362
|
-
| **Data (Shape)** | SiteConfig, MenuConfig, ThemeConfig, PageConfig as in Appendix A; JSON in `data/config` and `data/pages`. |
|
|
363
|
-
| **Capsules** | View + schema (with `ui:*`) + types + index; data schema extends BaseSectionData; array item with id. |
|
|
364
|
-
| **IDAC** | `data-jp-field` on editable scalar fields; `data-jp-item-id` and `data-jp-item-field` on array items. |
|
|
365
|
-
| **types.ts** | SectionComponentPropsMap (header with menu), augmentation, PageConfig, SiteConfig, MenuConfig, ThemeConfig. |
|
|
366
|
-
| **Registry** | All types mapped to component; registry type as in Appendix A. |
|
|
367
|
-
| **SECTION_SCHEMAS** | One entry per type (data schema); re-export base schemas. |
|
|
368
|
-
| **addSectionConfig** | addableSectionTypes, sectionTypeLabels, getDefaultSectionData. |
|
|
369
|
-
| **Config** | tenantId, registry, schemas, pages, siteConfig, themeConfig, menuConfig, themeCss, addSection. |
|
|
370
|
-
| **TOCC** | CSS overlay for `[data-jp-section-overlay]`, hover, selected, type label. |
|
|
823
|
+
### Data Scientist
|
|
371
824
|
|
|
825
|
+
```markdown
|
|
826
|
+
---
|
|
827
|
+
name: data-scientist
|
|
828
|
+
description: Data analysis expert for SQL queries, BigQuery operations, and data insights. Use proactively for data analysis tasks and queries.
|
|
372
829
|
---
|
|
373
830
|
|
|
374
|
-
|
|
831
|
+
You are a data scientist specializing in SQL and BigQuery analysis.
|
|
832
|
+
|
|
833
|
+
When invoked:
|
|
834
|
+
1. Understand the data analysis requirement
|
|
835
|
+
2. Write efficient SQL queries
|
|
836
|
+
3. Use BigQuery command line tools (bq) when appropriate
|
|
837
|
+
4. Analyze and summarize results
|
|
838
|
+
5. Present findings clearly
|
|
839
|
+
|
|
840
|
+
Key practices:
|
|
841
|
+
- Write optimized SQL queries with proper filters
|
|
842
|
+
- Use appropriate aggregations and joins
|
|
843
|
+
- Include comments explaining complex logic
|
|
844
|
+
- Format results for readability
|
|
845
|
+
- Provide data-driven recommendations
|
|
846
|
+
|
|
847
|
+
For each analysis:
|
|
848
|
+
- Explain the query approach
|
|
849
|
+
- Document any assumptions
|
|
850
|
+
- Highlight key findings
|
|
851
|
+
- Suggest next steps based on data
|
|
852
|
+
|
|
853
|
+
Always ensure queries are efficient and cost-effective.
|
|
854
|
+
```
|
|
375
855
|
|
|
376
|
-
|
|
377
|
-
- **Types and Code-Generation:** Appendix A (Core types, Tenant types, Schema contract, File paths, Integration checklist).
|
|
378
|
-
- **Admin:** JAP (Studio topology, Working Draft, Bake, overlay, Green Build).
|
|
856
|
+
## Subagent Creation Workflow
|
|
379
857
|
|
|
380
|
-
|
|
858
|
+
### Step 1: Decide the Scope
|
|
381
859
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
860
|
+
- **Project-level** (`.cursor/agents/`): For codebase-specific agents shared with team
|
|
861
|
+
- **User-level** (`~/.cursor/agents/`): For personal agents across all projects
|
|
862
|
+
|
|
863
|
+
### Step 2: Create the File
|
|
864
|
+
|
|
865
|
+
```bash
|
|
866
|
+
# For project-level
|
|
867
|
+
mkdir -p .cursor/agents
|
|
868
|
+
touch .cursor/agents/my-agent.md
|
|
869
|
+
|
|
870
|
+
# For user-level
|
|
871
|
+
mkdir -p ~/.cursor/agents
|
|
872
|
+
touch ~/.cursor/agents/my-agent.md
|
|
873
|
+
```
|
|
874
|
+
|
|
875
|
+
### Step 3: Define Configuration
|
|
876
|
+
|
|
877
|
+
Write the frontmatter with the required fields (`name` and `description`).
|
|
878
|
+
|
|
879
|
+
### Step 4: Write the System Prompt
|
|
880
|
+
|
|
881
|
+
The body becomes the system prompt. Be specific about:
|
|
882
|
+
- What the agent should do when invoked
|
|
883
|
+
- The workflow or process to follow
|
|
884
|
+
- Output format and structure
|
|
885
|
+
- Any constraints or guidelines
|
|
886
|
+
|
|
887
|
+
### Step 5: Test the Agent
|
|
888
|
+
|
|
889
|
+
Ask the AI to use your new agent:
|
|
890
|
+
|
|
891
|
+
```
|
|
892
|
+
Use the my-agent subagent to [task description]
|
|
893
|
+
```
|
|
387
894
|
|
|
388
|
-
|
|
895
|
+
## Best Practices
|
|
389
896
|
|
|
390
|
-
|
|
897
|
+
1. **Design focused subagents**: Each should excel at one specific task
|
|
898
|
+
2. **Write detailed descriptions**: Include trigger terms so the AI knows when to delegate
|
|
899
|
+
3. **Check into version control**: Share project subagents with your team
|
|
900
|
+
4. **Use proactive language**: Include "use proactively" in descriptions
|
|
391
901
|
|
|
902
|
+
## Troubleshooting
|
|
903
|
+
|
|
904
|
+
### Subagent Not Found
|
|
905
|
+
- Ensure file is in `.cursor/agents/` or `~/.cursor/agents/`
|
|
906
|
+
- Check file has `.md` extension
|
|
907
|
+
- Verify YAML frontmatter syntax is valid
|
|
908
|
+
|
|
909
|
+
END_OF_FILE_CONTENT
|
|
910
|
+
mkdir -p ".cursor/skills-cursor/jsonpages-tenant"
|
|
911
|
+
echo "Creating .cursor/skills-cursor/jsonpages-tenant/SKILL.md..."
|
|
912
|
+
cat << 'END_OF_FILE_CONTENT' > ".cursor/skills-cursor/jsonpages-tenant/SKILL.md"
|
|
392
913
|
---
|
|
914
|
+
name: jsonpages-tenant
|
|
915
|
+
description: Use when working on a JsonPages tenant, transforming the base tenant DNA into a branded tenant, adding or modifying tenant sections, maintaining schema-driven editability, or reasoning about what belongs to @jsonpages/core versus the tenant.
|
|
916
|
+
---
|
|
917
|
+
|
|
918
|
+
# JsonPages Tenant
|
|
919
|
+
|
|
920
|
+
Use this skill for work on the JsonPages ecosystem when the task involves:
|
|
921
|
+
|
|
922
|
+
- a tenant generated from the JsonPages CLI
|
|
923
|
+
- `@jsonpages/core`
|
|
924
|
+
- tenant sections/capsules
|
|
925
|
+
- `src/data/pages/**/*.json` or `src/data/config/*.json`
|
|
926
|
+
- schema-driven editing and inspector compatibility
|
|
927
|
+
- generator scripts that turn a base tenant into a branded tenant
|
|
928
|
+
|
|
929
|
+
Read code first. Treat documents as secondary unless they help interpret code that is otherwise ambiguous.
|
|
930
|
+
|
|
931
|
+
## Core Model
|
|
932
|
+
|
|
933
|
+
JsonPages has a hard split between `core` and `tenant`.
|
|
934
|
+
|
|
935
|
+
- `@jsonpages/core` owns routing, `/admin`, `/admin/preview`, preview stage, studio state, inspector/form factory, and shared engine behavior.
|
|
936
|
+
- The tenant owns sections, schemas, type augmentation, page/config JSON, theme/design layer, and local workflow scripts.
|
|
937
|
+
- The tenant does not implement the CMS. It implements the tenant protocol consumed by the engine.
|
|
938
|
+
|
|
939
|
+
In this ecosystem, code is the source of truth.
|
|
940
|
+
|
|
941
|
+
Compliance priority:
|
|
942
|
+
|
|
943
|
+
1. Data is bound correctly.
|
|
944
|
+
2. Schemas describe fields correctly.
|
|
945
|
+
3. Content is editable without breaking the inspector.
|
|
946
|
+
4. Tenant structure stays standardized.
|
|
947
|
+
5. Context-aware focus/highlight in the legacy admin is desirable but secondary.
|
|
948
|
+
|
|
949
|
+
## Canonical References
|
|
950
|
+
|
|
951
|
+
Use these local references when available:
|
|
952
|
+
|
|
953
|
+
- Base tenant DNA: `\\wsl.localhost\Ubuntu\home\dev\temp\alpha`
|
|
954
|
+
- Custom tenant reference: `\\wsl.localhost\Ubuntu\home\dev\temp\gptgiorgio`
|
|
955
|
+
- Core engine: `\\wsl.localhost\Ubuntu\home\dev\npm-jpcore\packages\core`
|
|
956
|
+
- Generator example: `\\wsl.localhost\Ubuntu\home\dev\temp\clonark\generate_olon.sh`
|
|
957
|
+
|
|
958
|
+
If these paths are missing, infer the same roles from the current workspace:
|
|
959
|
+
|
|
960
|
+
- base CLI-generated tenant
|
|
961
|
+
- branded tenant
|
|
962
|
+
- core package
|
|
963
|
+
- generator script
|
|
964
|
+
|
|
965
|
+
## Tenant Anatomy
|
|
966
|
+
|
|
967
|
+
Expect these files to move together:
|
|
968
|
+
|
|
969
|
+
- `src/components/<section>/View.tsx`
|
|
970
|
+
- `src/components/<section>/schema.ts`
|
|
971
|
+
- `src/components/<section>/types.ts`
|
|
972
|
+
- `src/components/<section>/index.ts`
|
|
973
|
+
- `src/lib/ComponentRegistry.tsx`
|
|
974
|
+
- `src/lib/schemas.ts`
|
|
975
|
+
- `src/lib/addSectionConfig.ts`
|
|
976
|
+
- `src/types.ts`
|
|
977
|
+
- `src/data/pages/**/*.json`
|
|
978
|
+
- `src/data/config/site.json`
|
|
979
|
+
- `src/data/config/theme.json`
|
|
980
|
+
- `src/data/config/menu.json`
|
|
981
|
+
|
|
982
|
+
Useful rule: if a section type changes, check all of the files above before concluding the task is done.
|
|
983
|
+
|
|
984
|
+
## What Good Work Looks Like
|
|
985
|
+
|
|
986
|
+
A good tenant change:
|
|
987
|
+
|
|
988
|
+
- stays inside tenant boundaries unless the issue is truly in `@jsonpages/core`
|
|
989
|
+
- keeps schema, defaults, registry, and type augmentation aligned
|
|
990
|
+
- preserves editability for strings, lists, nested objects, CTAs, and image fields
|
|
991
|
+
- uses `ImageSelectionSchema`-style image fields when the content is image-driven
|
|
992
|
+
- keeps page content JSON-first
|
|
993
|
+
|
|
994
|
+
A suspicious tenant change:
|
|
995
|
+
|
|
996
|
+
- patches the core to fix a tenant modeling problem
|
|
997
|
+
- adds visual complexity without data bindings
|
|
998
|
+
- introduces fields into JSON that are not represented in schema
|
|
999
|
+
- changes a section view without updating defaults or types
|
|
1000
|
+
- optimizes legacy context awareness at the expense of simpler, reliable editability
|
|
1001
|
+
|
|
1002
|
+
## Workflow 1: Base Tenant -> Branded Tenant
|
|
1003
|
+
|
|
1004
|
+
This is the primary workflow.
|
|
1005
|
+
|
|
1006
|
+
Goal:
|
|
1007
|
+
|
|
1008
|
+
- transform a CLI-generated base tenant into a branded tenant through a single generator script
|
|
1009
|
+
|
|
1010
|
+
Treat the generator script as procedural source of truth for the green build workflow.
|
|
1011
|
+
|
|
1012
|
+
When maintaining or authoring a generator:
|
|
1013
|
+
|
|
1014
|
+
1. Separate non-deterministic bootstrap from deterministic sync.
|
|
1015
|
+
2. Make explicit which files are managed output.
|
|
1016
|
+
3. Keep the script aligned with the current tenant code, not with stale docs.
|
|
1017
|
+
4. Preserve tenant protocol files: sections, schemas, registries, type augmentation, config JSON, assets, shims.
|
|
1018
|
+
5. Prefer deterministic local writes after any remote/bootstrap step.
|
|
1019
|
+
|
|
1020
|
+
Typical structure of a good generator:
|
|
1021
|
+
|
|
1022
|
+
- preflight checks
|
|
1023
|
+
- remote/bootstrap steps such as `shadcn` or external registries
|
|
1024
|
+
- deterministic creation/sync of tenant files
|
|
1025
|
+
- compatibility patches for known unstable upstream payloads
|
|
1026
|
+
- final validation commands
|
|
1027
|
+
|
|
1028
|
+
When asked to update a branded tenant generator:
|
|
1029
|
+
|
|
1030
|
+
1. Diff base tenant against branded tenant.
|
|
1031
|
+
2. Classify differences into:
|
|
1032
|
+
- intended branded output
|
|
1033
|
+
- reusable generator logic
|
|
1034
|
+
- accidental drift
|
|
1035
|
+
3. Encode only the reusable intended differences into the script.
|
|
1036
|
+
4. Keep the output reproducible from a fresh base tenant.
|
|
1037
|
+
|
|
1038
|
+
## Workflow 2: Add Or Change A Section
|
|
1039
|
+
|
|
1040
|
+
When adding a new section type:
|
|
1041
|
+
|
|
1042
|
+
1. Create `View.tsx`, `schema.ts`, `types.ts`, `index.ts`.
|
|
1043
|
+
2. Register the section in `src/lib/ComponentRegistry.tsx`.
|
|
1044
|
+
3. Register the schema in `src/lib/schemas.ts`.
|
|
1045
|
+
4. Add defaults and label in `src/lib/addSectionConfig.ts`.
|
|
1046
|
+
5. Extend `SectionComponentPropsMap` and module augmentation in `src/types.ts`.
|
|
1047
|
+
6. Add or update page JSON using the new section type.
|
|
1048
|
+
|
|
1049
|
+
When changing an existing section:
|
|
1050
|
+
|
|
1051
|
+
1. Read the section schema first.
|
|
1052
|
+
2. Read the page JSON using it.
|
|
1053
|
+
3. Check the view for `data-jp-field` usage and binding shape.
|
|
1054
|
+
4. Update defaults if the data shape changed.
|
|
1055
|
+
5. Verify the inspector still has a path to edit the content.
|
|
1056
|
+
|
|
1057
|
+
## Workflow 3: Images, Rich Content, Nested Routes
|
|
393
1058
|
|
|
394
|
-
|
|
1059
|
+
Images:
|
|
395
1060
|
|
|
396
|
-
-
|
|
397
|
-
-
|
|
398
|
-
-
|
|
399
|
-
- **Add Section:** Il tenant espone **AddSectionConfig** (tipi addabili, label, default data) così in Studio l'utente può aggiungere section dalla libreria.
|
|
400
|
-
- **Design tokens:** Le View usano variabili CSS (`--local-*`) e nessuna utility "nuda" (CIP) per coerenza e compatibilità con tema e overlay.
|
|
1061
|
+
- Prefer structured image objects compatible with tenant base schemas.
|
|
1062
|
+
- Assume the core supports image picking and upload flows.
|
|
1063
|
+
- The tenant is responsible for declaring image fields in schema and rendering them coherently.
|
|
401
1064
|
|
|
402
|
-
|
|
1065
|
+
Rich editorial content:
|
|
403
1066
|
|
|
1067
|
+
- Tiptap-style sections are tenant-level integrations.
|
|
1068
|
+
- Treat page JSON using `type: "tiptap"` as runtime usage examples, and section code as the real source of truth.
|
|
1069
|
+
|
|
1070
|
+
Nested routes:
|
|
1071
|
+
|
|
1072
|
+
- Files under `src/data/pages/**/*.json` may represent nested slugs.
|
|
1073
|
+
- Preserve slug/path consistency and do not replace file-based routing with manual lists.
|
|
1074
|
+
|
|
1075
|
+
## Decision Rules
|
|
1076
|
+
|
|
1077
|
+
Use `alpha` patterns when the task is about:
|
|
1078
|
+
|
|
1079
|
+
- tenant DNA
|
|
1080
|
+
- capability reference
|
|
1081
|
+
- baseline protocol shape
|
|
1082
|
+
- proving what the base system already supports
|
|
1083
|
+
|
|
1084
|
+
Use `gptgiorgio` patterns when the task is about:
|
|
1085
|
+
|
|
1086
|
+
- stronger branded frontend customization
|
|
1087
|
+
- richer domain-specific sections
|
|
1088
|
+
- image-heavy schema design
|
|
1089
|
+
- proving how far customization can go without changing the bootstrap
|
|
1090
|
+
|
|
1091
|
+
Do not treat `gptgiorgio` as canonical for legacy admin context awareness.
|
|
1092
|
+
|
|
1093
|
+
## Default Operating Procedure
|
|
1094
|
+
|
|
1095
|
+
When you receive a JsonPages tenant task:
|
|
1096
|
+
|
|
1097
|
+
1. Identify whether the problem belongs to `core`, tenant, or generator.
|
|
1098
|
+
2. Read the smallest code surface that proves it.
|
|
1099
|
+
3. Prefer fixing the tenant contract before touching visual polish.
|
|
1100
|
+
4. Keep generated and deterministic workflows reproducible.
|
|
1101
|
+
5. State assumptions when inferring intended branded output from examples.
|
|
1102
|
+
|
|
1103
|
+
END_OF_FILE_CONTENT
|
|
1104
|
+
mkdir -p ".cursor/skills-cursor/migrate-to-skills"
|
|
1105
|
+
echo "Creating .cursor/skills-cursor/migrate-to-skills/SKILL.md..."
|
|
1106
|
+
cat << 'END_OF_FILE_CONTENT' > ".cursor/skills-cursor/migrate-to-skills/SKILL.md"
|
|
1107
|
+
---
|
|
1108
|
+
name: migrate-to-skills
|
|
1109
|
+
description: >-
|
|
1110
|
+
Convert 'Applied intelligently' Cursor rules (.cursor/rules/*.mdc) and slash
|
|
1111
|
+
commands (.cursor/commands/*.md) to Agent Skills format (.cursor/skills/). Use
|
|
1112
|
+
when you want to migrate rules or commands to skills, convert .mdc rules to
|
|
1113
|
+
SKILL.md format, or consolidate commands into the skills directory.
|
|
1114
|
+
disable-model-invocation: true
|
|
404
1115
|
---
|
|
1116
|
+
# Migrate Rules and Slash Commands to Skills
|
|
1117
|
+
|
|
1118
|
+
Convert Cursor rules ("Applied intelligently") and slash commands to Agent Skills format.
|
|
1119
|
+
|
|
1120
|
+
**CRITICAL: Preserve the exact body content. Do not modify, reformat, or "improve" it - copy verbatim.**
|
|
1121
|
+
|
|
1122
|
+
## Locations
|
|
405
1123
|
|
|
406
|
-
|
|
1124
|
+
| Level | Source | Destination |
|
|
1125
|
+
|-------|--------|-------------|
|
|
1126
|
+
| Project | `{workspaceFolder}/**/.cursor/rules/*.mdc`, `{workspaceFolder}/.cursor/commands/*.md` |
|
|
1127
|
+
| User | `~/.cursor/commands/*.md` |
|
|
407
1128
|
|
|
408
|
-
|
|
1129
|
+
Notes:
|
|
1130
|
+
- Cursor rules inside the project can live in nested directories. Be thorough in your search and use glob patterns to find them.
|
|
1131
|
+
- Ignore anything in ~/.cursor/worktrees
|
|
1132
|
+
- Ignore anything in ~/.cursor/skills-cursor. This is reserved for Cursor's internal built-in skills and is managed automatically by the system.
|
|
409
1133
|
|
|
410
|
-
|
|
1134
|
+
## Finding Files to Migrate
|
|
411
1135
|
|
|
412
|
-
**
|
|
1136
|
+
**Rules**: Migrate if rule has a `description` but NO `globs` and NO `alwaysApply: true`.
|
|
1137
|
+
|
|
1138
|
+
**Commands**: Migrate all - they're plain markdown without frontmatter.
|
|
1139
|
+
|
|
1140
|
+
## Conversion Format
|
|
1141
|
+
|
|
1142
|
+
### Rules: .mdc → SKILL.md
|
|
1143
|
+
|
|
1144
|
+
```markdown
|
|
1145
|
+
# Before: .cursor/rules/my-rule.mdc
|
|
1146
|
+
---
|
|
1147
|
+
description: What this rule does
|
|
1148
|
+
globs:
|
|
1149
|
+
alwaysApply: false
|
|
1150
|
+
---
|
|
1151
|
+
# Title
|
|
1152
|
+
Body content...
|
|
1153
|
+
```
|
|
413
1154
|
|
|
1155
|
+
```markdown
|
|
1156
|
+
# After: .cursor/skills/my-rule/SKILL.md
|
|
1157
|
+
---
|
|
1158
|
+
name: my-rule
|
|
1159
|
+
description: What this rule does
|
|
414
1160
|
---
|
|
1161
|
+
# Title
|
|
1162
|
+
Body content...
|
|
1163
|
+
```
|
|
1164
|
+
|
|
1165
|
+
Changes: Add `name` field, remove `globs`/`alwaysApply`, keep body exactly.
|
|
415
1166
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
- **`src/data/config/site.json`** — SiteConfig (identity, pages[], header block, footer block).
|
|
419
|
-
- **`src/data/config/menu.json`** — MenuConfig (es. `main: MenuItem[]`).
|
|
420
|
-
- **`src/data/config/theme.json`** — ThemeConfig (tokens).
|
|
421
|
-
- **`src/data/pages/<slug>.json`** — PageConfig (slug, meta, sections[]). **Per creare una nuova pagina** basta aggiungere un file `<slug>.json` in `src/data/pages/`; lo slug del nome file diventa il path della pagina (es. `chi-siamo.json` → `/chi-siamo`).
|
|
422
|
-
- **`src/components/<sectionType>/`** — **Capsula piena:** View.tsx, schema.ts, types.ts, index.ts.
|
|
423
|
-
- **`src/lib/base-schemas.ts`** — BaseSectionData, BaseArrayItem, BaseSectionSettingsSchema.
|
|
424
|
-
- **`src/lib/schemas.ts`** — SECTION_SCHEMAS (aggregato degli schema data per tipo) + export SectionType.
|
|
425
|
-
- **`src/lib/ComponentRegistry.tsx`** — Registry tipizzato: `{ [K in SectionType]: React.FC<SectionComponentPropsMap[K]> }`.
|
|
426
|
-
- **`src/lib/addSectionConfig.ts`** — AddSectionConfig (addableSectionTypes, sectionTypeLabels, getDefaultSectionData).
|
|
427
|
-
- **`src/types.ts`** — SectionComponentPropsMap, PageConfig, SiteConfig, MenuConfig, ThemeConfig; **module augmentation** per SectionDataRegistry e SectionSettingsRegistry; re-export da `@olonjs/core`.
|
|
428
|
-
- **`src/App.tsx`** — Bootstrap: config (tenantId, registry, schemas, pages, siteConfig, themeConfig, menuConfig, themeCss, addSection); `<JsonPagesEngine config={config} />`.
|
|
429
|
-
- **CSS globale** — Include i selettori TOCC per overlay (hover/selected/type label).
|
|
1167
|
+
### Commands: .md → SKILL.md
|
|
430
1168
|
|
|
1169
|
+
```markdown
|
|
1170
|
+
# Before: .cursor/commands/commit.md
|
|
1171
|
+
# Commit current work
|
|
1172
|
+
Instructions here...
|
|
1173
|
+
```
|
|
1174
|
+
|
|
1175
|
+
```markdown
|
|
1176
|
+
# After: .cursor/skills/commit/SKILL.md
|
|
1177
|
+
---
|
|
1178
|
+
name: commit
|
|
1179
|
+
description: Commit current work with standardized message format
|
|
1180
|
+
disable-model-invocation: true
|
|
431
1181
|
---
|
|
1182
|
+
# Commit current work
|
|
1183
|
+
Instructions here...
|
|
1184
|
+
```
|
|
1185
|
+
|
|
1186
|
+
Changes: Add frontmatter with `name` (from filename), `description` (infer from content), and `disable-model-invocation: true`, keep body exactly.
|
|
1187
|
+
|
|
1188
|
+
**Note:** The `disable-model-invocation: true` field prevents the model from automatically invoking this skill. Slash commands are designed to be explicitly triggered by the user via the `/` menu, not automatically suggested by the model.
|
|
432
1189
|
|
|
433
|
-
##
|
|
1190
|
+
## Notes
|
|
1191
|
+
|
|
1192
|
+
- `name` must be lowercase with hyphens only
|
|
1193
|
+
- `description` is critical for skill discovery
|
|
1194
|
+
- Optionally delete originals after verifying migration works
|
|
1195
|
+
|
|
1196
|
+
### Migrate a Rule (.mdc → SKILL.md)
|
|
1197
|
+
|
|
1198
|
+
1. Read the rule file
|
|
1199
|
+
2. Extract the `description` from the frontmatter
|
|
1200
|
+
3. Extract the body content (everything after the closing `---` of the frontmatter)
|
|
1201
|
+
4. Create the skill directory: `.cursor/skills/{skill-name}/` (skill name = filename without .mdc)
|
|
1202
|
+
5. Write `SKILL.md` with new frontmatter (`name` and `description`) + the EXACT original body content (preserve all whitespace, formatting, code blocks verbatim)
|
|
1203
|
+
6. Delete the original rule file
|
|
1204
|
+
|
|
1205
|
+
### Migrate a Command (.md → SKILL.md)
|
|
1206
|
+
|
|
1207
|
+
1. Read the command file
|
|
1208
|
+
2. Extract description from the first heading (remove `#` prefix)
|
|
1209
|
+
3. Create the skill directory: `.cursor/skills/{skill-name}/` (skill name = filename without .md)
|
|
1210
|
+
4. Write `SKILL.md` with new frontmatter (`name`, `description`, and `disable-model-invocation: true`) + blank line + the EXACT original file content (preserve all whitespace, formatting, code blocks verbatim)
|
|
1211
|
+
5. Delete the original command file
|
|
434
1212
|
|
|
435
|
-
|
|
436
|
-
- **View:** Riceve `data` e `settings` (e `menu` per header). Non importa Zod. Usa **solo** variabili CSS per colori/raggi (es. `bg-[var(--local-bg)]`), sezione root con `z-index` ≤ 1.
|
|
437
|
-
- **IDAC (ICE):** Su ogni campo editabile in modo scalare: **`data-jp-field="<fieldKey>"`**. Su ogni item di array editabile: **`data-jp-item-id="<stableId>"`** e **`data-jp-item-field="<arrayKey>"`**. Così l'Inspector può legare selezione e form ai path corretti.
|
|
438
|
-
- **Schema:** Usa il vocabolario UI (ECIP): `.describe('ui:text')`, `ui:textarea`, `ui:select`, `ui:number`, `ui:list`, `ui:icon-picker`, **`ui:image-picker`** (vedi §3.1). Array di oggetti editabili: ogni oggetto con `id` (BaseArrayItem).
|
|
1213
|
+
**CRITICAL: Copy the body content character-for-character. Do not reformat, fix typos, or "improve" anything.**
|
|
439
1214
|
|
|
440
|
-
|
|
1215
|
+
## Workflow
|
|
441
1216
|
|
|
1217
|
+
If you have the Task tool available:
|
|
1218
|
+
DO NOT start to read all of the files yourself. That function should be delegated to the subagents. Your job is to dispatch the subagents for each category of files and wait for the results.
|
|
1219
|
+
|
|
1220
|
+
1. [ ] Create the skills directories if they don't exist (`.cursor/skills/` for project, `~/.cursor/skills/` for user)
|
|
1221
|
+
2. Dispatch three fast general purpose subagents (NOT explore) in parallel to do the following steps for project rules (pattern: `{workspaceFolder}/**/.cursor/rules/*.mdc`), user commands (pattern: `~/.cursor/commands/*.md`), and project commands (pattern: `{workspaceFolder}/**/.cursor/commands/*.md`):
|
|
1222
|
+
I. [ ] Find files to migrate in the given pattern
|
|
1223
|
+
II. [ ] For rules, check if it's an "applied intelligently" rule (has `description`, no `globs`, no `alwaysApply: true`). Commands are always migrated. DO NOT use the terminal to read files. Use the read tool.
|
|
1224
|
+
III. [ ] Make a list of files to migrate. If empty, done.
|
|
1225
|
+
IV. [ ] For each file, read it, then write the new skill file preserving the body content EXACTLY. DO NOT use the terminal to write these files. Use the edit tool.
|
|
1226
|
+
V. [ ] Delete the original file. DO NOT use the terminal to delete these files. Use the delete tool.
|
|
1227
|
+
VI. [ ] Return a list of all the skill files that were migrated along with the original file paths.
|
|
1228
|
+
3. [ ] Wait for all subagents to complete and summarize the results to the user. IMPORTANT: Make sure to let them know if they want to undo the migration, to ask you to.
|
|
1229
|
+
4. [ ] If the user asks you to undo the migration, do the opposite of the above steps to restore the original files.
|
|
1230
|
+
|
|
1231
|
+
|
|
1232
|
+
If you don't have the Task tool available:
|
|
1233
|
+
1. [ ] Create the skills directories if they don't exist (`.cursor/skills/` for project, `~/.cursor/skills/` for user)
|
|
1234
|
+
2. [ ] Find files to migrate in both project (`.cursor/`) and user (`~/.cursor/`) directories
|
|
1235
|
+
3. [ ] For rules, check if it's an "applied intelligently" rule (has `description`, no `globs`, no `alwaysApply: true`). Commands are always migrated. DO NOT use the terminal to read files. Use the read tool.
|
|
1236
|
+
4. [ ] Make a list of files to migrate. If empty, done.
|
|
1237
|
+
5. [ ] For each file, read it, then write the new skill file preserving the body content EXACTLY. DO NOT use the terminal to write these files. Use the edit tool.
|
|
1238
|
+
6. [ ] Delete the original file. DO NOT use the terminal to delete these files. Use the delete tool.
|
|
1239
|
+
7. [ ] Summarize the results to the user. IMPORTANT: Make sure to let them know if they want to undo the migration, to ask you to.
|
|
1240
|
+
8. [ ] If the user asks you to undo the migration, do the opposite of the above steps to restore the original files.
|
|
1241
|
+
|
|
1242
|
+
END_OF_FILE_CONTENT
|
|
1243
|
+
mkdir -p ".cursor/skills-cursor/olonjs"
|
|
1244
|
+
echo "Creating .cursor/skills-cursor/olonjs/SKILL.md..."
|
|
1245
|
+
cat << 'END_OF_FILE_CONTENT' > ".cursor/skills-cursor/olonjs/SKILL.md"
|
|
1246
|
+
---
|
|
1247
|
+
name: olonjs-tenant
|
|
1248
|
+
description: Use when working on a OlonJS tenant, transforming the base tenant DNA into a branded tenant, adding or modifying tenant sections, maintaining schema-driven editability, or reasoning about what belongs to @olonjs/core versus the tenant.
|
|
442
1249
|
---
|
|
443
1250
|
|
|
444
|
-
|
|
1251
|
+
# OlonJS Tenant
|
|
445
1252
|
|
|
446
|
-
|
|
1253
|
+
Use this skill for work on the OlonJS ecosystem when the task involves:
|
|
447
1254
|
|
|
448
|
-
|
|
1255
|
+
- a tenant generated from the OlonJS CLI
|
|
1256
|
+
- `@olonjs/core`
|
|
1257
|
+
- tenant sections/capsules
|
|
1258
|
+
- `src/data/pages/**/*.json` or `src/data/config/*.json`
|
|
1259
|
+
- schema-driven editing and inspector compatibility
|
|
1260
|
+
- generator scripts that turn a base tenant into a branded tenant
|
|
449
1261
|
|
|
450
|
-
|
|
451
|
-
- Lo **schema di questo oggetto** (il sub-schema) va marcato con **`.describe('ui:image-picker')`**. Il Form Factory riconosce `ui:image-picker` solo su **ZodObject** (schema oggetto), non su campi stringa.
|
|
1262
|
+
Read code first. Treat documents as secondary unless they help interpret code that is otherwise ambiguous.
|
|
452
1263
|
|
|
453
|
-
|
|
1264
|
+
## Architecture Specifications
|
|
454
1265
|
|
|
455
|
-
|
|
1266
|
+
Use this document as the architectural laws for each tenant, compliancy will be tested against these specs:
|
|
456
1267
|
|
|
457
|
-
|
|
458
|
-
import { z } from 'zod';
|
|
459
|
-
import { BaseSectionData } from '@/lib/base-schemas';
|
|
1268
|
+
- `\\wsl.localhost\Ubuntu\home\dev\npm-jpcore\specs\olonjsSpecs_V.1.3.md`
|
|
460
1269
|
|
|
461
|
-
const ImageSelectionSchema = z
|
|
462
|
-
.object({
|
|
463
|
-
url: z.string(),
|
|
464
|
-
alt: z.string().optional(),
|
|
465
|
-
})
|
|
466
|
-
.describe('ui:image-picker');
|
|
467
1270
|
|
|
468
|
-
export const ImageBreakSchema = BaseSectionData.extend({
|
|
469
|
-
label: z.string().optional().describe('ui:text'),
|
|
470
|
-
image: ImageSelectionSchema.default({ url: '', alt: '' }),
|
|
471
|
-
caption: z.string().optional().describe('ui:textarea'),
|
|
472
|
-
});
|
|
473
|
-
```
|
|
474
1271
|
|
|
475
|
-
- **ImageSelectionSchema** è un `z.object({ url, alt })` con **`.describe('ui:image-picker')`** sull'oggetto.
|
|
476
|
-
- Il campo **`image`** nella section data usa quel schema (con default) così l'Inspector mostra il widget Image Picker per `image`.
|
|
477
1272
|
|
|
478
|
-
|
|
1273
|
+
## Core Model
|
|
1274
|
+
|
|
1275
|
+
OlonJS has a hard split between `core` and `tenant`.
|
|
1276
|
+
|
|
1277
|
+
- `@olonjs/core` owns routing, `/admin`, `/admin/preview`, preview stage, studio state, inspector/form factory, and shared engine behavior.
|
|
1278
|
+
- The tenant owns sections, schemas, type augmentation, page/config JSON, theme/design layer, and local workflow scripts.
|
|
1279
|
+
- The tenant does not implement the CMS. It implements the tenant protocol consumed by the engine.
|
|
1280
|
+
|
|
1281
|
+
In this ecosystem, code is the source of truth.
|
|
1282
|
+
|
|
1283
|
+
Compliance priority:
|
|
1284
|
+
|
|
1285
|
+
1. Data is bound correctly.
|
|
1286
|
+
2. Schemas describe fields correctly.
|
|
1287
|
+
3. Content is editable without breaking the inspector.
|
|
1288
|
+
4. Tenant structure stays standardized.
|
|
1289
|
+
5. Context-aware focus/highlight in the legacy admin is desirable but secondary.
|
|
1290
|
+
|
|
1291
|
+
## Canonical References
|
|
1292
|
+
|
|
1293
|
+
Use these local references when available:
|
|
1294
|
+
|
|
1295
|
+
- Base tenant DNA: `\\wsl.localhost\Ubuntu\home\dev\temp\alpha`
|
|
1296
|
+
- Custom tenant reference: `\\wsl.localhost\Ubuntu\home\dev\temp\gptgiorgio`
|
|
1297
|
+
- Core engine: `\\wsl.localhost\Ubuntu\home\dev\npm-jpcore\packages\core`
|
|
1298
|
+
- Generator example: `\\wsl.localhost\Ubuntu\home\dev\temp\clonark\generate_olon.sh`
|
|
1299
|
+
|
|
1300
|
+
If these paths are missing, infer the same roles from the current workspace:
|
|
1301
|
+
|
|
1302
|
+
- base CLI-generated tenant
|
|
1303
|
+
- branded tenant
|
|
1304
|
+
- core package
|
|
1305
|
+
- generator script
|
|
1306
|
+
|
|
1307
|
+
## Tenant Anatomy
|
|
1308
|
+
|
|
1309
|
+
Expect these files to move together:
|
|
1310
|
+
|
|
1311
|
+
- `src/components/<section>/View.tsx`
|
|
1312
|
+
- `src/components/<section>/schema.ts`
|
|
1313
|
+
- `src/components/<section>/types.ts`
|
|
1314
|
+
- `src/components/<section>/index.ts`
|
|
1315
|
+
- `src/lib/ComponentRegistry.tsx`
|
|
1316
|
+
- `src/lib/schemas.ts`
|
|
1317
|
+
- `src/lib/addSectionConfig.ts`
|
|
1318
|
+
- `src/types.ts`
|
|
1319
|
+
- `src/data/pages/**/*.json`
|
|
1320
|
+
- `src/data/config/site.json`
|
|
1321
|
+
- `src/data/config/theme.json`
|
|
1322
|
+
- `src/data/config/menu.json`
|
|
1323
|
+
|
|
1324
|
+
Useful rule: if a section type changes, check all of the files above before concluding the task is done.
|
|
1325
|
+
|
|
1326
|
+
## What Good Work Looks Like
|
|
1327
|
+
|
|
1328
|
+
A good tenant change:
|
|
1329
|
+
|
|
1330
|
+
- stays inside tenant boundaries unless the issue is truly in `@olonjs/core`
|
|
1331
|
+
- keeps schema, defaults, registry, and type augmentation aligned
|
|
1332
|
+
- preserves editability for strings, lists, nested objects, CTAs, and image fields
|
|
1333
|
+
- uses `ImageSelectionSchema`-style image fields when the content is image-driven
|
|
1334
|
+
- keeps page content JSON-first
|
|
1335
|
+
|
|
1336
|
+
A suspicious tenant change:
|
|
1337
|
+
|
|
1338
|
+
- patches the core to fix a tenant modeling problem
|
|
1339
|
+
- adds visual complexity without data bindings
|
|
1340
|
+
- introduces fields into JSON that are not represented in schema
|
|
1341
|
+
- changes a section view without updating defaults or types
|
|
1342
|
+
- optimizes legacy context awareness at the expense of simpler, reliable editability
|
|
1343
|
+
|
|
1344
|
+
## Workflow 1: Base Tenant -> Branded Tenant
|
|
1345
|
+
|
|
1346
|
+
This is the primary workflow.
|
|
1347
|
+
|
|
1348
|
+
Goal:
|
|
1349
|
+
|
|
1350
|
+
- transform a CLI-generated base tenant into a branded tenant through a single generator script
|
|
1351
|
+
|
|
1352
|
+
Treat the generator script as procedural source of truth for the green build workflow.
|
|
1353
|
+
|
|
1354
|
+
When maintaining or authoring a generator:
|
|
1355
|
+
|
|
1356
|
+
1. Separate non-deterministic bootstrap from deterministic sync.
|
|
1357
|
+
2. Make explicit which files are managed output.
|
|
1358
|
+
3. Keep the script aligned with the current tenant code, not with stale docs.
|
|
1359
|
+
4. Preserve tenant protocol files: sections, schemas, registries, type augmentation, config JSON, assets, shims.
|
|
1360
|
+
5. Prefer deterministic local writes after any remote/bootstrap step.
|
|
1361
|
+
|
|
1362
|
+
Typical structure of a good generator:
|
|
1363
|
+
|
|
1364
|
+
- preflight checks
|
|
1365
|
+
- remote/bootstrap steps such as `shadcn` or external registries
|
|
1366
|
+
- deterministic creation/sync of tenant files
|
|
1367
|
+
- compatibility patches for known unstable upstream payloads
|
|
1368
|
+
- final validation commands
|
|
1369
|
+
|
|
1370
|
+
When asked to update a branded tenant generator:
|
|
1371
|
+
|
|
1372
|
+
1. Diff base tenant against branded tenant.
|
|
1373
|
+
2. Classify differences into:
|
|
1374
|
+
- intended branded output
|
|
1375
|
+
- reusable generator logic
|
|
1376
|
+
- accidental drift
|
|
1377
|
+
3. Encode only the reusable intended differences into the script.
|
|
1378
|
+
4. Keep the output reproducible from a fresh base tenant.
|
|
1379
|
+
|
|
1380
|
+
## Workflow 2: Add Or Change A Section
|
|
1381
|
+
|
|
1382
|
+
When adding a new section type:
|
|
1383
|
+
|
|
1384
|
+
1. Create `View.tsx`, `schema.ts`, `types.ts`, `index.ts`.
|
|
1385
|
+
2. Register the section in `src/lib/ComponentRegistry.tsx`.
|
|
1386
|
+
3. Register the schema in `src/lib/schemas.ts`.
|
|
1387
|
+
4. Add defaults and label in `src/lib/addSectionConfig.ts`.
|
|
1388
|
+
5. Extend `SectionComponentPropsMap` and module augmentation in `src/types.ts`.
|
|
1389
|
+
6. Add or update page JSON using the new section type.
|
|
479
1390
|
|
|
480
|
-
|
|
481
|
-
- Sul nodo che rappresenta l'immagine (es. il `<img>` o un wrapper): **`data-jp-field="image"`** così il click in Stage lega l'Inspector al campo `image`.
|
|
482
|
-
- Altri campi editabili (caption, label) con **`data-jp-field="caption"`** e **`data-jp-field="label"`** dove appropriato.
|
|
1391
|
+
When changing an existing section:
|
|
483
1392
|
|
|
484
|
-
|
|
1393
|
+
1. Read the section schema first.
|
|
1394
|
+
2. Read the page JSON using it.
|
|
1395
|
+
3. Check the view for `data-jp-field` usage and binding shape.
|
|
1396
|
+
4. Update defaults if the data shape changed.
|
|
1397
|
+
5. Verify the inspector still has a path to edit the content.
|
|
485
1398
|
|
|
486
|
-
|
|
1399
|
+
## Workflow 3: Images, Rich Content, Nested Routes
|
|
487
1400
|
|
|
488
|
-
|
|
489
|
-
- **Non** dimenticare `data-jp-field="image"` sul nodo corrispondente nel DOM, altrimenti il binding Inspector ↔ Stage non funziona per quel campo.
|
|
1401
|
+
Images:
|
|
490
1402
|
|
|
1403
|
+
- Prefer structured image objects compatible with tenant base schemas.
|
|
1404
|
+
- Assume the core supports image picking and upload flows.
|
|
1405
|
+
- The tenant is responsible for declaring image fields in schema and rendering them coherently.
|
|
1406
|
+
|
|
1407
|
+
Rich editorial content:
|
|
1408
|
+
|
|
1409
|
+
- Tiptap-style sections are tenant-level integrations.
|
|
1410
|
+
- Treat page JSON using `type: "tiptap"` as runtime usage examples, and section code as the real source of truth.
|
|
1411
|
+
|
|
1412
|
+
Nested routes:
|
|
1413
|
+
|
|
1414
|
+
- Files under `src/data/pages/**/*.json` may represent nested slugs.
|
|
1415
|
+
- Preserve slug/path consistency and do not replace file-based routing with manual lists.
|
|
1416
|
+
|
|
1417
|
+
## Decision Rules
|
|
1418
|
+
|
|
1419
|
+
Use `alpha` patterns when the task is about:
|
|
1420
|
+
|
|
1421
|
+
- tenant DNA
|
|
1422
|
+
- capability reference
|
|
1423
|
+
- baseline protocol shape
|
|
1424
|
+
- proving what the base system already supports
|
|
1425
|
+
|
|
1426
|
+
Use `gptgiorgio` patterns when the task is about:
|
|
1427
|
+
|
|
1428
|
+
- stronger branded frontend customization
|
|
1429
|
+
- richer domain-specific sections
|
|
1430
|
+
- image-heavy schema design
|
|
1431
|
+
- proving how far customization can go without changing the bootstrap
|
|
1432
|
+
|
|
1433
|
+
Do not treat `gptgiorgio` as canonical for legacy admin context awareness.
|
|
1434
|
+
|
|
1435
|
+
## Default Operating Procedure
|
|
1436
|
+
|
|
1437
|
+
When you receive a OlonJS tenant task:
|
|
1438
|
+
|
|
1439
|
+
1. Identify whether the problem belongs to `core`, tenant, or generator.
|
|
1440
|
+
2. Read the smallest code surface that proves it.
|
|
1441
|
+
3. Prefer fixing the tenant contract before touching visual polish.
|
|
1442
|
+
4. Keep generated and deterministic workflows reproducible.
|
|
1443
|
+
5. State assumptions when inferring intended branded output from examples.
|
|
1444
|
+
|
|
1445
|
+
END_OF_FILE_CONTENT
|
|
1446
|
+
# SKIP: .cursor/skills-cursor/olonjs/SKILL.md:Zone.Identifier is binary and cannot be embedded as text.
|
|
1447
|
+
mkdir -p ".cursor/skills-cursor/shell"
|
|
1448
|
+
echo "Creating .cursor/skills-cursor/shell/SKILL.md..."
|
|
1449
|
+
cat << 'END_OF_FILE_CONTENT' > ".cursor/skills-cursor/shell/SKILL.md"
|
|
1450
|
+
---
|
|
1451
|
+
name: shell
|
|
1452
|
+
description: >-
|
|
1453
|
+
Runs the rest of a /shell request as a literal shell command. Use only when
|
|
1454
|
+
the user explicitly invokes /shell and wants the following text executed
|
|
1455
|
+
directly in the terminal.
|
|
1456
|
+
disable-model-invocation: true
|
|
491
1457
|
---
|
|
1458
|
+
# Run Shell Commands
|
|
1459
|
+
|
|
1460
|
+
Use this skill only when the user explicitly invokes `/shell`.
|
|
492
1461
|
|
|
493
|
-
##
|
|
1462
|
+
## Behavior
|
|
494
1463
|
|
|
495
|
-
|
|
496
|
-
|
|
1464
|
+
1. Treat all user text after the `/shell` invocation as the literal shell command to run.
|
|
1465
|
+
2. Execute that command immediately with the terminal tool.
|
|
1466
|
+
3. Do not rewrite, explain, or "improve" the command before running it.
|
|
1467
|
+
4. Do not inspect the repository first unless the command itself requires repository context.
|
|
1468
|
+
5. If the user invokes `/shell` without any following text, ask them which command to run.
|
|
497
1469
|
|
|
498
|
-
|
|
1470
|
+
## Response
|
|
499
1471
|
|
|
1472
|
+
- Run the command first.
|
|
1473
|
+
- Then briefly report the exit status and any important stdout or stderr.
|
|
1474
|
+
|
|
1475
|
+
END_OF_FILE_CONTENT
|
|
1476
|
+
mkdir -p ".cursor/skills-cursor/update-cursor-settings"
|
|
1477
|
+
echo "Creating .cursor/skills-cursor/update-cursor-settings/SKILL.md..."
|
|
1478
|
+
cat << 'END_OF_FILE_CONTENT' > ".cursor/skills-cursor/update-cursor-settings/SKILL.md"
|
|
1479
|
+
---
|
|
1480
|
+
name: update-cursor-settings
|
|
1481
|
+
description: >-
|
|
1482
|
+
Modify Cursor/VSCode user settings in settings.json. Use when you want to
|
|
1483
|
+
change editor settings, preferences, configuration, themes, font size, tab
|
|
1484
|
+
size, format on save, auto save, keybindings, or any settings.json values.
|
|
500
1485
|
---
|
|
1486
|
+
# Updating Cursor Settings
|
|
1487
|
+
|
|
1488
|
+
This skill guides you through modifying Cursor/VSCode user settings. Use this when you want to change editor settings, preferences, configuration, themes, keybindings, or any `settings.json` values.
|
|
1489
|
+
|
|
1490
|
+
## Settings File Location
|
|
501
1491
|
|
|
502
|
-
|
|
1492
|
+
| OS | Path |
|
|
1493
|
+
|----|------|
|
|
1494
|
+
| macOS | ~/Library/Application Support/Cursor/User/settings.json |
|
|
1495
|
+
| Linux | ~/.config/Cursor/User/settings.json |
|
|
1496
|
+
| Windows | %APPDATA%\Cursor\User\settings.json |
|
|
1497
|
+
|
|
1498
|
+
## Before Modifying Settings
|
|
1499
|
+
|
|
1500
|
+
1. **Read the existing settings file** to understand current configuration
|
|
1501
|
+
2. **Preserve existing settings** - only add/modify what the user requested
|
|
1502
|
+
3. **Validate JSON syntax** before writing to avoid breaking the editor
|
|
1503
|
+
|
|
1504
|
+
## Modifying Settings
|
|
1505
|
+
|
|
1506
|
+
### Step 1: Read Current Settings
|
|
1507
|
+
|
|
1508
|
+
```typescript
|
|
1509
|
+
// Read the settings file first
|
|
1510
|
+
const settingsPath = "~/Library/Application Support/Cursor/User/settings.json";
|
|
1511
|
+
// Use the Read tool to get current contents
|
|
1512
|
+
```
|
|
1513
|
+
|
|
1514
|
+
### Step 2: Identify the Setting to Change
|
|
1515
|
+
|
|
1516
|
+
Common setting categories:
|
|
1517
|
+
- **Editor**: `editor.fontSize`, `editor.tabSize`, `editor.wordWrap`, `editor.formatOnSave`
|
|
1518
|
+
- **Workbench**: `workbench.colorTheme`, `workbench.iconTheme`, `workbench.sideBar.location`
|
|
1519
|
+
- **Files**: `files.autoSave`, `files.exclude`, `files.associations`
|
|
1520
|
+
- **Terminal**: `terminal.integrated.fontSize`, `terminal.integrated.shell.*`
|
|
1521
|
+
- **Cursor-specific**: Settings prefixed with `cursor.` or `aipopup.`
|
|
1522
|
+
|
|
1523
|
+
### Step 3: Update the Setting
|
|
1524
|
+
|
|
1525
|
+
When modifying settings.json:
|
|
1526
|
+
1. Parse the existing JSON (handle comments - VSCode settings support JSON with comments)
|
|
1527
|
+
2. Add or update the requested setting
|
|
1528
|
+
3. Preserve all other existing settings
|
|
1529
|
+
4. Write back with proper formatting (2-space indentation)
|
|
1530
|
+
|
|
1531
|
+
### Example: Changing Font Size
|
|
1532
|
+
|
|
1533
|
+
If user says "make the font bigger":
|
|
1534
|
+
|
|
1535
|
+
```json
|
|
1536
|
+
{
|
|
1537
|
+
"editor.fontSize": 16
|
|
1538
|
+
}
|
|
1539
|
+
```
|
|
1540
|
+
|
|
1541
|
+
### Example: Enabling Format on Save
|
|
1542
|
+
|
|
1543
|
+
If user says "format my code when I save":
|
|
1544
|
+
|
|
1545
|
+
```json
|
|
1546
|
+
{
|
|
1547
|
+
"editor.formatOnSave": true
|
|
1548
|
+
}
|
|
1549
|
+
```
|
|
503
1550
|
|
|
504
|
-
|
|
505
|
-
- **ComponentRegistry:** Ogni chiave di SectionType ha il componente corrispondente; tipo: `{ [K in SectionType]: React.FC<SectionComponentPropsMap[K]> }`.
|
|
506
|
-
- **SECTION_SCHEMAS:** Ogni chiave di SectionType ha lo **schema Zod della data** (stesso ordine del registry). Base schemas re-exportati da base-schemas.ts.
|
|
507
|
-
- **addSectionConfig:** addableSectionTypes (solo i tipi che l'utente può aggiungere dalla libreria), sectionTypeLabels, getDefaultSectionData(type) che restituisce `data` valido per quello schema.
|
|
1551
|
+
### Example: Changing Theme
|
|
508
1552
|
|
|
509
|
-
|
|
1553
|
+
If user says "use dark theme" or "change my theme":
|
|
510
1554
|
|
|
511
|
-
|
|
1555
|
+
```json
|
|
1556
|
+
{
|
|
1557
|
+
"workbench.colorTheme": "Default Dark Modern"
|
|
1558
|
+
}
|
|
1559
|
+
```
|
|
512
1560
|
|
|
513
|
-
##
|
|
1561
|
+
## Important Notes
|
|
514
1562
|
|
|
515
|
-
|
|
516
|
-
- `[data-jp-section-overlay]` copra la section, `pointer-events: none`, z-index alto (es. 9999).
|
|
517
|
-
- Hover e selected siano visibili (bordo tratteggiato / pieno, eventuale tint).
|
|
518
|
-
- Il type label (es. `[data-jp-section-overlay] > div`) sia posizionato e visibile su hover/selected.
|
|
1563
|
+
1. **JSON with Comments**: VSCode/Cursor settings.json supports comments (`//` and `/* */`). When reading, be aware comments may exist. When writing, preserve comments if possible.
|
|
519
1564
|
|
|
520
|
-
|
|
1565
|
+
2. **Restart May Be Required**: Some settings take effect immediately, others require reloading the window or restarting Cursor. Inform the user if a restart is needed.
|
|
521
1566
|
|
|
522
|
-
|
|
1567
|
+
3. **Backup**: For significant changes, consider mentioning the user can undo via Ctrl/Cmd+Z in the settings file or by reverting git changes if tracked.
|
|
523
1568
|
|
|
524
|
-
|
|
1569
|
+
4. **Workspace vs User Settings**:
|
|
1570
|
+
- User settings (what this skill covers): Apply globally to all projects
|
|
1571
|
+
- Workspace settings (`.vscode/settings.json`): Apply only to the current project
|
|
525
1572
|
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
| Cosa | Azione |
|
|
529
|
-
|------|--------|
|
|
530
|
-
| **Layout / grafico** | View con variabili `--local-*`, z-index ≤ 1, nessuna utility naked. |
|
|
531
|
-
| **Dati (forma)** | SiteConfig, MenuConfig, ThemeConfig, PageConfig come in Appendix A; JSON in `data/config` e `data/pages`. |
|
|
532
|
-
| **Nuova pagina** | Aggiungere un file `<slug>.json` in `src/data/pages/` (lo slug diventa il path della pagina). |
|
|
533
|
-
| **Capsule** | View + schema (con ui:*) + types + index; data schema estende BaseSectionData; array item con id. |
|
|
534
|
-
| **IDAC** | data-jp-field su campi scalari editabili; data-jp-item-id e data-jp-item-field su item di array. |
|
|
535
|
-
| **Image Picker** | Campo immagine = oggetto `{ url, alt? }` con sub-schema `.describe('ui:image-picker')`; View con `resolveAssetUrl` e `data-jp-field="image"`. Esempio: `image-break`. |
|
|
536
|
-
| **types.ts** | SectionComponentPropsMap (header con menu), augmentation, PageConfig, SiteConfig, MenuConfig, ThemeConfig. |
|
|
537
|
-
| **Registry** | Tutti i tipi mappati al componente; tipo registry come in Appendix A. |
|
|
538
|
-
| **SECTION_SCHEMAS** | Un entry per tipo (schema data); re-export base schemas. |
|
|
539
|
-
| **addSectionConfig** | addableSectionTypes, sectionTypeLabels, getDefaultSectionData. |
|
|
540
|
-
| **Config** | tenantId, registry, schemas, pages, siteConfig, themeConfig, menuConfig, themeCss, addSection. |
|
|
541
|
-
| **TOCC** | CSS overlay per [data-jp-section-overlay], hover, selected, type label. |
|
|
1573
|
+
5. **Commit Attribution**: When the user asks about commit attribution, clarify whether they want to edit the **CLI agent** or the **IDE agent**. For the CLI agent, modify `~/.cursor/cli-config.json`. For the IDE agent, it is controlled from the UI at **Cursor Settings > Agent > Attribution** (not settings.json).
|
|
542
1574
|
|
|
543
|
-
|
|
1575
|
+
## Common User Requests → Settings
|
|
544
1576
|
|
|
545
|
-
|
|
1577
|
+
| User Request | Setting |
|
|
1578
|
+
|--------------|---------|
|
|
1579
|
+
| "bigger/smaller font" | `editor.fontSize` |
|
|
1580
|
+
| "change tab size" | `editor.tabSize` |
|
|
1581
|
+
| "format on save" | `editor.formatOnSave` |
|
|
1582
|
+
| "word wrap" | `editor.wordWrap` |
|
|
1583
|
+
| "change theme" | `workbench.colorTheme` |
|
|
1584
|
+
| "hide minimap" | `editor.minimap.enabled` |
|
|
1585
|
+
| "auto save" | `files.autoSave` |
|
|
1586
|
+
| "line numbers" | `editor.lineNumbers` |
|
|
1587
|
+
| "bracket matching" | `editor.bracketPairColorization.enabled` |
|
|
1588
|
+
| "cursor style" | `editor.cursorStyle` |
|
|
1589
|
+
| "smooth scrolling" | `editor.smoothScrolling` |
|
|
546
1590
|
|
|
547
|
-
|
|
548
|
-
- **Tipi e code-generation:** Appendix A (Core types, Tenant types, Schema contract, File paths, Integration checklist).
|
|
549
|
-
- **Admin:** JAP (Studio topology, Working Draft, Bake, overlay, Green Build).
|
|
1591
|
+
## Workflow
|
|
550
1592
|
|
|
551
|
-
|
|
1593
|
+
1. Read ~/Library/Application Support/Cursor/User/settings.json
|
|
1594
|
+
2. Parse the JSON content
|
|
1595
|
+
3. Add/modify the requested setting(s)
|
|
1596
|
+
4. Write the updated JSON back to the file
|
|
1597
|
+
5. Inform the user the setting has been changed and whether a reload is needed
|
|
552
1598
|
|
|
553
1599
|
END_OF_FILE_CONTENT
|
|
554
|
-
mkdir -p "docs/ver"
|
|
555
1600
|
echo "Creating index.html..."
|
|
556
1601
|
cat << 'END_OF_FILE_CONTENT' > "index.html"
|
|
557
1602
|
<!DOCTYPE html>
|
|
@@ -585,7 +1630,7 @@ cat << 'END_OF_FILE_CONTENT' > "package.json"
|
|
|
585
1630
|
"dev:clean": "vite --force",
|
|
586
1631
|
"prebuild": "node scripts/sync-pages-to-public.mjs",
|
|
587
1632
|
"build": "tsc && vite build",
|
|
588
|
-
"dist": "bash ./src2Code.sh --template alpha src vercel.json index.html vite.config.ts scripts
|
|
1633
|
+
"dist": "bash ./src2Code.sh --template alpha src .cursor vercel.json index.html vite.config.ts scripts specs package.json",
|
|
589
1634
|
"preview": "vite preview",
|
|
590
1635
|
"bake:email": "tsx scripts/bake-email.tsx",
|
|
591
1636
|
"bakemail": "npm run bake:email --",
|
|
@@ -596,7 +1641,7 @@ cat << 'END_OF_FILE_CONTENT' > "package.json"
|
|
|
596
1641
|
"@tiptap/extension-link": "^2.11.5",
|
|
597
1642
|
"@tiptap/react": "^2.11.5",
|
|
598
1643
|
"@tiptap/starter-kit": "^2.11.5",
|
|
599
|
-
"@olonjs/core": "^1.0.
|
|
1644
|
+
"@olonjs/core": "^1.0.77",
|
|
600
1645
|
"clsx": "^2.1.1",
|
|
601
1646
|
"lucide-react": "^0.474.0",
|
|
602
1647
|
"react": "^19.0.0",
|
|
@@ -916,6 +1961,615 @@ fs.cpSync(sourceDir, targetDir, { recursive: true });
|
|
|
916
1961
|
|
|
917
1962
|
console.log('[sync-pages-to-public] Synced pages to public/pages');
|
|
918
1963
|
|
|
1964
|
+
END_OF_FILE_CONTENT
|
|
1965
|
+
mkdir -p "specs"
|
|
1966
|
+
echo "Creating specs/olonjsSpecs_V.1.3.md..."
|
|
1967
|
+
cat << 'END_OF_FILE_CONTENT' > "specs/olonjsSpecs_V.1.3.md"
|
|
1968
|
+
# 📐 OlonJS Architecture Specifications v1.3
|
|
1969
|
+
|
|
1970
|
+
**Status:** Mandatory Standard
|
|
1971
|
+
**Version:** 1.3.0 (Sovereign Core Edition — Architecture + Studio/ICE UX, Path-Deterministic Nested Editing)
|
|
1972
|
+
**Target:** Senior Architects / AI Agents / Enterprise Governance
|
|
1973
|
+
|
|
1974
|
+
**Scope v1.3:** This edition preserves the complete v1.2 architecture (MTRP, JSP, TBP, CIP, ECIP, JAP + Studio/ICE UX contract: IDAC, TOCC, BSDS, ASC, JEB + Tenant Type & Code-Generation Annex) as a **faithful superset**, and adds strict path-based/nested-array behavior for Studio selection and Inspector expansion.
|
|
1975
|
+
**Scope note (breaking):** In strict v1.3 Studio semantics, the legacy flat protocol (`itemField` / `itemId`) is removed in favor of `itemPath` (root-to-leaf path segments).
|
|
1976
|
+
|
|
1977
|
+
---
|
|
1978
|
+
|
|
1979
|
+
## 1. 📐 Modular Type Registry Pattern (MTRP) v1.2
|
|
1980
|
+
|
|
1981
|
+
**Objective:** Establish a strictly typed, open-ended protocol for extending content data structures where the **Core Engine** is the orchestrator and the **Tenant** is the provider.
|
|
1982
|
+
|
|
1983
|
+
### 1.1 The Sovereign Dependency Inversion
|
|
1984
|
+
The **Core** defines the empty `SectionDataRegistry`. The **Tenant** "injects" its specific definitions using **Module Augmentation**. This allows the Core to be distributed as a compiled NPM package while remaining aware of Tenant-specific types at compile-time.
|
|
1985
|
+
|
|
1986
|
+
### 1.2 Technical Implementation (`@olonjs/core/kernel`)
|
|
1987
|
+
```typescript
|
|
1988
|
+
export interface SectionDataRegistry {} // Augmented by Tenant
|
|
1989
|
+
export interface SectionSettingsRegistry {} // Augmented by Tenant
|
|
1990
|
+
|
|
1991
|
+
export interface BaseSection<K extends keyof SectionDataRegistry> {
|
|
1992
|
+
id: string;
|
|
1993
|
+
type: K;
|
|
1994
|
+
data: SectionDataRegistry[K];
|
|
1995
|
+
settings?: K extends keyof SectionSettingsRegistry
|
|
1996
|
+
? SectionSettingsRegistry[K]
|
|
1997
|
+
: BaseSectionSettings;
|
|
1998
|
+
}
|
|
1999
|
+
|
|
2000
|
+
export type Section = {
|
|
2001
|
+
[K in keyof SectionDataRegistry]: BaseSection<K>
|
|
2002
|
+
}[keyof SectionDataRegistry];
|
|
2003
|
+
```
|
|
2004
|
+
|
|
2005
|
+
**SectionType:** Core exports (or Tenant infers) **`SectionType`** as **`keyof SectionDataRegistry`**. After Tenant module augmentation, this is the union of all section type keys (e.g. `'header' | 'footer' | 'hero' | ...`). The Tenant uses this type for the ComponentRegistry and SECTION_SCHEMAS keys.
|
|
2006
|
+
|
|
2007
|
+
**Perché servono:** Il Core deve poter renderizzare section senza conoscere i tipi concreti a compile-time; il Tenant deve poter aggiungere nuovi tipi senza modificare il Core. I registry vuoti + module augmentation permettono di distribuire Core come pacchetto NPM e mantenere type-safety end-to-end (Section, registry, config). Senza MTRP, ogni nuovo tipo richiederebbe cambi nel Core o tipi deboli (`any`).
|
|
2008
|
+
|
|
2009
|
+
---
|
|
2010
|
+
|
|
2011
|
+
## 2. 📐 JsonPages Site Protocol (JSP) v1.8
|
|
2012
|
+
|
|
2013
|
+
**Objective:** Define the deterministic file system and the **Sovereign Projection Engine** (CLI).
|
|
2014
|
+
|
|
2015
|
+
### 2.1 The File System Ontology (The Silo Contract)
|
|
2016
|
+
Every site must reside in an isolated directory. Global Governance is physically separated from Local Content.
|
|
2017
|
+
* **`/config/site.json`** — Global Identity & Reserved System Blocks (Header/Footer). See Appendix A for typed shape.
|
|
2018
|
+
* **`/config/menu.json`** — Navigation Tree (SSOT for System Header). See Appendix A.
|
|
2019
|
+
* **`/config/theme.json`** — Theme tokens (optional but recommended). See Appendix A.
|
|
2020
|
+
* **`/pages/[slug].json`** — Local Body Content per page. See Appendix A (PageConfig).
|
|
2021
|
+
|
|
2022
|
+
**Application path convention:** The runtime app typically imports these via an alias (e.g. **`@/data/config/`** and **`@/data/pages/`**). The physical silo may be `src/data/config/` and `src/data/pages/` so that `site.json`, `menu.json`, `theme.json` live under `src/data/config/`, and page JSONs under `src/data/pages/`. The CLI or projection script may use `/config/` and `/pages/` at repo root; the **contract** is that the app receives **siteConfig**, **menuConfig**, **themeConfig**, and **pages** as defined in JEB (§10) and Appendix A.
|
|
2023
|
+
|
|
2024
|
+
### 2.2 Deterministic Projection (CLI Workflow)
|
|
2025
|
+
The CLI (`@olonjs/cli`) creates new tenants by:
|
|
2026
|
+
1. **Infra Projection:** Generating `package.json`, `tsconfig.json`, and `vite.config.ts` (The Shell).
|
|
2027
|
+
2. **Source Projection:** Executing a deterministic script (`src_tenant_alpha.sh`) to reconstruct the `src` folder (The DNA).
|
|
2028
|
+
3. **Dependency Resolution:** Enforcing specific versions of React, Radix, and Tailwind v4.
|
|
2029
|
+
|
|
2030
|
+
**Perché servono:** Una struttura file deterministica (config vs pages) separa governance globale (site, menu, theme) dal contenuto per pagina; il CLI può rigenerare tenant e tooling può trovare dati e schemi sempre negli stessi path. Senza JSP, ogni tenant sarebbe una struttura ad hoc e ingestione/export/Bake sarebbero fragili.
|
|
2031
|
+
|
|
2032
|
+
---
|
|
2033
|
+
|
|
2034
|
+
## 3. 🧱 Tenant Block Protocol (TBP) v1.0
|
|
2035
|
+
|
|
2036
|
+
**Objective:** Standardize the "Capsule" structure for components to enable automated ingestion (Pull) by the SaaS.
|
|
2037
|
+
|
|
2038
|
+
### 3.1 The Atomic Capsule Structure
|
|
2039
|
+
Components are self-contained directories under **`src/components/<sectionType>/`**:
|
|
2040
|
+
* **`View.tsx`** — The pure React component (Dumb View). Props: see Appendix A (SectionComponentPropsMap).
|
|
2041
|
+
* **`schema.ts`** — Zod schema(s) for the **data** contract (and optionally **settings**). Exports at least one schema (e.g. `HeroSchema`) used as the **data** schema for that type. Must extend BaseSectionData (§8) for data; array items must extend BaseArrayItem (§8).
|
|
2042
|
+
* **`types.ts`** — TypeScript interfaces inferred from the schema (e.g. `HeroData`, `HeroSettings`). Export types with names **`<SectionType>Data`** and **`<SectionType>Settings`** (or equivalent) so the Tenant can aggregate them in a single types module.
|
|
2043
|
+
* **`index.ts`** — Public API: re-exports View, schema(s), and types.
|
|
2044
|
+
|
|
2045
|
+
### 3.2 Reserved System Types
|
|
2046
|
+
* **`type: 'header'`** — Reserved for `site.json`. Receives **`menu: MenuItem[]`** in addition to `data` and `settings`. Menu is sourced from `menu.json` (see Appendix A). The Tenant **must** type `SectionComponentPropsMap['header']` as `{ data: HeaderData; settings?: HeaderSettings; menu: MenuItem[] }`.
|
|
2047
|
+
* **`type: 'footer'`** — Reserved for `site.json`. Props: `{ data: FooterData; settings?: FooterSettings }` only (no `menu`).
|
|
2048
|
+
* **`type: 'sectionHeader'`** — A standard local block. Must define its own `links` array in its local schema if used.
|
|
2049
|
+
|
|
2050
|
+
**Perché servono:** La capsula (View + schema + types + index) è l’unità di estensione: il Core e il Form Factory possono scoprire tipi e contratti per tipo senza convenzioni ad hoc. Header/footer riservati evitano conflitti tra globale e locale. Senza TBP, aggregazione di SECTION_SCHEMAS e registry sarebbe incoerente e l’ingestion da SaaS non sarebbe automatizzabile.
|
|
2051
|
+
|
|
2052
|
+
---
|
|
2053
|
+
|
|
2054
|
+
## 4. 🧱 Component Implementation Protocol (CIP) v1.5
|
|
2055
|
+
|
|
2056
|
+
**Objective:** Ensure system-wide stability and Admin UI integrity.
|
|
2057
|
+
|
|
2058
|
+
1. **The "Sovereign View" Law:** Components receive `data` and `settings` (and `menu` for header only) and return JSX. They are metadata-blind (never import Zod schemas).
|
|
2059
|
+
2. **Z-Index Neutrality:** Components must not use `z-index > 1`. Layout delegation (sticky/fixed) is managed by the `SectionRenderer`.
|
|
2060
|
+
3. **Agnostic Asset Protocol:** Use `resolveAssetUrl(path, tenantId)` for all media. Resolved URLs are under **`/assets/...`** with no tenantId segment in the path (e.g. relative `img/hero.jpg` → `/assets/img/hero.jpg`).
|
|
2061
|
+
|
|
2062
|
+
### 4.4 Local Design Tokens (v1.2)
|
|
2063
|
+
Section Views that control their own background, text, borders, or radii **shall** define a **local scope** via an inline `style` object on the section root: e.g. `--local-bg`, `--local-text`, `--local-text-muted`, `--local-surface`, `--local-border`, `--local-radius-lg`, `--local-accent`, mapped to theme variables. All Tailwind classes that affect color or radius in that section **must** use these variables (e.g. `bg-[var(--local-bg)]`, `text-[var(--local-text)]`). No naked utilities (e.g. `bg-blue-500`). An optional **`label`** in section data may be rendered with class **`jp-section-label`** for overlay type labels.
|
|
2064
|
+
|
|
2065
|
+
### 4.5 Z-Index & Overlay Governance (v1.2)
|
|
2066
|
+
Section content root **must** stay at **`z-index` ≤ 1** (prefer `z-0`) so the Sovereign Overlay can sit above with high z-index in Tenant CSS (§7). Header/footer may use a higher z-index (e.g. 50) only as a documented exception for global chrome.
|
|
2067
|
+
|
|
2068
|
+
**Perché servono (CIP):** View “dumb” (solo data/settings) e senza import di Zod evita accoppiamento e permette al Form Factory di essere l’unica fonte di verità sugli schemi. Z-index basso evita che il contenuto copra l’overlay di selezione in Studio. Asset via `resolveAssetUrl`: i path relativi vengono risolti in `/assets/...` (senza segmento tenantId nel path). Token locali (`--local-*`) rendono le section temabili e coerenti con overlay e tema; senza, stili “nudi” creano drift visivo e conflitti con l’UI di editing.
|
|
2069
|
+
|
|
2070
|
+
---
|
|
2071
|
+
|
|
2072
|
+
## 5. 🛠️ Editor Component Implementation Protocol (ECIP) v1.5
|
|
2073
|
+
|
|
2074
|
+
**Objective:** Standardize the Polymorphic ICE engine.
|
|
2075
|
+
|
|
2076
|
+
1. **Recursive Form Factory:** The Admin UI builds forms by traversing the Zod ontology.
|
|
2077
|
+
2. **UI Metadata:** Use `.describe('ui:[widget]')` in schemas to pass instructions to the Form Factory.
|
|
2078
|
+
3. **Deterministic IDs:** Every object in a `ZodArray` must extend `BaseArrayItem` (containing an `id`) to ensure React reconciliation stability during reordering.
|
|
2079
|
+
|
|
2080
|
+
### 5.4 UI Metadata Vocabulary (v1.2)
|
|
2081
|
+
Standard keys for the Form Factory:
|
|
2082
|
+
|
|
2083
|
+
| Key | Use case |
|
|
2084
|
+
|-----|----------|
|
|
2085
|
+
| `ui:text` | Single-line text input. |
|
|
2086
|
+
| `ui:textarea` | Multi-line text. |
|
|
2087
|
+
| `ui:select` | Enum / single choice. |
|
|
2088
|
+
| `ui:number` | Numeric input. |
|
|
2089
|
+
| `ui:list` | Array of items; list editor (add/remove/reorder). |
|
|
2090
|
+
| `ui:icon-picker` | Icon selection. |
|
|
2091
|
+
|
|
2092
|
+
Unknown keys may be treated as `ui:text`. Array fields must use `BaseArrayItem` for items.
|
|
2093
|
+
|
|
2094
|
+
### 5.5 Path-Only Nested Selection & Expansion (v1.3, breaking)
|
|
2095
|
+
In strict v1.3 Studio/Inspector behavior, nested editing targets are represented by **path segments from root to leaf**.
|
|
2096
|
+
|
|
2097
|
+
```typescript
|
|
2098
|
+
export type SelectionPathSegment = { fieldKey: string; itemId?: string };
|
|
2099
|
+
export type SelectionPath = SelectionPathSegment[];
|
|
2100
|
+
```
|
|
2101
|
+
|
|
2102
|
+
Rules:
|
|
2103
|
+
* Expansion and focus for nested arrays **must** be computed from `SelectionPath` (root → leaf), not from a single flat pair.
|
|
2104
|
+
* Matching by `fieldKey` alone is non-compliant for nested structures.
|
|
2105
|
+
* Legacy flat payload fields **`itemField`** and **`itemId`** are removed from strict v1.3 selection protocol.
|
|
2106
|
+
|
|
2107
|
+
**Perché servono (ECIP):** Il Form Factory deve sapere quale widget usare (text, textarea, select, list, …) senza hardcodare per tipo; `.describe('ui:...')` è il contratto. BaseArrayItem con `id` su ogni item di array garantisce chiavi stabili in React e reorder/delete corretti nell’Inspector. In v1.3 la selezione/espansione path-only elimina ambiguità su array annidati: senza path completo root→leaf, la sidebar può aprire il ramo sbagliato o non aprire il target.
|
|
2108
|
+
|
|
2109
|
+
---
|
|
2110
|
+
|
|
2111
|
+
## 6. 🎯 ICE Data Attribute Contract (IDAC) v1.1
|
|
2112
|
+
|
|
2113
|
+
**Objective:** Mandatory data attributes so the Stage (iframe) and Inspector can bind selection and field/item editing without coupling to Tenant DOM.
|
|
2114
|
+
|
|
2115
|
+
### 6.1 Section-Level Markup (Core-Provided)
|
|
2116
|
+
**SectionRenderer** (Core) wraps each section root with:
|
|
2117
|
+
* **`data-section-id`** — Section instance ID (e.g. UUID). On the wrapper that contains content + overlay.
|
|
2118
|
+
* Sibling overlay element **`data-jp-section-overlay`** — Selection ring and type label. **Tenant does not add this;** Core injects it.
|
|
2119
|
+
|
|
2120
|
+
Tenant Views render the **content** root only (e.g. `<section>` or `<div>`), placed **inside** the Core wrapper.
|
|
2121
|
+
|
|
2122
|
+
### 6.2 Field-Level Binding (Tenant-Provided)
|
|
2123
|
+
For every **editable scalar field** the View **must** attach **`data-jp-field="<fieldKey>"`** (key matches schema path: e.g. `title`, `description`, `sectionTitle`, `label`).
|
|
2124
|
+
|
|
2125
|
+
### 6.3 Array-Item Binding (Tenant-Provided)
|
|
2126
|
+
For every **editable array item** the View **must** attach:
|
|
2127
|
+
* **`data-jp-item-id="<stableId>"`** — Prefer `item.id`; fallback e.g. `legacy-${index}` only outside strict mode.
|
|
2128
|
+
* **`data-jp-item-field="<arrayKey>"`** — e.g. `cards`, `layers`, `products`, `paragraphs`.
|
|
2129
|
+
|
|
2130
|
+
### 6.4 Compliance
|
|
2131
|
+
**Reserved types** (`header`, `footer`): ICE attributes optional unless Studio edits them. **All other section types** in the Stage and in `SECTION_SCHEMAS` **must** implement §6.2 and §6.3 for every editable field and array item.
|
|
2132
|
+
|
|
2133
|
+
### 6.5 Strict Path Extraction for Nested Arrays (v1.3, breaking)
|
|
2134
|
+
For nested array targets, the Core/Inspector contract is path-based:
|
|
2135
|
+
* The runtime selection target is expressed as `itemPath: SelectionPath` (root → leaf).
|
|
2136
|
+
* Flat identity (`itemField` + `itemId`) is not sufficient for nested structures and is removed in strict v1.3 payloads.
|
|
2137
|
+
* In strict mode, index-based identity fallback is non-compliant for editable object arrays.
|
|
2138
|
+
|
|
2139
|
+
**Perché servono (IDAC):** Lo Stage è in un iframe e l’Inspector deve sapere **quale campo o item** corrisponde al click (o alla selezione) senza conoscere la struttura DOM del Tenant. **`data-jp-field`** associa un nodo DOM al path dello schema (es. `title`, `description`): così il Core può evidenziare la riga giusta nella sidebar, applicare opacità attivo/inattivo e aprire il form sul campo corretto. **`data-jp-item-id`** e **`data-jp-item-field`** fanno lo stesso per gli item di array (liste, reorder, delete). In v1.3, `itemPath` rende deterministico anche il caso nested (array dentro array), eliminando mismatch tra selezione canvas e ramo aperto in sidebar.
|
|
2140
|
+
|
|
2141
|
+
---
|
|
2142
|
+
|
|
2143
|
+
## 7. 🎨 Tenant Overlay CSS Contract (TOCC) v1.0
|
|
2144
|
+
|
|
2145
|
+
**Objective:** The Stage iframe loads only Tenant HTML/CSS. Core injects overlay **markup** but does **not** ship overlay styles. The Tenant **must** supply CSS so overlay is visible.
|
|
2146
|
+
|
|
2147
|
+
### 7.1 Required Selectors (Tenant global CSS)
|
|
2148
|
+
1. **`[data-jp-section-overlay]`** — `position: absolute; inset: 0`; `pointer-events: none`; base state transparent.
|
|
2149
|
+
2. **`[data-section-id]:hover [data-jp-section-overlay]`** — Hover: e.g. dashed border, subtle tint.
|
|
2150
|
+
3. **`[data-section-id][data-jp-selected] [data-jp-section-overlay]`** — Selected: solid border, optional tint.
|
|
2151
|
+
4. **`[data-jp-section-overlay] > div`** (type label) — Position and visibility (e.g. visible on hover/selected).
|
|
2152
|
+
|
|
2153
|
+
### 7.2 Z-Index
|
|
2154
|
+
Overlay **z-index** high (e.g. 9999). Section content at or below CIP limit (§4.5).
|
|
2155
|
+
|
|
2156
|
+
### 7.3 Responsibility
|
|
2157
|
+
**Core:** Injects wrapper and overlay DOM; sets `data-jp-selected`. **Tenant:** All overlay **visual** rules.
|
|
2158
|
+
|
|
2159
|
+
**Perché servono (TOCC):** L’iframe dello Stage carica solo HTML/CSS del Tenant; il Core inietta il markup dell’overlay ma non gli stili. Senza CSS Tenant per i selettori TOCC, bordo hover/selected e type label non sarebbero visibili: l’autore non vedrebbe quale section è selezionata né il label del tipo. TOCC chiarisce la responsabilità (Core = markup, Tenant = aspetto) e garantisce UX uniforme tra tenant.
|
|
2160
|
+
|
|
2161
|
+
---
|
|
2162
|
+
|
|
2163
|
+
## 8. 📦 Base Section Data & Settings (BSDS) v1.0
|
|
2164
|
+
|
|
2165
|
+
**Objective:** Standardize base schema fragments for anchors, array items, and section settings.
|
|
2166
|
+
|
|
2167
|
+
### 8.1 BaseSectionData
|
|
2168
|
+
Every section data schema **must** extend a base with at least **`anchorId`** (optional string). Canonical Zod (Tenant `lib/base-schemas.ts` or equivalent):
|
|
2169
|
+
|
|
2170
|
+
```typescript
|
|
2171
|
+
export const BaseSectionData = z.object({
|
|
2172
|
+
anchorId: z.string().optional().describe('ui:text'),
|
|
2173
|
+
});
|
|
2174
|
+
```
|
|
2175
|
+
|
|
2176
|
+
### 8.2 BaseArrayItem
|
|
2177
|
+
Every array item schema editable in the Inspector **must** include **`id`** (optional string minimum). Canonical Zod:
|
|
2178
|
+
|
|
2179
|
+
```typescript
|
|
2180
|
+
export const BaseArrayItem = z.object({
|
|
2181
|
+
id: z.string().optional(),
|
|
2182
|
+
});
|
|
2183
|
+
```
|
|
2184
|
+
|
|
2185
|
+
Recommended: required UUID for new items. Used by `data-jp-item-id` and React reconciliation.
|
|
2186
|
+
|
|
2187
|
+
### 8.3 BaseSectionSettings (Optional)
|
|
2188
|
+
Common section-level settings. Canonical Zod (name **BaseSectionSettingsSchema** or as exported by Core):
|
|
2189
|
+
|
|
2190
|
+
```typescript
|
|
2191
|
+
export const BaseSectionSettingsSchema = z.object({
|
|
2192
|
+
paddingTop: z.enum(['none', 'sm', 'md', 'lg', 'xl', '2xl']).default('md').describe('ui:select'),
|
|
2193
|
+
paddingBottom: z.enum(['none', 'sm', 'md', 'lg', 'xl', '2xl']).default('md').describe('ui:select'),
|
|
2194
|
+
theme: z.enum(['dark', 'light', 'accent']).default('dark').describe('ui:select'),
|
|
2195
|
+
container: z.enum(['boxed', 'fluid']).default('boxed').describe('ui:select'),
|
|
2196
|
+
});
|
|
2197
|
+
```
|
|
2198
|
+
|
|
2199
|
+
Capsules may extend this for type-specific settings. Core may export **BaseSectionSettings** as the TypeScript type inferred from this or a superset.
|
|
2200
|
+
|
|
2201
|
+
**Perché servono (BSDS):** anchorId permette deep-link e navigazione in-page; id sugli array item è necessario per `data-jp-item-id`, reorder e React reconciliation. BaseSectionSettings comuni (padding, theme, container) evitano ripetizione e allineano il Form Factory tra capsule. Senza base condivisi, ogni capsule inventa convenzioni e validazione/add-section diventano fragili.
|
|
2202
|
+
|
|
2203
|
+
---
|
|
2204
|
+
|
|
2205
|
+
## 9. 📌 AddSectionConfig (ASC) v1.0
|
|
2206
|
+
|
|
2207
|
+
**Objective:** Formalize the "Add Section" contract used by the Studio.
|
|
2208
|
+
|
|
2209
|
+
**Type (Core exports `AddSectionConfig`):**
|
|
2210
|
+
```typescript
|
|
2211
|
+
interface AddSectionConfig {
|
|
2212
|
+
addableSectionTypes: readonly string[];
|
|
2213
|
+
sectionTypeLabels: Record<string, string>;
|
|
2214
|
+
getDefaultSectionData(sectionType: string): Record<string, unknown>;
|
|
2215
|
+
}
|
|
2216
|
+
```
|
|
2217
|
+
|
|
2218
|
+
**Shape:** Tenant provides one object (e.g. `addSectionConfig`) with:
|
|
2219
|
+
* **`addableSectionTypes`** — Readonly array of section type keys. Only these types appear in the Add Section Library. Must be a subset of (or equal to) the keys in SectionDataRegistry.
|
|
2220
|
+
* **`sectionTypeLabels`** — Map type key → display string (e.g. `{ hero: 'Hero', 'cta-banner': 'CTA Banner' }`).
|
|
2221
|
+
* **`getDefaultSectionData(sectionType: string): Record<string, unknown>`** — Returns default `data` for a new section. Must conform to the capsule’s data schema so the new section validates.
|
|
2222
|
+
|
|
2223
|
+
Core creates a new section with deterministic UUID, `type`, and `data` from `getDefaultSectionData(type)`.
|
|
2224
|
+
|
|
2225
|
+
**Perché servono (ASC):** Lo Studio deve mostrare una libreria “Aggiungi sezione” con nomi leggibili e, alla scelta, creare una section con dati iniziali validi. addableSectionTypes, sectionTypeLabels e getDefaultSectionData sono il contratto: il Tenant è l’unica fonte di verità su quali tipi sono addabili e con quali default. Senza ASC, il Core non saprebbe cosa mostrare in modal né come popolare i dati della nuova section.
|
|
2226
|
+
|
|
2227
|
+
---
|
|
2228
|
+
|
|
2229
|
+
## 10. ⚙️ JsonPagesConfig & Engine Bootstrap (JEB) v1.1
|
|
2230
|
+
|
|
2231
|
+
**Objective:** Bootstrap contract between Tenant app and `@olonjs/core`.
|
|
2232
|
+
|
|
2233
|
+
### 10.1 JsonPagesConfig (required fields)
|
|
2234
|
+
The Tenant passes a single **config** object to **JsonPagesEngine**. Required fields:
|
|
2235
|
+
|
|
2236
|
+
| Field | Type | Description |
|
|
2237
|
+
|-------|------|-------------|
|
|
2238
|
+
| **tenantId** | string | Passed to `resolveAssetUrl(path, tenantId)`; resolved asset URLs are **`/assets/...`** with no tenantId segment in the path. |
|
|
2239
|
+
| **registry** | `{ [K in SectionType]: React.FC<SectionComponentPropsMap[K]> }` | Component registry. Must match MTRP keys. See Appendix A. |
|
|
2240
|
+
| **schemas** | `Record<SectionType, ZodType>` or equivalent | SECTION_SCHEMAS: type → **data** Zod schema. Form Factory uses this. See Appendix A. |
|
|
2241
|
+
| **pages** | `Record<string, PageConfig>` | Slug → page config. See Appendix A. |
|
|
2242
|
+
| **siteConfig** | SiteConfig | Global site (identity, header/footer blocks). See Appendix A. |
|
|
2243
|
+
| **themeConfig** | ThemeConfig | Theme tokens. See Appendix A. |
|
|
2244
|
+
| **menuConfig** | MenuConfig | Navigation tree (SSOT for header menu). See Appendix A. |
|
|
2245
|
+
| **themeCss** | `{ tenant: string }` | At least **tenant**: string (inline CSS or URL) for Stage iframe injection. |
|
|
2246
|
+
| **addSection** | AddSectionConfig | Add-section config (§9). |
|
|
2247
|
+
|
|
2248
|
+
Core may define optional fields. The Tenant must not omit required fields.
|
|
2249
|
+
|
|
2250
|
+
### 10.2 JsonPagesEngine
|
|
2251
|
+
Root component: **`<JsonPagesEngine config={config} />`**. Responsibilities: route → page, SectionRenderer per section; in Studio mode Sovereign Shell (Inspector, Control Bar, postMessage); section wrappers and overlay per IDAC and JAP. Tenant does not implement the Shell.
|
|
2252
|
+
|
|
2253
|
+
### 10.3 Studio Selection Event Contract (v1.3, breaking)
|
|
2254
|
+
In strict v1.3 Studio, section selection payload for nested targets is path-based:
|
|
2255
|
+
|
|
2256
|
+
```typescript
|
|
2257
|
+
type SectionSelectMessage = {
|
|
2258
|
+
type: 'SECTION_SELECT';
|
|
2259
|
+
section: { id: string; type: string; scope: 'global' | 'local' };
|
|
2260
|
+
itemPath?: SelectionPath; // root -> leaf
|
|
2261
|
+
};
|
|
2262
|
+
```
|
|
2263
|
+
|
|
2264
|
+
Removed from strict protocol:
|
|
2265
|
+
* `itemField`
|
|
2266
|
+
* `itemId`
|
|
2267
|
+
|
|
2268
|
+
**Perché servono (JEB):** Un unico punto di bootstrap (config + Engine) evita che il Tenant replichi logica di routing, Shell e overlay. I campi obbligatori in JsonPagesConfig (tenantId, registry, schemas, pages, siteConfig, themeConfig, menuConfig, themeCss, addSection) sono il minimo per far funzionare rendering, Studio e Form Factory; omissioni causano errori a runtime. In v1.3, il payload `itemPath` sincronizza in modo non ambiguo Stage e Inspector su nested arrays.
|
|
2269
|
+
|
|
2270
|
+
---
|
|
2271
|
+
|
|
2272
|
+
# 🏛️ OlonJS_ADMIN_PROTOCOL (JAP) v1.2
|
|
2273
|
+
|
|
2274
|
+
**Status:** Mandatory Standard
|
|
2275
|
+
**Version:** 1.2.0 (Sovereign Shell Edition — Path/Nested Strictness)
|
|
2276
|
+
**Objective:** Deterministic orchestration of the "Studio" environment (ICE Level 1).
|
|
2277
|
+
|
|
2278
|
+
---
|
|
2279
|
+
|
|
2280
|
+
## 1. The Sovereign Shell Topology
|
|
2281
|
+
The Admin interface is a **Sovereign Shell** from `@olonjs/core`.
|
|
2282
|
+
1. **The Stage (Canvas):** Isolated Iframe; postMessage for data updates and selection mirroring. Section markup follows **IDAC** (§6); overlay styling follows **TOCC** (§7).
|
|
2283
|
+
2. **The Inspector (Sidebar):** Consumes Tenant Zod schemas to generate editors; binding via `data-jp-field` and `data-jp-item-*`.
|
|
2284
|
+
3. **The Control Bar:** Save, Export, Add Section.
|
|
2285
|
+
|
|
2286
|
+
## 2. State Orchestration & Persistence
|
|
2287
|
+
* **Working Draft:** Reactive local state for unsaved changes.
|
|
2288
|
+
* **Sync Law:** Inspector changes → Working Draft → Stage via `STUDIO_EVENTS.UPDATE_DRAFTS`.
|
|
2289
|
+
* **Bake Protocol:** "Bake HTML" requests snapshot from Iframe, injects `ProjectState` as JSON, triggers download.
|
|
2290
|
+
|
|
2291
|
+
## 3. Context Switching (Global vs. Local)
|
|
2292
|
+
* **Header/Footer** selection → Global Mode, `site.json`.
|
|
2293
|
+
* Any other section → Page Mode, current `[slug].json`.
|
|
2294
|
+
|
|
2295
|
+
## 4. Section Lifecycle Management
|
|
2296
|
+
1. **Add Section:** Modal from Tenant `SECTION_SCHEMAS`; UUID + default data via **AddSectionConfig** (§9).
|
|
2297
|
+
2. **Reorder:** Inspector or Stage Overlay; array mutation in Working Draft.
|
|
2298
|
+
3. **Delete:** Confirmation; remove from array, clear selection.
|
|
2299
|
+
|
|
2300
|
+
## 5. Stage Isolation & Overlay
|
|
2301
|
+
* **CSS Shielding:** Stage in Iframe; Tenant CSS does not leak into Admin.
|
|
2302
|
+
* **Sovereign Overlay:** Selection ring and type labels injected per **IDAC** (§6); Tenant styles them per **TOCC** (§7).
|
|
2303
|
+
|
|
2304
|
+
## 6. "Green Build" Validation
|
|
2305
|
+
Studio enforces `tsc && vite build`. No export with TypeScript errors.
|
|
2306
|
+
|
|
2307
|
+
## 7. Path-Deterministic Selection & Sidebar Expansion (v1.3, breaking)
|
|
2308
|
+
* Section/item focus synchronization uses `itemPath` (root → leaf), not flat `itemField/itemId`.
|
|
2309
|
+
* Sidebar expansion state for nested arrays must be derived from all path segments.
|
|
2310
|
+
* Flat-only matching may open/close wrong branches and is non-compliant in strict mode.
|
|
2311
|
+
|
|
2312
|
+
**Perché servono (JAP):** Stage in iframe + Inspector + Control Bar separano il contesto di editing dal sito; postMessage e Working Draft permettono modifiche senza toccare subito i file. Bake ed Export richiedono uno stato coerente. Global vs Page mode evita confusione su dove si sta editando (site.json vs [slug].json). Add/Reorder/Delete sono gestiti in un solo modo (Working Draft + ASC). Green Build garantisce che ciò che si esporta compili. In v1.3, il path completo elimina ambiguità nella sincronizzazione Stage↔Sidebar su strutture annidate.
|
|
2313
|
+
|
|
2314
|
+
---
|
|
2315
|
+
|
|
2316
|
+
## Compliance: Legacy vs Full UX (v1.3)
|
|
2317
|
+
|
|
2318
|
+
| Dimension | Legacy / Less UX | Full UX (Core-aligned) |
|
|
2319
|
+
|-----------|-------------------|-------------------------|
|
|
2320
|
+
| **ICE binding** | No `data-jp-*`; Inspector cannot bind. | IDAC (§6) on every editable section/field/item. |
|
|
2321
|
+
| **Section wrapper** | Plain `<section>`; no overlay contract. | Core wrapper + overlay; Tenant CSS per TOCC (§7). |
|
|
2322
|
+
| **Design tokens** | Raw BEM / fixed classes. | Local tokens (§4.4); `var(--local-*)` only. |
|
|
2323
|
+
| **Base schemas** | Ad hoc. | BSDS (§8): BaseSectionData, BaseArrayItem, BaseSectionSettings. |
|
|
2324
|
+
| **Add Section** | Ad hoc defaults. | ASC (§9): addableSectionTypes, labels, getDefaultSectionData. |
|
|
2325
|
+
| **Bootstrap** | Implicit. | JEB (§10): JsonPagesConfig + JsonPagesEngine. |
|
|
2326
|
+
| **Selection payload** | Flat `itemField/itemId`. | Path-only `itemPath: SelectionPath` (JEB §10.3). |
|
|
2327
|
+
| **Nested array expansion** | Single-segment or field-only heuristics. | Root-to-leaf path expansion (ECIP §5.5, JAP §7). |
|
|
2328
|
+
| **Array item identity (strict)** | Index fallback tolerated. | Stable `id` required for editable object arrays. |
|
|
2329
|
+
|
|
2330
|
+
**Rule:** Every page section (non-header/footer) that appears in the Stage and in `SECTION_SCHEMAS` must comply with §6, §7, §4.4, §8, §9, §10 for full Studio UX.
|
|
2331
|
+
|
|
2332
|
+
---
|
|
2333
|
+
|
|
2334
|
+
## Summary of v1.3 Additions
|
|
2335
|
+
|
|
2336
|
+
| § | Title | Purpose |
|
|
2337
|
+
|---|--------|--------|
|
|
2338
|
+
| 5.5 | Path-Only Nested Selection & Expansion | ECIP: root→leaf `SelectionPath`; remove flat matching in strict mode. |
|
|
2339
|
+
| 6.5 | Strict Path Extraction for Nested Arrays | IDAC: path-based nested targeting; no strict flat fallback. |
|
|
2340
|
+
| 10.3 | Studio Selection Event Contract | JEB: `SECTION_SELECT` uses `itemPath`; remove `itemField/itemId`. |
|
|
2341
|
+
| JAP §7 | Path-Deterministic Selection & Sidebar Expansion | Studio state synchronization for nested arrays. |
|
|
2342
|
+
| Compliance | Legacy vs Full UX (v1.3) | Explicit breaking delta for flat protocol removal and strict IDs. |
|
|
2343
|
+
| **Appendix A.6** | **v1.3 Path/Nested Strictness Addendum** | Type/export and migration checklist for path-only protocol. |
|
|
2344
|
+
|
|
2345
|
+
---
|
|
2346
|
+
|
|
2347
|
+
# Appendix A — Tenant Type & Code-Generation Annex
|
|
2348
|
+
|
|
2349
|
+
**Objective:** Make the specification **sufficient** to generate or audit a full tenant (new site, new components, new data) without a reference codebase. Defines TypeScript types, JSON shapes, schema contract, file paths, and integration pattern.
|
|
2350
|
+
|
|
2351
|
+
**Status:** Mandatory for code-generation and governance. Compliance ensures generated tenants are typed and wired like the reference implementation.
|
|
2352
|
+
|
|
2353
|
+
---
|
|
2354
|
+
|
|
2355
|
+
## A.1 Core-Provided Types (from `@olonjs/core`)
|
|
2356
|
+
|
|
2357
|
+
The following are assumed to be exported by Core. The Tenant augments **SectionDataRegistry** and **SectionSettingsRegistry**; all other types are consumed as-is.
|
|
2358
|
+
|
|
2359
|
+
| Type | Description |
|
|
2360
|
+
|------|-------------|
|
|
2361
|
+
| **SectionType** | `keyof SectionDataRegistry` (after Tenant augmentation). Union of all section type keys. |
|
|
2362
|
+
| **Section** | Union of `BaseSection<K>` for all K in SectionDataRegistry. See MTRP §1.2. |
|
|
2363
|
+
| **BaseSectionSettings** | Optional base type for section settings (may align with BSDS §8.3). |
|
|
2364
|
+
| **MenuItem** | Navigation item. **Minimum shape:** `{ label: string; href: string }`. Core may extend (e.g. `children?: MenuItem[]`). |
|
|
2365
|
+
| **AddSectionConfig** | See §9. |
|
|
2366
|
+
| **JsonPagesConfig** | See §10.1. |
|
|
2367
|
+
|
|
2368
|
+
**Perché servono (A.1):** Il Tenant deve conoscere i tipi esportati dal Core (SectionType, MenuItem, AddSectionConfig, JsonPagesConfig) per tipizzare registry, config e augmentation senza dipendere da implementazioni interne.
|
|
2369
|
+
|
|
2370
|
+
---
|
|
2371
|
+
|
|
2372
|
+
## A.2 Tenant-Provided Types (single source: `src/types.ts` or equivalent)
|
|
2373
|
+
|
|
2374
|
+
The Tenant **must** define the following in one module (e.g. **`src/types.ts`**). This module **must** perform the **module augmentation** of `@olonjs/core` for **SectionDataRegistry** and **SectionSettingsRegistry**, and **must** export **SectionComponentPropsMap** and re-export from `@olonjs/core` so that **SectionType** is available after augmentation.
|
|
2375
|
+
|
|
2376
|
+
### A.2.1 SectionComponentPropsMap
|
|
2377
|
+
|
|
2378
|
+
Maps each section type to the props of its React component. **Header** is the only type that receives **menu**.
|
|
2379
|
+
|
|
2380
|
+
**Option A — Explicit (recommended for clarity and tooling):** For each section type K, add one entry. Header receives **menu**.
|
|
2381
|
+
|
|
2382
|
+
```typescript
|
|
2383
|
+
import type { MenuItem } from '@olonjs/core';
|
|
2384
|
+
// Import Data/Settings from each capsule.
|
|
2385
|
+
|
|
2386
|
+
export type SectionComponentPropsMap = {
|
|
2387
|
+
'header': { data: HeaderData; settings?: HeaderSettings; menu: MenuItem[] };
|
|
2388
|
+
'footer': { data: FooterData; settings?: FooterSettings };
|
|
2389
|
+
'hero': { data: HeroData; settings?: HeroSettings };
|
|
2390
|
+
// ... one entry per SectionType, e.g. 'feature-grid', 'cta-banner', etc.
|
|
2391
|
+
};
|
|
2392
|
+
```
|
|
2393
|
+
|
|
2394
|
+
**Option B — Mapped type (DRY, requires SectionDataRegistry/SectionSettingsRegistry in scope):**
|
|
2395
|
+
|
|
2396
|
+
```typescript
|
|
2397
|
+
import type { MenuItem } from '@olonjs/core';
|
|
2398
|
+
|
|
2399
|
+
export type SectionComponentPropsMap = {
|
|
2400
|
+
[K in SectionType]: K extends 'header'
|
|
2401
|
+
? { data: SectionDataRegistry[K]; settings?: SectionSettingsRegistry[K]; menu: MenuItem[] }
|
|
2402
|
+
: { data: SectionDataRegistry[K]; settings?: K extends keyof SectionSettingsRegistry ? SectionSettingsRegistry[K] : BaseSectionSettings };
|
|
2403
|
+
};
|
|
2404
|
+
```
|
|
2405
|
+
|
|
2406
|
+
SectionType is imported from Core (after Tenant augmentation). In practice Option A is the reference pattern; Option B is valid if the Tenant prefers a single derived definition.
|
|
2407
|
+
|
|
2408
|
+
**Perché servono (A.2):** SectionComponentPropsMap e i tipi di config (PageConfig, SiteConfig, MenuConfig, ThemeConfig) definiscono il contratto tra dati (JSON, API) e componente; l’augmentation è l’unico modo per estendere i registry del Core senza fork. Senza questi tipi, generazione tenant e refactor sarebbero senza guida e il type-check fallirebbe.
|
|
2409
|
+
|
|
2410
|
+
### A.2.2 ComponentRegistry type
|
|
2411
|
+
|
|
2412
|
+
The registry object **must** be typed as:
|
|
2413
|
+
|
|
2414
|
+
```typescript
|
|
2415
|
+
import type { SectionType } from '@olonjs/core';
|
|
2416
|
+
import type { SectionComponentPropsMap } from '@/types';
|
|
2417
|
+
|
|
2418
|
+
export const ComponentRegistry: {
|
|
2419
|
+
[K in SectionType]: React.FC<SectionComponentPropsMap[K]>;
|
|
2420
|
+
} = { /* ... */ };
|
|
2421
|
+
```
|
|
2422
|
+
|
|
2423
|
+
File: **`src/lib/ComponentRegistry.tsx`** (or equivalent). Imports one View per section type and assigns it to the corresponding key.
|
|
2424
|
+
|
|
2425
|
+
### A.2.3 PageConfig
|
|
2426
|
+
|
|
2427
|
+
Minimum shape for a single page (used in **pages** and in each **`[slug].json`**):
|
|
2428
|
+
|
|
2429
|
+
```typescript
|
|
2430
|
+
export interface PageConfig {
|
|
2431
|
+
id?: string;
|
|
2432
|
+
slug: string;
|
|
2433
|
+
meta?: {
|
|
2434
|
+
title?: string;
|
|
2435
|
+
description?: string;
|
|
2436
|
+
};
|
|
2437
|
+
sections: Section[];
|
|
2438
|
+
}
|
|
2439
|
+
```
|
|
2440
|
+
|
|
2441
|
+
**Section** is the union type from MTRP (§1.2). Each element of **sections** has **id**, **type**, **data**, **settings** and conforms to the capsule schemas.
|
|
2442
|
+
|
|
2443
|
+
### A.2.4 SiteConfig
|
|
2444
|
+
|
|
2445
|
+
Minimum shape for **site.json** (and for **siteConfig** in JsonPagesConfig):
|
|
2446
|
+
|
|
2447
|
+
```typescript
|
|
2448
|
+
export interface SiteConfigIdentity {
|
|
2449
|
+
title?: string;
|
|
2450
|
+
logoUrl?: string;
|
|
2451
|
+
}
|
|
2452
|
+
|
|
2453
|
+
export interface SiteConfig {
|
|
2454
|
+
identity?: SiteConfigIdentity;
|
|
2455
|
+
pages?: Array<{ slug: string; label: string }>;
|
|
2456
|
+
header: {
|
|
2457
|
+
id: string;
|
|
2458
|
+
type: 'header';
|
|
2459
|
+
data: HeaderData;
|
|
2460
|
+
settings?: HeaderSettings;
|
|
2461
|
+
};
|
|
2462
|
+
footer: {
|
|
2463
|
+
id: string;
|
|
2464
|
+
type: 'footer';
|
|
2465
|
+
data: FooterData;
|
|
2466
|
+
settings?: FooterSettings;
|
|
2467
|
+
};
|
|
2468
|
+
}
|
|
2469
|
+
```
|
|
2470
|
+
|
|
2471
|
+
**HeaderData**, **FooterData**, **HeaderSettings**, **FooterSettings** are the types exported from the header and footer capsules.
|
|
2472
|
+
|
|
2473
|
+
### A.2.5 MenuConfig
|
|
2474
|
+
|
|
2475
|
+
Minimum shape for **menu.json** (and for **menuConfig** in JsonPagesConfig). Structure is tenant-defined; Core expects the header to receive **MenuItem[]**. Common pattern: an object with a key (e.g. **main**) whose value is **MenuItem[]**.
|
|
2476
|
+
|
|
2477
|
+
```typescript
|
|
2478
|
+
export interface MenuConfig {
|
|
2479
|
+
main?: MenuItem[];
|
|
2480
|
+
[key: string]: MenuItem[] | undefined;
|
|
2481
|
+
}
|
|
2482
|
+
```
|
|
2483
|
+
|
|
2484
|
+
Or simply **`MenuItem[]`** if the app uses a single flat list. The Tenant must ensure that the value passed to the header component as **menu** conforms to **MenuItem[]** (e.g. `menuConfig.main` or `menuConfig` if it is the array).
|
|
2485
|
+
|
|
2486
|
+
### A.2.6 ThemeConfig
|
|
2487
|
+
|
|
2488
|
+
Minimum shape for **theme.json** (and for **themeConfig** in JsonPagesConfig). Tenant-defined; typically tokens for colors, typography, radius.
|
|
2489
|
+
|
|
2490
|
+
```typescript
|
|
2491
|
+
export interface ThemeConfig {
|
|
2492
|
+
name?: string;
|
|
2493
|
+
tokens?: {
|
|
2494
|
+
colors?: Record<string, string>;
|
|
2495
|
+
typography?: Record<string, string | Record<string, string>>;
|
|
2496
|
+
borderRadius?: Record<string, string>;
|
|
2497
|
+
};
|
|
2498
|
+
[key: string]: unknown;
|
|
2499
|
+
}
|
|
2500
|
+
```
|
|
2501
|
+
|
|
2502
|
+
---
|
|
2503
|
+
|
|
2504
|
+
## A.3 Schema Contract (SECTION_SCHEMAS)
|
|
2505
|
+
|
|
2506
|
+
**Location:** **`src/lib/schemas.ts`** (or equivalent).
|
|
2507
|
+
|
|
2508
|
+
**Contract:**
|
|
2509
|
+
* **SECTION_SCHEMAS** is a **single object** whose keys are **SectionType** and whose values are **Zod schemas for the section data** (not settings, unless the Form Factory contract expects a combined or per-type settings schema; then each value may be the data schema only, and settings may be defined per capsule and aggregated elsewhere if needed).
|
|
2510
|
+
* The Tenant **must** re-export **BaseSectionData**, **BaseArrayItem**, and optionally **BaseSectionSettingsSchema** from **`src/lib/base-schemas.ts`** (or equivalent). Each capsule’s data schema **must** extend BaseSectionData; each array item schema **must** extend or include BaseArrayItem.
|
|
2511
|
+
* **SECTION_SCHEMAS** is typed as **`Record<SectionType, ZodType>`** or **`{ [K in SectionType]: ZodType }`** so that keys match the registry and SectionDataRegistry.
|
|
2512
|
+
|
|
2513
|
+
**Export:** The app imports **SECTION_SCHEMAS** and passes it as **config.schemas** to JsonPagesEngine. The Form Factory traverses these schemas to build editors.
|
|
2514
|
+
|
|
2515
|
+
**Perché servono (A.3):** Un unico oggetto SECTION_SCHEMAS con chiavi = SectionType e valori = schema data permette al Form Factory di costruire form per tipo senza convenzioni ad hoc; i base schema garantiscono anchorId e id su item. Senza questo contratto, l’Inspector non saprebbe quali campi mostrare né come validare.
|
|
2516
|
+
|
|
2517
|
+
---
|
|
2518
|
+
|
|
2519
|
+
## A.4 File Paths & Data Layout
|
|
2520
|
+
|
|
2521
|
+
| Purpose | Path (conventional) | Description |
|
|
2522
|
+
|---------|---------------------|-------------|
|
|
2523
|
+
| Site config | **`src/data/config/site.json`** | SiteConfig (identity, header, footer, pages list). |
|
|
2524
|
+
| Menu config | **`src/data/config/menu.json`** | MenuConfig (e.g. main nav). |
|
|
2525
|
+
| Theme config | **`src/data/config/theme.json`** | ThemeConfig (tokens). |
|
|
2526
|
+
| Page data | **`src/data/pages/<slug>.json`** | One file per page; content is PageConfig (slug, meta, sections). |
|
|
2527
|
+
| Base schemas | **`src/lib/base-schemas.ts`** | BaseSectionData, BaseArrayItem, BaseSectionSettingsSchema. |
|
|
2528
|
+
| Schema aggregate | **`src/lib/schemas.ts`** | SECTION_SCHEMAS; re-exports base schemas. |
|
|
2529
|
+
| Registry | **`src/lib/ComponentRegistry.tsx`** | ComponentRegistry object. |
|
|
2530
|
+
| Add-section config | **`src/lib/addSectionConfig.ts`** | addSectionConfig (AddSectionConfig). |
|
|
2531
|
+
| Tenant types & augmentation | **`src/types.ts`** | SectionComponentPropsMap, PageConfig, SiteConfig, MenuConfig, ThemeConfig; **declare module '@olonjs/core'** for SectionDataRegistry and SectionSettingsRegistry; re-export from Core. |
|
|
2532
|
+
| Bootstrap | **`src/App.tsx`** | Imports config (site, theme, menu, pages), registry, schemas, addSection, themeCss; builds JsonPagesConfig; renders **<JsonPagesEngine config={config} />**. |
|
|
2533
|
+
|
|
2534
|
+
The app entry (e.g. **main.tsx**) renders **App**. No other bootstrap contract is specified; the Tenant may use Vite aliases (e.g. **@/**) for the paths above.
|
|
2535
|
+
|
|
2536
|
+
**Perché servono (A.4):** Path fissi (data/config, data/pages, lib/schemas, types.ts, App.tsx) permettono a CLI, tooling e agenti di trovare sempre gli stessi file; l’onboarding e la generazione da spec sono deterministici. Senza convenzione, ogni tenant sarebbe una struttura diversa.
|
|
2537
|
+
|
|
2538
|
+
---
|
|
2539
|
+
|
|
2540
|
+
## A.5 Integration Checklist (Code-Generation)
|
|
2541
|
+
|
|
2542
|
+
When generating or auditing a tenant, ensure the following in order:
|
|
2543
|
+
|
|
2544
|
+
1. **Capsules** — For each section type, create **`src/components/<type>/`** with View.tsx, schema.ts, types.ts, index.ts. Data schema extends BaseSectionData; array items extend BaseArrayItem; View complies with CIP and IDAC (§6.2–6.3 for non-reserved types).
|
|
2545
|
+
2. **Base schemas** — **src/lib/base-schemas.ts** exports BaseSectionData, BaseArrayItem, BaseSectionSettingsSchema (and optional CtaSchema or similar shared fragments).
|
|
2546
|
+
3. **types.ts** — Define SectionComponentPropsMap (header with **menu**), PageConfig, SiteConfig, MenuConfig, ThemeConfig; **declare module '@olonjs/core'** and augment SectionDataRegistry and SectionSettingsRegistry; re-export from `@olonjs/core`.
|
|
2547
|
+
4. **ComponentRegistry** — Import every View; build object **{ [K in SectionType]: ViewComponent }**; type as **{ [K in SectionType]: React.FC<SectionComponentPropsMap[K]> }**.
|
|
2548
|
+
5. **schemas.ts** — Import base schemas and each capsule’s data schema; export SECTION_SCHEMAS as **{ [K in SectionType]: SchemaK }**; export SectionType as **keyof typeof SECTION_SCHEMAS** if not using Core’s SectionType.
|
|
2549
|
+
6. **addSectionConfig** — addableSectionTypes, sectionTypeLabels, getDefaultSectionData; export as AddSectionConfig.
|
|
2550
|
+
7. **App.tsx** — Import site, theme, menu, pages from data paths; build config (tenantId, registry, schemas, pages, siteConfig, themeConfig, menuConfig, themeCss: { tenant }, addSection); render JsonPagesEngine.
|
|
2551
|
+
8. **Data files** — Create or update site.json, menu.json, theme.json, and one or more **<slug>.json** under the paths in A.4. Ensure JSON shapes match SiteConfig, MenuConfig, ThemeConfig, PageConfig.
|
|
2552
|
+
9. **Tenant CSS** — Include TOCC (§7) selectors in global CSS so the Stage overlay is visible.
|
|
2553
|
+
10. **Reserved types** — Header and footer capsules receive props per SectionComponentPropsMap; menu is populated from menuConfig (e.g. menuConfig.main) when building the config or inside Core when rendering the header.
|
|
2554
|
+
|
|
2555
|
+
**Perché servono (A.5):** La checklist in ordine evita di dimenticare passi (es. augmentation prima del registry, TOCC dopo le View) e rende la spec sufficiente per generare o verificare un tenant senza codebase di riferimento.
|
|
2556
|
+
|
|
2557
|
+
---
|
|
2558
|
+
|
|
2559
|
+
## A.6 v1.3 Path/Nested Strictness Addendum (breaking)
|
|
2560
|
+
|
|
2561
|
+
This addendum extends Appendix A without removing prior v1.2 obligations:
|
|
2562
|
+
|
|
2563
|
+
1. **Type exports** — Core and/or shared types module should expose `SelectionPathSegment` and `SelectionPath` for Studio messaging and Inspector expansion logic.
|
|
2564
|
+
2. **Protocol migration** — Replace flat payload fields `itemField` / `itemId` with `itemPath?: SelectionPath` in strict v1.3 channels.
|
|
2565
|
+
3. **Nested array compliance** — For editable object arrays, item identity must be stable (`id`) and propagated to DOM attributes (`data-jp-item-id`), schema items (BaseArrayItem), and selection path segments (`itemId` when segment targets array item).
|
|
2566
|
+
4. **Backward compatibility policy** — Legacy flat fields may exist only in transitional adapters outside strict mode; normative v1.3 contract is path-only.
|
|
2567
|
+
|
|
2568
|
+
---
|
|
2569
|
+
|
|
2570
|
+
**Validation:** Align with current `@olonjs/core` exports (SectionType, MenuItem, AddSectionConfig, JsonPagesConfig, and in v1.3 path types for Studio selection).
|
|
2571
|
+
**Distribution:** Core via `.yalc`; tenant projections via `@olonjs/cli`. This annex makes the spec **necessary and sufficient** for tenant code-generation and governance at enterprise grade.
|
|
2572
|
+
|
|
919
2573
|
END_OF_FILE_CONTENT
|
|
920
2574
|
mkdir -p "src"
|
|
921
2575
|
echo "Creating src/App.tsx..."
|
|
@@ -6089,19 +7743,19 @@ cat << 'END_OF_FILE_CONTENT' > "src/data/config/menu.json"
|
|
|
6089
7743
|
{
|
|
6090
7744
|
"main": [
|
|
6091
7745
|
{
|
|
6092
|
-
"label": "
|
|
6093
|
-
"href": "#
|
|
7746
|
+
"label": "The Problem",
|
|
7747
|
+
"href": "#problem"
|
|
6094
7748
|
},
|
|
6095
7749
|
{
|
|
6096
|
-
"label": "
|
|
6097
|
-
"href": "#
|
|
7750
|
+
"label": "Architecture",
|
|
7751
|
+
"href": "#architecture"
|
|
6098
7752
|
},
|
|
6099
7753
|
{
|
|
6100
|
-
"label": "
|
|
6101
|
-
"href": "#
|
|
7754
|
+
"label": "Why",
|
|
7755
|
+
"href": "#why"
|
|
6102
7756
|
},
|
|
6103
7757
|
{
|
|
6104
|
-
"label": "
|
|
7758
|
+
"label": "DX",
|
|
6105
7759
|
"href": "#devex"
|
|
6106
7760
|
}
|
|
6107
7761
|
]
|
|
@@ -6142,19 +7796,19 @@ cat << 'END_OF_FILE_CONTENT' > "src/data/config/site.json"
|
|
|
6142
7796
|
"badge": "v1.4.0",
|
|
6143
7797
|
"links": [
|
|
6144
7798
|
{
|
|
6145
|
-
"label": "
|
|
6146
|
-
"href": "#
|
|
7799
|
+
"label": "The Problem",
|
|
7800
|
+
"href": "#problem"
|
|
6147
7801
|
},
|
|
6148
7802
|
{
|
|
6149
|
-
"label": "
|
|
6150
|
-
"href": "#
|
|
7803
|
+
"label": "Architecture",
|
|
7804
|
+
"href": "#architecture"
|
|
6151
7805
|
},
|
|
6152
7806
|
{
|
|
6153
|
-
"label": "
|
|
6154
|
-
"href": "#
|
|
7807
|
+
"label": "Why",
|
|
7808
|
+
"href": "#why"
|
|
6155
7809
|
},
|
|
6156
7810
|
{
|
|
6157
|
-
"label": "
|
|
7811
|
+
"label": "DX",
|
|
6158
7812
|
"href": "#devex"
|
|
6159
7813
|
}
|
|
6160
7814
|
]
|
|
@@ -6263,8 +7917,18 @@ cat << 'END_OF_FILE_CONTENT' > "src/data/pages/home.json"
|
|
|
6263
7917
|
"titleHighlight": "Agentic Web",
|
|
6264
7918
|
"description": "AI agents are becoming operational actors in commerce, marketing, and support. OlonJS introduces a deterministic machine contract for websites — so agents can reliably read and operate any site, without custom glue.",
|
|
6265
7919
|
"ctas": [
|
|
6266
|
-
{
|
|
6267
|
-
|
|
7920
|
+
{
|
|
7921
|
+
"id": "cta-1",
|
|
7922
|
+
"label": "Read the Spec",
|
|
7923
|
+
"href": "/docs",
|
|
7924
|
+
"variant": "primary"
|
|
7925
|
+
},
|
|
7926
|
+
{
|
|
7927
|
+
"id": "cta-2",
|
|
7928
|
+
"label": "View on GitHub",
|
|
7929
|
+
"href": "https://github.com/olonjs/npm-jpcore",
|
|
7930
|
+
"variant": "secondary"
|
|
7931
|
+
}
|
|
6268
7932
|
],
|
|
6269
7933
|
"metrics": []
|
|
6270
7934
|
},
|
|
@@ -6279,16 +7943,35 @@ cat << 'END_OF_FILE_CONTENT' > "src/data/pages/home.json"
|
|
|
6279
7943
|
"problemTag": "The problem",
|
|
6280
7944
|
"problemTitle": "Websites aren't built for agents",
|
|
6281
7945
|
"problemItems": [
|
|
6282
|
-
{
|
|
6283
|
-
|
|
6284
|
-
|
|
7946
|
+
{
|
|
7947
|
+
"id": "pi-1",
|
|
7948
|
+
"text": "Agentic workflows are growing, but integration is mostly custom glue — rebuilt tenant by tenant"
|
|
7949
|
+
},
|
|
7950
|
+
{
|
|
7951
|
+
"id": "pi-2",
|
|
7952
|
+
"text": "Every site has a different content structure, routing assumptions, and edge cases"
|
|
7953
|
+
},
|
|
7954
|
+
{
|
|
7955
|
+
"id": "pi-3",
|
|
7956
|
+
"text": "HTML-heavy, CMS-fragmented, inconsistent across properties — slow, brittle, expensive"
|
|
7957
|
+
}
|
|
6285
7958
|
],
|
|
6286
7959
|
"solutionTag": "Our solution",
|
|
6287
7960
|
"solutionTitle": "A standard machine contract across tenants",
|
|
6288
7961
|
"solutionItems": [
|
|
6289
|
-
{
|
|
6290
|
-
|
|
6291
|
-
|
|
7962
|
+
{
|
|
7963
|
+
"id": "si-1",
|
|
7964
|
+
"text": "Predictable page endpoints for agents —",
|
|
7965
|
+
"code": "/{slug}.json"
|
|
7966
|
+
},
|
|
7967
|
+
{
|
|
7968
|
+
"id": "si-2",
|
|
7969
|
+
"text": "Typed, schema-driven content contracts — validated, versioned, auditable"
|
|
7970
|
+
},
|
|
7971
|
+
{
|
|
7972
|
+
"id": "si-3",
|
|
7973
|
+
"text": "Repeatable governance and deployment patterns across every tenant"
|
|
7974
|
+
}
|
|
6292
7975
|
]
|
|
6293
7976
|
},
|
|
6294
7977
|
"settings": {}
|
|
@@ -6302,15 +7985,47 @@ cat << 'END_OF_FILE_CONTENT' > "src/data/pages/home.json"
|
|
|
6302
7985
|
"sectionTitle": "Built for enterprise scale",
|
|
6303
7986
|
"sectionLead": "Every layer is designed for determinism — from file system layout to component contracts to Studio UX.",
|
|
6304
7987
|
"cards": [
|
|
6305
|
-
{
|
|
6306
|
-
|
|
6307
|
-
|
|
6308
|
-
|
|
6309
|
-
|
|
6310
|
-
|
|
7988
|
+
{
|
|
7989
|
+
"id": "fc-1",
|
|
7990
|
+
"emoji": "📐",
|
|
7991
|
+
"title": "Modular Type Registry",
|
|
7992
|
+
"description": "Core defines empty registries; tenants inject types via module augmentation. Full TypeScript safety, zero Core changes."
|
|
7993
|
+
},
|
|
7994
|
+
{
|
|
7995
|
+
"id": "fc-2",
|
|
7996
|
+
"emoji": "🧱",
|
|
7997
|
+
"title": "Tenant Block Protocol",
|
|
7998
|
+
"description": "Self-contained capsules (View + schema + types) enable automated ingestion and consistent editor generation."
|
|
7999
|
+
},
|
|
8000
|
+
{
|
|
8001
|
+
"id": "fc-3",
|
|
8002
|
+
"emoji": "⚙️",
|
|
8003
|
+
"title": "Deterministic CLI",
|
|
8004
|
+
"description": "@olonjs/cli projects new tenants from a canonical script — reproducible across every environment."
|
|
8005
|
+
},
|
|
8006
|
+
{
|
|
8007
|
+
"id": "fc-4",
|
|
8008
|
+
"emoji": "🎯",
|
|
8009
|
+
"title": "ICE Data Contract",
|
|
8010
|
+
"description": "Mandatory DOM attributes bind the Studio canvas to Inspector fields without coupling to tenant DOM structure."
|
|
8011
|
+
},
|
|
8012
|
+
{
|
|
8013
|
+
"id": "fc-5",
|
|
8014
|
+
"emoji": "📦",
|
|
8015
|
+
"title": "Base Schema Fragments",
|
|
8016
|
+
"description": "Shared BaseSectionData and BaseArrayItem enforce anchor IDs and stable React keys across all capsules."
|
|
8017
|
+
},
|
|
8018
|
+
{
|
|
8019
|
+
"id": "fc-6",
|
|
8020
|
+
"emoji": "🔗",
|
|
8021
|
+
"title": "Path-Based Selection",
|
|
8022
|
+
"description": "v1.4 strict path semantics eliminate nested array ambiguity. Studio selection is root-to-leaf, always deterministic."
|
|
8023
|
+
}
|
|
6311
8024
|
]
|
|
6312
8025
|
},
|
|
6313
|
-
"settings": {
|
|
8026
|
+
"settings": {
|
|
8027
|
+
"columns": 3
|
|
8028
|
+
}
|
|
6314
8029
|
},
|
|
6315
8030
|
{
|
|
6316
8031
|
"id": "why-now",
|
|
@@ -6321,10 +8036,26 @@ cat << 'END_OF_FILE_CONTENT' > "src/data/pages/home.json"
|
|
|
6321
8036
|
"title": "Why this matters",
|
|
6322
8037
|
"titleAccent": "now",
|
|
6323
8038
|
"cards": [
|
|
6324
|
-
{
|
|
6325
|
-
|
|
6326
|
-
|
|
6327
|
-
|
|
8039
|
+
{
|
|
8040
|
+
"id": "wc-1",
|
|
8041
|
+
"title": "Agentic commerce is live",
|
|
8042
|
+
"description": "Operational standards are missing. Without a contract layer, teams face high integration cost and low reliability."
|
|
8043
|
+
},
|
|
8044
|
+
{
|
|
8045
|
+
"id": "wc-2",
|
|
8046
|
+
"title": "Enterprises need governance",
|
|
8047
|
+
"description": "A contract layer you can audit, version, and scale — not a one-off adapter for every new agent workflow."
|
|
8048
|
+
},
|
|
8049
|
+
{
|
|
8050
|
+
"id": "wc-3",
|
|
8051
|
+
"title": "AI tooling is ready",
|
|
8052
|
+
"description": "Deterministic structure means AI can scaffold, validate, and evolve tenants with less prompt ambiguity."
|
|
8053
|
+
},
|
|
8054
|
+
{
|
|
8055
|
+
"id": "wc-4",
|
|
8056
|
+
"title": "Speed compounds",
|
|
8057
|
+
"description": "Teams that standardize now ship new experiences in hours while others rebuild integration logic repeatedly."
|
|
8058
|
+
}
|
|
6328
8059
|
]
|
|
6329
8060
|
},
|
|
6330
8061
|
"settings": {}
|
|
@@ -6333,19 +8064,40 @@ cat << 'END_OF_FILE_CONTENT' > "src/data/pages/home.json"
|
|
|
6333
8064
|
"id": "dx-section",
|
|
6334
8065
|
"type": "devex",
|
|
6335
8066
|
"data": {
|
|
6336
|
-
"anchorId": "
|
|
8067
|
+
"anchorId": "devex",
|
|
6337
8068
|
"label": "Developer Velocity",
|
|
6338
8069
|
"title": "AI-native advantage,\nfrom day one",
|
|
6339
8070
|
"description": "OlonJS dramatically increases AI-assisted development speed. Because structure is deterministic, agents scaffold and evolve tenants faster — with lower regression risk.",
|
|
6340
8071
|
"features": [
|
|
6341
|
-
{
|
|
6342
|
-
|
|
6343
|
-
|
|
8072
|
+
{
|
|
8073
|
+
"id": "df-1",
|
|
8074
|
+
"text": "AI scaffolds and evolves tenants faster because structure is deterministic"
|
|
8075
|
+
},
|
|
8076
|
+
{
|
|
8077
|
+
"id": "df-2",
|
|
8078
|
+
"text": "Shared conventions reduce prompt ambiguity and implementation drift"
|
|
8079
|
+
},
|
|
8080
|
+
{
|
|
8081
|
+
"id": "df-3",
|
|
8082
|
+
"text": "Ship new tenant experiences in hours, not weeks"
|
|
8083
|
+
}
|
|
6344
8084
|
],
|
|
6345
8085
|
"stats": [
|
|
6346
|
-
{
|
|
6347
|
-
|
|
6348
|
-
|
|
8086
|
+
{
|
|
8087
|
+
"id": "ds-1",
|
|
8088
|
+
"value": "10×",
|
|
8089
|
+
"label": "Faster scaffolding"
|
|
8090
|
+
},
|
|
8091
|
+
{
|
|
8092
|
+
"id": "ds-2",
|
|
8093
|
+
"value": "∅",
|
|
8094
|
+
"label": "Glue per tenant"
|
|
8095
|
+
},
|
|
8096
|
+
{
|
|
8097
|
+
"id": "ds-3",
|
|
8098
|
+
"value": "100%",
|
|
8099
|
+
"label": "Type-safe contracts"
|
|
8100
|
+
}
|
|
6349
8101
|
]
|
|
6350
8102
|
},
|
|
6351
8103
|
"settings": {}
|
|
@@ -6359,15 +8111,24 @@ cat << 'END_OF_FILE_CONTENT' > "src/data/pages/home.json"
|
|
|
6359
8111
|
"description": "Read the full specification or explore the source on GitHub. Zero dependencies to start — one JSON endpoint per page.",
|
|
6360
8112
|
"cliCommand": "npx @olonjs/cli@latest new tenant",
|
|
6361
8113
|
"ctas": [
|
|
6362
|
-
{
|
|
6363
|
-
|
|
8114
|
+
{
|
|
8115
|
+
"id": "cta-docs",
|
|
8116
|
+
"label": "Read the Specification",
|
|
8117
|
+
"href": "/docs",
|
|
8118
|
+
"variant": "primary"
|
|
8119
|
+
},
|
|
8120
|
+
{
|
|
8121
|
+
"id": "cta-gh",
|
|
8122
|
+
"label": "View on GitHub",
|
|
8123
|
+
"href": "https://github.com/olonjs/npm-jpcore",
|
|
8124
|
+
"variant": "secondary"
|
|
8125
|
+
}
|
|
6364
8126
|
]
|
|
6365
8127
|
},
|
|
6366
8128
|
"settings": {}
|
|
6367
8129
|
}
|
|
6368
8130
|
]
|
|
6369
8131
|
}
|
|
6370
|
-
|
|
6371
8132
|
END_OF_FILE_CONTENT
|
|
6372
8133
|
echo "Creating src/data/pages/post.json..."
|
|
6373
8134
|
cat << 'END_OF_FILE_CONTENT' > "src/data/pages/post.json"
|