@olonjs/cli 3.0.87 → 3.0.88
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 +2004 -350
- package/assets/templates/agritourism/src_tenant.sh +1 -1
- package/assets/templates/alpha/src_tenant.sh +2004 -350
- 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
|
|
20
|
+
|
|
21
|
+
Create project rules in `.cursor/rules/` to provide persistent context for the AI agent.
|
|
22
|
+
|
|
23
|
+
## Gather Requirements
|
|
24
|
+
|
|
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.
|
|
34
|
+
|
|
35
|
+
### Required Questions
|
|
36
|
+
|
|
37
|
+
If the user hasn't specified scope, ask:
|
|
38
|
+
- "Should this rule always apply, or only when working with specific files?"
|
|
39
|
+
|
|
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`)
|
|
10
42
|
|
|
11
|
-
|
|
43
|
+
It's very important that we get clarity on the file patterns.
|
|
12
44
|
|
|
13
|
-
|
|
45
|
+
Use the AskQuestion tool when available to gather this efficiently.
|
|
14
46
|
|
|
15
47
|
---
|
|
16
48
|
|
|
17
|
-
##
|
|
49
|
+
## Rule File Format
|
|
50
|
+
|
|
51
|
+
Rules are `.mdc` files in `.cursor/rules/` with YAML frontmatter:
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
.cursor/rules/
|
|
55
|
+
typescript-standards.mdc
|
|
56
|
+
react-patterns.mdc
|
|
57
|
+
api-conventions.mdc
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### File Structure
|
|
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
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
# Rule Title
|
|
70
|
+
|
|
71
|
+
Your rule content here...
|
|
72
|
+
```
|
|
73
|
+
|
|
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 |
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Rule Configurations
|
|
85
|
+
|
|
86
|
+
### Always Apply
|
|
87
|
+
|
|
88
|
+
For universal standards that should apply to every conversation:
|
|
89
|
+
|
|
90
|
+
```yaml
|
|
91
|
+
---
|
|
92
|
+
description: Core coding standards for the project
|
|
93
|
+
alwaysApply: true
|
|
94
|
+
---
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Apply to Specific Files
|
|
98
|
+
|
|
99
|
+
For rules that apply when working with certain file types:
|
|
100
|
+
|
|
101
|
+
```yaml
|
|
102
|
+
---
|
|
103
|
+
description: TypeScript conventions for this project
|
|
104
|
+
globs: **/*.ts
|
|
105
|
+
alwaysApply: false
|
|
106
|
+
---
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
18
110
|
|
|
19
|
-
|
|
20
|
-
|
|
111
|
+
## Best Practices
|
|
112
|
+
|
|
113
|
+
### Keep Rules Concise
|
|
114
|
+
|
|
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
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Example Rules
|
|
123
|
+
|
|
124
|
+
### TypeScript Standards
|
|
125
|
+
|
|
126
|
+
```markdown
|
|
127
|
+
---
|
|
128
|
+
description: TypeScript coding standards
|
|
129
|
+
globs: **/*.ts
|
|
130
|
+
alwaysApply: false
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
# Error Handling
|
|
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
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
# React Patterns
|
|
161
|
+
|
|
162
|
+
- Use functional components
|
|
163
|
+
- Extract custom hooks for reusable logic
|
|
164
|
+
- Colocate styles with components
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Checklist
|
|
170
|
+
|
|
171
|
+
- [ ] File is `.mdc` format in `.cursor/rules/`
|
|
172
|
+
- [ ] Frontmatter configured correctly
|
|
173
|
+
- [ ] Content under 500 lines
|
|
174
|
+
- [ ] Includes concrete examples
|
|
175
|
+
|
|
176
|
+
END_OF_FILE_CONTENT
|
|
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
|
|
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.
|
|
190
|
+
|
|
191
|
+
## Before You Begin: Gather Requirements
|
|
192
|
+
|
|
193
|
+
Before creating a skill, gather essential information from the user about:
|
|
194
|
+
|
|
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?
|
|
201
|
+
|
|
202
|
+
### Inferring from Context
|
|
203
|
+
|
|
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
|
|
207
|
+
|
|
208
|
+
If you need clarification, use the AskQuestion tool when available:
|
|
209
|
+
|
|
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
|
+
```
|
|
21
215
|
|
|
22
|
-
|
|
216
|
+
If the AskQuestion tool is not available, ask these questions conversationally.
|
|
23
217
|
|
|
24
218
|
---
|
|
25
219
|
|
|
26
|
-
##
|
|
220
|
+
## Skill File Structure
|
|
27
221
|
|
|
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`)***.
|
|
222
|
+
### Directory Layout
|
|
34
223
|
|
|
35
|
-
|
|
224
|
+
Skills are stored as directories containing a `SKILL.md` file:
|
|
36
225
|
|
|
37
|
-
|
|
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
|
+
```
|
|
235
|
+
|
|
236
|
+
### Storage Locations
|
|
237
|
+
|
|
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 |
|
|
242
|
+
|
|
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.
|
|
244
|
+
|
|
245
|
+
### SKILL.md Structure
|
|
38
246
|
|
|
247
|
+
Every skill requires a `SKILL.md` file with YAML frontmatter and markdown body:
|
|
248
|
+
|
|
249
|
+
```markdown
|
|
250
|
+
---
|
|
251
|
+
name: your-skill-name
|
|
252
|
+
description: Brief description of what this skill does and when to use it
|
|
39
253
|
---
|
|
40
254
|
|
|
41
|
-
|
|
255
|
+
# Your Skill Name
|
|
256
|
+
|
|
257
|
+
## Instructions
|
|
258
|
+
Clear, step-by-step guidance for the agent.
|
|
259
|
+
|
|
260
|
+
## Examples
|
|
261
|
+
Concrete examples of using this skill.
|
|
262
|
+
```
|
|
42
263
|
|
|
43
|
-
|
|
44
|
-
- **Niente obbligo di capsule "piene":** puoi avere solo `View.tsx` (e magari un `index.ts` che esporta la View). Schema Zod e types servono solo se vuoi type-safety in sviluppo o se in futuro attivi il CMS.
|
|
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.
|
|
264
|
+
### Required Metadata Fields
|
|
47
265
|
|
|
48
|
-
|
|
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 |
|
|
49
270
|
|
|
50
271
|
---
|
|
51
272
|
|
|
52
|
-
##
|
|
273
|
+
## Writing Effective Descriptions
|
|
53
274
|
|
|
54
|
-
|
|
275
|
+
The description is **critical** for skill discovery. The agent uses it to decide when to apply your skill.
|
|
55
276
|
|
|
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).
|
|
277
|
+
### Description Best Practices
|
|
58
278
|
|
|
59
|
-
**
|
|
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"
|
|
283
|
+
|
|
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)
|
|
291
|
+
|
|
292
|
+
### Description Examples
|
|
293
|
+
|
|
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.
|
|
297
|
+
|
|
298
|
+
# Excel Analysis
|
|
299
|
+
description: Analyze Excel spreadsheets, create pivot tables, generate charts. Use when analyzing Excel files, spreadsheets, tabular data, or .xlsx files.
|
|
300
|
+
|
|
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
|
+
```
|
|
60
307
|
|
|
61
308
|
---
|
|
62
309
|
|
|
63
|
-
##
|
|
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.
|
|
64
315
|
|
|
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.
|
|
316
|
+
**Default assumption**: The agent is already very smart. Only add context it doesn't already have.
|
|
68
317
|
|
|
69
|
-
|
|
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?"
|
|
70
322
|
|
|
71
|
-
**
|
|
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:
|
|
371
|
+
|
|
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 |
|
|
72
377
|
|
|
73
378
|
---
|
|
74
379
|
|
|
75
|
-
##
|
|
380
|
+
## Common Patterns
|
|
381
|
+
|
|
382
|
+
### Template Pattern
|
|
76
383
|
|
|
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.
|
|
384
|
+
Provide output format templates:
|
|
81
385
|
|
|
82
|
-
|
|
386
|
+
```markdown
|
|
387
|
+
## Report structure
|
|
83
388
|
|
|
84
|
-
|
|
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:
|
|
441
|
+
|
|
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
|
+
\`\`\`
|
|
450
|
+
|
|
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
|
|
467
|
+
|
|
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
|
+
```
|
|
85
489
|
|
|
86
490
|
---
|
|
87
491
|
|
|
88
|
-
##
|
|
492
|
+
## Utility Scripts
|
|
493
|
+
|
|
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
|
|
499
|
+
|
|
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
|
+
\`\`\`
|
|
89
507
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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. |
|
|
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.
|
|
100
516
|
|
|
101
517
|
---
|
|
102
518
|
|
|
103
|
-
##
|
|
519
|
+
## Anti-Patterns to Avoid
|
|
520
|
+
|
|
521
|
+
### 1. Windows-Style Paths
|
|
522
|
+
- ✅ Use: `scripts/helper.py`
|
|
523
|
+
- ❌ Avoid: `scripts\helper.py`
|
|
104
524
|
|
|
105
|
-
|
|
525
|
+
### 2. Too Many Options
|
|
526
|
+
```markdown
|
|
527
|
+
# Bad - confusing
|
|
528
|
+
"You can use pypdf, or pdfplumber, or PyMuPDF, or..."
|
|
529
|
+
|
|
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
|
+
```
|
|
550
|
+
|
|
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")
|
|
555
|
+
|
|
556
|
+
### 5. Vague Skill Names
|
|
557
|
+
- ✅ Good: `processing-pdfs`, `analyzing-spreadsheets`
|
|
558
|
+
- ❌ Avoid: `helper`, `utils`, `tools`
|
|
559
|
+
|
|
560
|
+
---
|
|
561
|
+
|
|
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
|
|
598
|
+
|
|
599
|
+
---
|
|
600
|
+
|
|
601
|
+
## Complete Example
|
|
602
|
+
|
|
603
|
+
Here's a complete example of a well-structured skill:
|
|
604
|
+
|
|
605
|
+
**Directory structure:**
|
|
606
|
+
```
|
|
607
|
+
code-review/
|
|
608
|
+
├── SKILL.md
|
|
609
|
+
├── STANDARDS.md
|
|
610
|
+
└── examples.md
|
|
611
|
+
```
|
|
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.
|
|
618
|
+
---
|
|
619
|
+
|
|
620
|
+
# Code Review
|
|
621
|
+
|
|
622
|
+
## Quick Start
|
|
623
|
+
|
|
624
|
+
When reviewing code:
|
|
625
|
+
|
|
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
|
|
630
|
+
|
|
631
|
+
## Review Checklist
|
|
632
|
+
|
|
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
|
|
639
|
+
|
|
640
|
+
## Providing Feedback
|
|
641
|
+
|
|
642
|
+
Format feedback as:
|
|
643
|
+
- 🔴 **Critical**: Must fix before merge
|
|
644
|
+
- 🟡 **Suggestion**: Consider improving
|
|
645
|
+
- 🟢 **Nice to have**: Optional enhancement
|
|
646
|
+
|
|
647
|
+
## Additional Resources
|
|
648
|
+
|
|
649
|
+
- For detailed coding standards, see [STANDARDS.md](STANDARDS.md)
|
|
650
|
+
- For example reviews, see [examples.md](examples.md)
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
---
|
|
654
|
+
|
|
655
|
+
## Summary Checklist
|
|
656
|
+
|
|
657
|
+
Before finalizing a skill, verify:
|
|
658
|
+
|
|
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
|
|
666
|
+
|
|
667
|
+
### Structure
|
|
668
|
+
- [ ] File references are one level deep
|
|
669
|
+
- [ ] Progressive disclosure used appropriately
|
|
670
|
+
- [ ] Workflows have clear steps
|
|
671
|
+
- [ ] No time-sensitive information
|
|
672
|
+
|
|
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
|
|
106
678
|
|
|
107
679
|
END_OF_FILE_CONTENT
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
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"
|
|
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
|
|
692
|
+
|
|
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.
|
|
694
|
+
|
|
695
|
+
## When to Use Subagents
|
|
111
696
|
|
|
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
|
|
112
701
|
|
|
702
|
+
### Inferring from Context
|
|
113
703
|
|
|
114
|
-
|
|
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.
|
|
115
705
|
|
|
116
|
-
|
|
706
|
+
## Subagent Locations
|
|
117
707
|
|
|
118
|
-
|
|
708
|
+
| Location | Scope | Priority |
|
|
709
|
+
|----------|-------|----------|
|
|
710
|
+
| `.cursor/agents/` | Current project | Higher |
|
|
711
|
+
| `~/.cursor/agents/` | All your projects | Lower |
|
|
119
712
|
|
|
713
|
+
When multiple subagents share the same name, the higher-priority location wins.
|
|
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
|
|
120
724
|
---
|
|
725
|
+
name: code-reviewer
|
|
726
|
+
description: Reviews code for quality and best practices
|
|
727
|
+
---
|
|
728
|
+
|
|
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!) |
|
|
121
739
|
|
|
122
|
-
##
|
|
740
|
+
## Writing Effective Descriptions
|
|
123
741
|
|
|
124
|
-
|
|
125
|
-
- **Data:** Where pages get their data (JSON files, API, external CMS) and how they are passed to the engine (config + pages).
|
|
742
|
+
The description is **critical** - the AI uses it to decide when to delegate.
|
|
126
743
|
|
|
127
|
-
|
|
744
|
+
```yaml
|
|
745
|
+
# ❌ Too vague
|
|
746
|
+
description: Helps with code
|
|
128
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
|
|
757
|
+
|
|
758
|
+
```markdown
|
|
129
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
|
+
---
|
|
763
|
+
|
|
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
|
+
```
|
|
130
788
|
|
|
131
|
-
|
|
789
|
+
### Debugger
|
|
132
790
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
- **`src/App.tsx`** — Loads site, menu, theme, pages; builds the config; renders **`<JsonPagesEngine config={config} />`**.
|
|
791
|
+
```markdown
|
|
792
|
+
---
|
|
793
|
+
name: debugger
|
|
794
|
+
description: Debugging specialist for errors, test failures, and unexpected behavior. Use proactively when encountering any issues.
|
|
795
|
+
---
|
|
139
796
|
|
|
140
|
-
|
|
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
|
+
```
|
|
141
822
|
|
|
142
|
-
|
|
823
|
+
### Data Scientist
|
|
143
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.
|
|
144
829
|
---
|
|
145
830
|
|
|
146
|
-
|
|
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
|
+
```
|
|
855
|
+
|
|
856
|
+
## Subagent Creation Workflow
|
|
857
|
+
|
|
858
|
+
### Step 1: Decide the Scope
|
|
859
|
+
|
|
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
|
+
```
|
|
147
874
|
|
|
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.
|
|
875
|
+
### Step 3: Define Configuration
|
|
152
876
|
|
|
153
|
-
|
|
877
|
+
Write the frontmatter with the required fields (`name` and `description`).
|
|
154
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
|
+
```
|
|
894
|
+
|
|
895
|
+
## Best Practices
|
|
896
|
+
|
|
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
|
|
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"
|
|
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
|
|
1058
|
+
|
|
1059
|
+
Images:
|
|
1060
|
+
|
|
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.
|
|
1064
|
+
|
|
1065
|
+
Rich editorial content:
|
|
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
|
|
155
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.**
|
|
156
1121
|
|
|
157
|
-
##
|
|
1122
|
+
## Locations
|
|
158
1123
|
|
|
159
|
-
|
|
1124
|
+
| Level | Source | Destination |
|
|
1125
|
+
|-------|--------|-------------|
|
|
1126
|
+
| Project | `{workspaceFolder}/**/.cursor/rules/*.mdc`, `{workspaceFolder}/.cursor/commands/*.md` |
|
|
1127
|
+
| User | `~/.cursor/commands/*.md` |
|
|
160
1128
|
|
|
161
|
-
|
|
162
|
-
-
|
|
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.
|
|
163
1133
|
|
|
164
|
-
|
|
1134
|
+
## Finding Files to Migrate
|
|
165
1135
|
|
|
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
|
|
166
1150
|
---
|
|
1151
|
+
# Title
|
|
1152
|
+
Body content...
|
|
1153
|
+
```
|
|
167
1154
|
|
|
168
|
-
|
|
1155
|
+
```markdown
|
|
1156
|
+
# After: .cursor/skills/my-rule/SKILL.md
|
|
1157
|
+
---
|
|
1158
|
+
name: my-rule
|
|
1159
|
+
description: What this rule does
|
|
1160
|
+
---
|
|
1161
|
+
# Title
|
|
1162
|
+
Body content...
|
|
1163
|
+
```
|
|
169
1164
|
|
|
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.
|
|
1165
|
+
Changes: Add `name` field, remove `globs`/`alwaysApply`, keep body exactly.
|
|
173
1166
|
|
|
174
|
-
|
|
1167
|
+
### Commands: .md → SKILL.md
|
|
175
1168
|
|
|
176
|
-
|
|
1169
|
+
```markdown
|
|
1170
|
+
# Before: .cursor/commands/commit.md
|
|
1171
|
+
# Commit current work
|
|
1172
|
+
Instructions here...
|
|
1173
|
+
```
|
|
177
1174
|
|
|
1175
|
+
```markdown
|
|
1176
|
+
# After: .cursor/skills/commit/SKILL.md
|
|
178
1177
|
---
|
|
1178
|
+
name: commit
|
|
1179
|
+
description: Commit current work with standardized message format
|
|
1180
|
+
disable-model-invocation: true
|
|
1181
|
+
---
|
|
1182
|
+
# Commit current work
|
|
1183
|
+
Instructions here...
|
|
1184
|
+
```
|
|
179
1185
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
- **Registry:** An object mapping every `sectionType` (string) to the React component rendering that type. E.g.: `{ header: Header, footer: Footer, hero: Hero, ... }`. If not using Studio, you can type loosely (e.g., `Record<string, React.FC<any>>` or whatever is compatible with `JsonPagesConfig['registry']`).
|
|
183
|
-
- **Config passed to JsonPagesEngine:**
|
|
184
|
-
`tenantId`, `registry`, `pages`, `siteConfig`, `menuConfig`, `themeConfig` (or empty object), `themeCss: { tenant: cssString }`.
|
|
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.
|
|
1186
|
+
Changes: Add frontmatter with `name` (from filename), `description` (infer from content), and `disable-model-invocation: true`, keep body exactly.
|
|
186
1187
|
|
|
187
|
-
|
|
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.
|
|
188
1189
|
|
|
189
|
-
|
|
1190
|
+
## Notes
|
|
190
1191
|
|
|
191
|
-
|
|
1192
|
+
- `name` must be lowercase with hyphens only
|
|
1193
|
+
- `description` is critical for skill discovery
|
|
1194
|
+
- Optionally delete originals after verifying migration works
|
|
192
1195
|
|
|
193
|
-
|
|
1196
|
+
### Migrate a Rule (.mdc → SKILL.md)
|
|
194
1197
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
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. |
|
|
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
|
|
205
1204
|
|
|
206
|
-
|
|
1205
|
+
### Migrate a Command (.md → SKILL.md)
|
|
207
1206
|
|
|
208
|
-
|
|
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
|
|
209
1212
|
|
|
210
|
-
|
|
1213
|
+
**CRITICAL: Copy the body content character-for-character. Do not reformat, fix typos, or "improve" anything.**
|
|
211
1214
|
|
|
1215
|
+
## Workflow
|
|
212
1216
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
cat << 'END_OF_FILE_CONTENT' > "docs/02-Onboarding_Governance_CMS.md"
|
|
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.
|
|
216
1219
|
|
|
217
|
-
|
|
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.
|
|
218
1230
|
|
|
219
|
-
**Target:** Lead Developers & Architects setting up the **CMS** (Studio, ICE, Form Factory): in-app authoring, strong typing, content and component governance.
|
|
220
1231
|
|
|
221
|
-
|
|
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.
|
|
222
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.
|
|
223
1249
|
---
|
|
224
1250
|
|
|
225
|
-
|
|
1251
|
+
# OlonJS Tenant
|
|
226
1252
|
|
|
227
|
-
|
|
228
|
-
- **Schema:** Every section type has a Zod schema (data, and optionally settings) used by the Form Factory to generate the editor in the Inspector. Schemas are aggregated in `SECTION_SCHEMAS`.
|
|
229
|
-
- **Studio/ICE:** The editor (Inspector) hooks into the DOM via **data-jp-field** and **data-jp-item-id** / **data-jp-item-field**. The selection overlay in the iframe requires the **tenant** to provide the CSS (TOCC).
|
|
230
|
-
- **Add Section:** The tenant exposes **AddSectionConfig** (addable types, labels, default data) so the user can add sections from the library in Studio.
|
|
231
|
-
- **Design Tokens:** Views use CSS variables (`--local-*`) and no "naked" utilities (CIP) for consistency and compatibility with themes and overlays.
|
|
1253
|
+
Use this skill for work on the OlonJS ecosystem when the task involves:
|
|
232
1254
|
|
|
233
|
-
|
|
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
|
|
234
1261
|
|
|
235
|
-
|
|
1262
|
+
Read code first. Treat documents as secondary unless they help interpret code that is otherwise ambiguous.
|
|
236
1263
|
|
|
237
|
-
##
|
|
1264
|
+
## Architecture Specifications
|
|
238
1265
|
|
|
239
|
-
|
|
1266
|
+
Use this document as the architectural laws for each tenant, compliancy will be tested against these specs:
|
|
240
1267
|
|
|
241
|
-
|
|
1268
|
+
- `\\wsl.localhost\Ubuntu\home\dev\npm-jpcore\specs\olonjsSpecs_V.1.3.md`
|
|
242
1269
|
|
|
243
|
-
**CMS UX:** The Zod schema drives the **Form Factory** (which widget for which field: text, textarea, select, list, icon-picker, **image-picker**); **data-jp-field** and **data-jp-item-id/field** bind Stage clicks to Inspector forms; **AddSectionConfig** provides addable types, labels, and defaults. Result for the author: consistent forms, "Add Section" with sensible names and initial data, correct selection (click → right form), validation with clear errors. Without schema and typed contracts, the Inspector wouldn't know which fields to show or how to validate. Thus: for governance, typing guarantees **contracts**; for CMS UX, it defines the **editing experience**. Both must be specified.
|
|
244
1270
|
|
|
245
|
-
---
|
|
246
1271
|
|
|
247
|
-
## 2. Project Structure (Complete)
|
|
248
|
-
|
|
249
|
-
- **`src/data/config/site.json`** — SiteConfig (identity, pages[], header block, footer block).
|
|
250
|
-
- **`src/data/config/menu.json`** — MenuConfig (e.g., `main: MenuItem[]`).
|
|
251
|
-
- **`src/data/config/theme.json`** — ThemeConfig (tokens).
|
|
252
|
-
- **`src/data/pages/<slug>.json`** — PageConfig (slug, meta, sections[]). **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`).
|
|
253
|
-
- **`src/components/<sectionType>/`** — **Full Capsule:** View.tsx, schema.ts, types.ts, index.ts.
|
|
254
|
-
- **`src/lib/base-schemas.ts`** — BaseSectionData, BaseArrayItem, BaseSectionSettingsSchema.
|
|
255
|
-
- **`src/lib/schemas.ts`** — SECTION_SCHEMAS (aggregate of data schemas per type) + export SectionType.
|
|
256
|
-
- **`src/lib/ComponentRegistry.tsx`** — Typed Registry: `{ [K in SectionType]: React.FC<SectionComponentPropsMap[K]> }`.
|
|
257
|
-
- **`src/lib/addSectionConfig.ts`** — AddSectionConfig (addableSectionTypes, sectionTypeLabels, getDefaultSectionData).
|
|
258
|
-
- **`src/types.ts`** — SectionComponentPropsMap, PageConfig, SiteConfig, MenuConfig, ThemeConfig; **module augmentation** for SectionDataRegistry and SectionSettingsRegistry; re-export from `@olonjs/core`.
|
|
259
|
-
- **`src/App.tsx`** — Bootstrap: config (tenantId, registry, schemas, pages, siteConfig, themeConfig, menuConfig, themeCss, addSection); `<JsonPagesEngine config={config} />`.
|
|
260
|
-
- **Global CSS** — Includes TOCC selectors for overlay (hover/selected/type label).
|
|
261
1272
|
|
|
262
|
-
|
|
1273
|
+
## Core Model
|
|
263
1274
|
|
|
264
|
-
|
|
1275
|
+
OlonJS has a hard split between `core` and `tenant`.
|
|
265
1276
|
|
|
266
|
-
-
|
|
267
|
-
-
|
|
268
|
-
-
|
|
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).
|
|
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.
|
|
270
1280
|
|
|
271
|
-
|
|
1281
|
+
In this ecosystem, code is the source of truth.
|
|
272
1282
|
|
|
273
|
-
|
|
1283
|
+
Compliance priority:
|
|
274
1284
|
|
|
275
|
-
|
|
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.
|
|
276
1290
|
|
|
277
|
-
|
|
1291
|
+
## Canonical References
|
|
278
1292
|
|
|
279
|
-
|
|
1293
|
+
Use these local references when available:
|
|
280
1294
|
|
|
281
|
-
-
|
|
282
|
-
-
|
|
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`
|
|
283
1299
|
|
|
284
|
-
|
|
1300
|
+
If these paths are missing, infer the same roles from the current workspace:
|
|
285
1301
|
|
|
286
|
-
|
|
1302
|
+
- base CLI-generated tenant
|
|
1303
|
+
- branded tenant
|
|
1304
|
+
- core package
|
|
1305
|
+
- generator script
|
|
287
1306
|
|
|
288
|
-
|
|
289
|
-
import { z } from 'zod';
|
|
290
|
-
import { BaseSectionData } from '@/lib/base-schemas';
|
|
1307
|
+
## Tenant Anatomy
|
|
291
1308
|
|
|
292
|
-
|
|
293
|
-
.object({
|
|
294
|
-
url: z.string(),
|
|
295
|
-
alt: z.string().optional(),
|
|
296
|
-
})
|
|
297
|
-
.describe('ui:image-picker');
|
|
1309
|
+
Expect these files to move together:
|
|
298
1310
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
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`
|
|
305
1323
|
|
|
306
|
-
|
|
307
|
-
- The **`image`** field in the section data uses that schema (with default), so the Inspector shows the Image Picker widget for `image`.
|
|
1324
|
+
Useful rule: if a section type changes, check all of the files above before concluding the task is done.
|
|
308
1325
|
|
|
309
|
-
|
|
1326
|
+
## What Good Work Looks Like
|
|
310
1327
|
|
|
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.
|
|
1328
|
+
A good tenant change:
|
|
314
1329
|
|
|
315
|
-
|
|
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
|
|
316
1335
|
|
|
317
|
-
|
|
1336
|
+
A suspicious tenant change:
|
|
318
1337
|
|
|
319
|
-
-
|
|
320
|
-
-
|
|
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
|
|
321
1343
|
|
|
322
|
-
|
|
1344
|
+
## Workflow 1: Base Tenant -> Branded Tenant
|
|
323
1345
|
|
|
324
|
-
|
|
1346
|
+
This is the primary workflow.
|
|
325
1347
|
|
|
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.
|
|
1348
|
+
Goal:
|
|
328
1349
|
|
|
329
|
-
|
|
1350
|
+
- transform a CLI-generated base tenant into a branded tenant through a single generator script
|
|
330
1351
|
|
|
331
|
-
|
|
1352
|
+
Treat the generator script as procedural source of truth for the green build workflow.
|
|
332
1353
|
|
|
333
|
-
|
|
1354
|
+
When maintaining or authoring a generator:
|
|
334
1355
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
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.
|
|
339
1361
|
|
|
340
|
-
|
|
1362
|
+
Typical structure of a good generator:
|
|
341
1363
|
|
|
342
|
-
|
|
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
|
|
343
1369
|
|
|
344
|
-
|
|
1370
|
+
When asked to update a branded tenant generator:
|
|
345
1371
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
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.
|
|
350
1379
|
|
|
351
|
-
|
|
1380
|
+
## Workflow 2: Add Or Change A Section
|
|
352
1381
|
|
|
353
|
-
|
|
1382
|
+
When adding a new section type:
|
|
354
1383
|
|
|
355
|
-
|
|
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.
|
|
356
1390
|
|
|
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. |
|
|
1391
|
+
When changing an existing section:
|
|
371
1392
|
|
|
372
|
-
|
|
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.
|
|
373
1398
|
|
|
374
|
-
##
|
|
1399
|
+
## Workflow 3: Images, Rich Content, Nested Routes
|
|
375
1400
|
|
|
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).
|
|
1401
|
+
Images:
|
|
379
1402
|
|
|
380
|
-
|
|
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.
|
|
381
1406
|
|
|
382
|
-
|
|
383
|
-
END_OF_FILE_CONTENT
|
|
384
|
-
echo "Creating docs/02-Onboarding_Governance_completo_aggiornato.md..."
|
|
385
|
-
cat << 'END_OF_FILE_CONTENT' > "docs/02-Onboarding_Governance_completo_aggiornato.md"
|
|
386
|
-
# Onboarding — Percorso Governance (con CMS) — Versione completa
|
|
1407
|
+
Rich editorial content:
|
|
387
1408
|
|
|
388
|
-
|
|
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.
|
|
389
1411
|
|
|
390
|
-
|
|
1412
|
+
Nested routes:
|
|
391
1413
|
|
|
392
|
-
|
|
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.
|
|
393
1416
|
|
|
394
|
-
##
|
|
1417
|
+
## Decision Rules
|
|
395
1418
|
|
|
396
|
-
|
|
397
|
-
- **Schema:** Ogni section type ha uno schema Zod (data, e opzionalmente settings) usato dal Form Factory per generare l'editor nell'Inspector. Gli schema sono aggregati in `SECTION_SCHEMAS`.
|
|
398
|
-
- **Studio/ICE:** L'editor (Inspector) si aggancia al DOM tramite **data-jp-field** e **data-jp-item-id** / **data-jp-item-field**. L'overlay di selezione in iframe richiede che il **tenant** fornisca il CSS (TOCC).
|
|
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.
|
|
1419
|
+
Use `alpha` patterns when the task is about:
|
|
401
1420
|
|
|
402
|
-
|
|
1421
|
+
- tenant DNA
|
|
1422
|
+
- capability reference
|
|
1423
|
+
- baseline protocol shape
|
|
1424
|
+
- proving what the base system already supports
|
|
403
1425
|
|
|
404
|
-
|
|
1426
|
+
Use `gptgiorgio` patterns when the task is about:
|
|
405
1427
|
|
|
406
|
-
|
|
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
|
|
407
1432
|
|
|
408
|
-
|
|
1433
|
+
Do not treat `gptgiorgio` as canonical for legacy admin context awareness.
|
|
409
1434
|
|
|
410
|
-
|
|
1435
|
+
## Default Operating Procedure
|
|
411
1436
|
|
|
412
|
-
|
|
1437
|
+
When you receive a OlonJS tenant task:
|
|
413
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"
|
|
414
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
|
|
1457
|
+
---
|
|
1458
|
+
# Run Shell Commands
|
|
415
1459
|
|
|
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).
|
|
1460
|
+
Use this skill only when the user explicitly invokes `/shell`.
|
|
430
1461
|
|
|
431
|
-
|
|
1462
|
+
## Behavior
|
|
432
1463
|
|
|
433
|
-
|
|
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.
|
|
434
1469
|
|
|
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).
|
|
1470
|
+
## Response
|
|
439
1471
|
|
|
440
|
-
|
|
1472
|
+
- Run the command first.
|
|
1473
|
+
- Then briefly report the exit status and any important stdout or stderr.
|
|
441
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"
|
|
442
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.
|
|
1485
|
+
---
|
|
1486
|
+
# Updating Cursor Settings
|
|
443
1487
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
Per i **campi immagine** il Form Factory espone il widget **Image Picker** solo se lo schema è modellato correttamente.
|
|
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.
|
|
447
1489
|
|
|
448
|
-
|
|
1490
|
+
## Settings File Location
|
|
449
1491
|
|
|
450
|
-
|
|
451
|
-
|
|
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 |
|
|
452
1497
|
|
|
453
|
-
|
|
1498
|
+
## Before Modifying Settings
|
|
454
1499
|
|
|
455
|
-
**
|
|
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
|
|
456
1503
|
|
|
457
|
-
|
|
458
|
-
import { z } from 'zod';
|
|
459
|
-
import { BaseSectionData } from '@/lib/base-schemas';
|
|
1504
|
+
## Modifying Settings
|
|
460
1505
|
|
|
461
|
-
|
|
462
|
-
.object({
|
|
463
|
-
url: z.string(),
|
|
464
|
-
alt: z.string().optional(),
|
|
465
|
-
})
|
|
466
|
-
.describe('ui:image-picker');
|
|
1506
|
+
### Step 1: Read Current Settings
|
|
467
1507
|
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
});
|
|
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
|
|
473
1512
|
```
|
|
474
1513
|
|
|
475
|
-
|
|
476
|
-
- Il campo **`image`** nella section data usa quel schema (con default) così l'Inspector mostra il widget Image Picker per `image`.
|
|
1514
|
+
### Step 2: Identify the Setting to Change
|
|
477
1515
|
|
|
478
|
-
|
|
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.`
|
|
479
1522
|
|
|
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.
|
|
1523
|
+
### Step 3: Update the Setting
|
|
483
1524
|
|
|
484
|
-
|
|
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)
|
|
485
1530
|
|
|
486
|
-
###
|
|
1531
|
+
### Example: Changing Font Size
|
|
487
1532
|
|
|
488
|
-
|
|
489
|
-
- **Non** dimenticare `data-jp-field="image"` sul nodo corrispondente nel DOM, altrimenti il binding Inspector ↔ Stage non funziona per quel campo.
|
|
1533
|
+
If user says "make the font bigger":
|
|
490
1534
|
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
- **Studio** aggiorna il Working Draft; il sync con l'iframe e il "Bake" usano la stessa struttura. Quindi i dati che passi a JsonPagesEngine (siteConfig, menuConfig, pages) devono essere compatibili con ciò che l'editor modifica.
|
|
1535
|
+
```json
|
|
1536
|
+
{
|
|
1537
|
+
"editor.fontSize": 16
|
|
1538
|
+
}
|
|
1539
|
+
```
|
|
497
1540
|
|
|
498
|
-
|
|
1541
|
+
### Example: Enabling Format on Save
|
|
499
1542
|
|
|
500
|
-
|
|
1543
|
+
If user says "format my code when I save":
|
|
501
1544
|
|
|
502
|
-
|
|
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.76",
|
|
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..."
|