@supatent/skills 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -9
- package/bin/install.mjs +252 -52
- package/package.json +4 -3
- package/skills/{content-blog → supatent-content-blog}/SKILL.md +3 -3
- package/skills/supatent-content-blog/blog-sections.md +99 -0
- package/skills/{content-landing → supatent-content-landing}/SKILL.md +3 -3
- package/skills/supatent-content-landing/landing-sections.md +360 -0
- package/skills/{core → supatent-core}/SKILL.md +4 -4
- package/skills/supatent-references/schema-reference.md +289 -0
- package/skills/supatent-references/workflow-reference.md +345 -0
- package/skills-codex/supatent-content-blog/SKILL.md +298 -0
- package/skills-codex/supatent-content-landing/SKILL.md +384 -0
- package/skills-codex/supatent-core/SKILL.md +236 -0
- package/.claude-plugin/plugin.json +0 -5
- /package/{skills/content-blog → skills-codex/supatent-content-blog}/blog-sections.md +0 -0
- /package/{skills/content-landing → skills-codex/supatent-content-landing}/landing-sections.md +0 -0
- /package/{skills/references → skills-codex/supatent-references}/schema-reference.md +0 -0
- /package/{skills/references → skills-codex/supatent-references}/workflow-reference.md +0 -0
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
# Landing Page Section Catalog
|
|
2
|
+
|
|
3
|
+
Defines the schemas created by the landing page content skill. The SKILL.md references this file for schema generation. Each section is either a singleton (one content item) or a collection (multiple items).
|
|
4
|
+
|
|
5
|
+
## Category 1: Above the Fold
|
|
6
|
+
|
|
7
|
+
### landing-hero (Singleton)
|
|
8
|
+
|
|
9
|
+
Main hero section with headline, subheadline, and call-to-action.
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
{
|
|
13
|
+
"slug": "landing-hero",
|
|
14
|
+
"name": "Landing Hero",
|
|
15
|
+
"description": "Main hero section with headline, subheadline, and call-to-action",
|
|
16
|
+
"isSingleton": true,
|
|
17
|
+
"fields": [
|
|
18
|
+
{ "slug": "headline", "name": "Headline", "type": "text", "interface": "textInput", "order": 0 },
|
|
19
|
+
{ "slug": "subheadline", "name": "Subheadline", "type": "text", "interface": "textarea", "order": 1 },
|
|
20
|
+
{ "slug": "cta-text", "name": "CTA Text", "type": "text", "interface": "textInput", "order": 2 },
|
|
21
|
+
{ "slug": "cta-url", "name": "CTA URL", "type": "text", "interface": "textInput", "order": 3 },
|
|
22
|
+
{ "slug": "hero-image", "name": "Hero Image", "type": "image", "interface": "singleImage", "order": 4 }
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Image guidance: Hero image: 1920x1080px or 16:9 ratio. Required for visual impact.
|
|
28
|
+
|
|
29
|
+
### landing-announcement (Singleton)
|
|
30
|
+
|
|
31
|
+
Top banner bar for announcements or promotions.
|
|
32
|
+
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"slug": "landing-announcement",
|
|
36
|
+
"name": "Landing Announcement",
|
|
37
|
+
"description": "Top banner bar for announcements or promotions",
|
|
38
|
+
"isSingleton": true,
|
|
39
|
+
"fields": [
|
|
40
|
+
{ "slug": "text", "name": "Text", "type": "text", "interface": "textInput", "order": 0 },
|
|
41
|
+
{ "slug": "link-text", "name": "Link Text", "type": "text", "interface": "textInput", "order": 1 },
|
|
42
|
+
{ "slug": "link-url", "name": "Link URL", "type": "text", "interface": "textInput", "order": 2 }
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Image guidance: No images required.
|
|
48
|
+
|
|
49
|
+
## Category 2: Social Proof
|
|
50
|
+
|
|
51
|
+
### landing-logo (Collection)
|
|
52
|
+
|
|
53
|
+
Client or partner logos for trust building.
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"slug": "landing-logo",
|
|
58
|
+
"name": "Landing Logo",
|
|
59
|
+
"description": "Client or partner logos for trust building",
|
|
60
|
+
"isSingleton": false,
|
|
61
|
+
"fields": [
|
|
62
|
+
{ "slug": "name", "name": "Name", "type": "text", "interface": "textInput", "order": 0 },
|
|
63
|
+
{ "slug": "logo-image", "name": "Logo Image", "type": "image", "interface": "singleImage", "order": 1 }
|
|
64
|
+
]
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Default count: 5. Image guidance: Logo image: 200x80px or similar horizontal format. Required per logo.
|
|
69
|
+
|
|
70
|
+
### landing-testimonial (Collection)
|
|
71
|
+
|
|
72
|
+
Customer quotes and social proof.
|
|
73
|
+
|
|
74
|
+
```json
|
|
75
|
+
{
|
|
76
|
+
"slug": "landing-testimonial",
|
|
77
|
+
"name": "Landing Testimonial",
|
|
78
|
+
"description": "Customer quotes and social proof",
|
|
79
|
+
"isSingleton": false,
|
|
80
|
+
"fields": [
|
|
81
|
+
{ "slug": "quote", "name": "Quote", "type": "text", "interface": "textarea", "order": 0 },
|
|
82
|
+
{ "slug": "author-name", "name": "Author Name", "type": "text", "interface": "textInput", "order": 1 },
|
|
83
|
+
{ "slug": "author-title", "name": "Author Title", "type": "text", "interface": "textInput", "order": 2 },
|
|
84
|
+
{ "slug": "author-company", "name": "Author Company", "type": "text", "interface": "textInput", "order": 3 },
|
|
85
|
+
{ "slug": "author-image", "name": "Author Image", "type": "image", "interface": "singleImage", "order": 4 }
|
|
86
|
+
]
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Default count: 3. Image guidance: Author image: 100x100px square. Optional but recommended.
|
|
91
|
+
|
|
92
|
+
### landing-stat (Collection)
|
|
93
|
+
|
|
94
|
+
Key metrics and statistics.
|
|
95
|
+
|
|
96
|
+
```json
|
|
97
|
+
{
|
|
98
|
+
"slug": "landing-stat",
|
|
99
|
+
"name": "Landing Stat",
|
|
100
|
+
"description": "Key metrics and statistics",
|
|
101
|
+
"isSingleton": false,
|
|
102
|
+
"fields": [
|
|
103
|
+
{ "slug": "value", "name": "Value", "type": "text", "interface": "textInput", "order": 0 },
|
|
104
|
+
{ "slug": "label", "name": "Label", "type": "text", "interface": "textInput", "order": 1 },
|
|
105
|
+
{ "slug": "description", "name": "Description", "type": "text", "interface": "textInput", "order": 2 }
|
|
106
|
+
]
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Default count: 3. Image guidance: No images required.
|
|
111
|
+
|
|
112
|
+
## Category 3: Features and Info
|
|
113
|
+
|
|
114
|
+
### landing-feature (Collection)
|
|
115
|
+
|
|
116
|
+
Product features with title and description.
|
|
117
|
+
|
|
118
|
+
```json
|
|
119
|
+
{
|
|
120
|
+
"slug": "landing-feature",
|
|
121
|
+
"name": "Landing Feature",
|
|
122
|
+
"description": "Product features with title and description",
|
|
123
|
+
"isSingleton": false,
|
|
124
|
+
"fields": [
|
|
125
|
+
{ "slug": "title", "name": "Title", "type": "text", "interface": "textInput", "order": 0 },
|
|
126
|
+
{ "slug": "description", "name": "Description", "type": "text", "interface": "textarea", "order": 1 },
|
|
127
|
+
{ "slug": "icon-image", "name": "Icon Image", "type": "image", "interface": "singleImage", "order": 2 }
|
|
128
|
+
]
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Default count: 3. Image guidance: Icon image: 64x64px or SVG icon. Optional.
|
|
133
|
+
|
|
134
|
+
### landing-pricing-tier (Collection)
|
|
135
|
+
|
|
136
|
+
Pricing plans with features and CTA.
|
|
137
|
+
|
|
138
|
+
```json
|
|
139
|
+
{
|
|
140
|
+
"slug": "landing-pricing-tier",
|
|
141
|
+
"name": "Landing Pricing Tier",
|
|
142
|
+
"description": "Pricing plans with features and CTA",
|
|
143
|
+
"isSingleton": false,
|
|
144
|
+
"fields": [
|
|
145
|
+
{ "slug": "name", "name": "Name", "type": "text", "interface": "textInput", "order": 0 },
|
|
146
|
+
{ "slug": "price", "name": "Price", "type": "number", "interface": "numberInput", "order": 1 },
|
|
147
|
+
{ "slug": "price-period", "name": "Price Period", "type": "text", "interface": "textInput", "order": 2 },
|
|
148
|
+
{ "slug": "description", "name": "Description", "type": "text", "interface": "textarea", "order": 3 },
|
|
149
|
+
{ "slug": "features-list", "name": "Features List", "type": "markdown", "interface": "markdownEditor", "order": 4 },
|
|
150
|
+
{ "slug": "cta-text", "name": "CTA Text", "type": "text", "interface": "textInput", "order": 5 },
|
|
151
|
+
{ "slug": "cta-url", "name": "CTA URL", "type": "text", "interface": "textInput", "order": 6 },
|
|
152
|
+
{ "slug": "is-featured", "name": "Is Featured", "type": "text", "interface": "textInput", "order": 7 }
|
|
153
|
+
]
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Default count: 3. Notes: `features-list` uses markdown with bullet list format (one feature per bullet). `is-featured` uses "true" or "false" as string values (no boolean field type in Supatent). Image guidance: No images required.
|
|
158
|
+
|
|
159
|
+
### landing-team-member (Collection)
|
|
160
|
+
|
|
161
|
+
Team members with name, role, and bio.
|
|
162
|
+
|
|
163
|
+
```json
|
|
164
|
+
{
|
|
165
|
+
"slug": "landing-team-member",
|
|
166
|
+
"name": "Landing Team Member",
|
|
167
|
+
"description": "Team members with name, role, and bio",
|
|
168
|
+
"isSingleton": false,
|
|
169
|
+
"fields": [
|
|
170
|
+
{ "slug": "name", "name": "Name", "type": "text", "interface": "textInput", "order": 0 },
|
|
171
|
+
{ "slug": "role", "name": "Role", "type": "text", "interface": "textInput", "order": 1 },
|
|
172
|
+
{ "slug": "bio", "name": "Bio", "type": "markdown", "interface": "markdownEditor", "order": 2 },
|
|
173
|
+
{ "slug": "photo", "name": "Photo", "type": "image", "interface": "singleImage", "order": 3 }
|
|
174
|
+
]
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Default count: 3. Image guidance: Photo: 400x400px square. Required for team display.
|
|
179
|
+
|
|
180
|
+
### landing-faq-item (Collection)
|
|
181
|
+
|
|
182
|
+
Frequently asked questions and answers.
|
|
183
|
+
|
|
184
|
+
```json
|
|
185
|
+
{
|
|
186
|
+
"slug": "landing-faq-item",
|
|
187
|
+
"name": "Landing FAQ Item",
|
|
188
|
+
"description": "Frequently asked questions and answers",
|
|
189
|
+
"isSingleton": false,
|
|
190
|
+
"fields": [
|
|
191
|
+
{ "slug": "question", "name": "Question", "type": "text", "interface": "textInput", "order": 0 },
|
|
192
|
+
{ "slug": "answer", "name": "Answer", "type": "markdown", "interface": "markdownEditor", "order": 1 }
|
|
193
|
+
]
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Default count: 5. Image guidance: No images required. FAQ answers use markdown for rich formatting (links, lists, emphasis).
|
|
198
|
+
|
|
199
|
+
## Category 4: Conversion and Footer
|
|
200
|
+
|
|
201
|
+
### landing-cta (Singleton)
|
|
202
|
+
|
|
203
|
+
Primary call-to-action section.
|
|
204
|
+
|
|
205
|
+
```json
|
|
206
|
+
{
|
|
207
|
+
"slug": "landing-cta",
|
|
208
|
+
"name": "Landing CTA",
|
|
209
|
+
"description": "Primary call-to-action section",
|
|
210
|
+
"isSingleton": true,
|
|
211
|
+
"fields": [
|
|
212
|
+
{ "slug": "headline", "name": "Headline", "type": "text", "interface": "textInput", "order": 0 },
|
|
213
|
+
{ "slug": "description", "name": "Description", "type": "text", "interface": "textarea", "order": 1 },
|
|
214
|
+
{ "slug": "cta-text", "name": "CTA Text", "type": "text", "interface": "textInput", "order": 2 },
|
|
215
|
+
{ "slug": "cta-url", "name": "CTA URL", "type": "text", "interface": "textInput", "order": 3 },
|
|
216
|
+
{ "slug": "secondary-cta-text", "name": "Secondary CTA Text", "type": "text", "interface": "textInput", "order": 4 },
|
|
217
|
+
{ "slug": "secondary-cta-url", "name": "Secondary CTA URL", "type": "text", "interface": "textInput", "order": 5 }
|
|
218
|
+
]
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Image guidance: No images required.
|
|
223
|
+
|
|
224
|
+
### landing-footer (Singleton)
|
|
225
|
+
|
|
226
|
+
Page footer with company info.
|
|
227
|
+
|
|
228
|
+
```json
|
|
229
|
+
{
|
|
230
|
+
"slug": "landing-footer",
|
|
231
|
+
"name": "Landing Footer",
|
|
232
|
+
"description": "Page footer with company info",
|
|
233
|
+
"isSingleton": true,
|
|
234
|
+
"fields": [
|
|
235
|
+
{ "slug": "company-name", "name": "Company Name", "type": "text", "interface": "textInput", "order": 0 },
|
|
236
|
+
{ "slug": "tagline", "name": "Tagline", "type": "text", "interface": "textInput", "order": 1 },
|
|
237
|
+
{ "slug": "copyright-text", "name": "Copyright Text", "type": "text", "interface": "textInput", "order": 2 }
|
|
238
|
+
]
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
Image guidance: No images required.
|
|
243
|
+
|
|
244
|
+
### landing-metadata (Singleton)
|
|
245
|
+
|
|
246
|
+
Page metadata and structured data for SEO.
|
|
247
|
+
|
|
248
|
+
```json
|
|
249
|
+
{
|
|
250
|
+
"slug": "landing-metadata",
|
|
251
|
+
"name": "Landing Metadata",
|
|
252
|
+
"description": "Page metadata and structured data for SEO",
|
|
253
|
+
"isSingleton": true,
|
|
254
|
+
"fields": [
|
|
255
|
+
{ "slug": "page-title", "name": "Page Title", "type": "text", "interface": "textInput", "order": 0 },
|
|
256
|
+
{ "slug": "page-description", "name": "Page Description", "type": "text", "interface": "textarea", "order": 1 },
|
|
257
|
+
{ "slug": "json-ld", "name": "Organization Data", "type": "jsonLd", "interface": "jsonLdEditor", "order": 2 }
|
|
258
|
+
]
|
|
259
|
+
}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
Conditional JSON-LD fields added based on section selection:
|
|
263
|
+
- If FAQ section is selected, add: `{ "slug": "json-ld-faq", "name": "FAQ Data", "type": "jsonLd", "interface": "jsonLdEditor", "order": 3 }`
|
|
264
|
+
- If pricing section is selected (SaaS product), add: `{ "slug": "json-ld-product", "name": "Product Data", "type": "jsonLd", "interface": "jsonLdEditor", "order": 4 }`
|
|
265
|
+
|
|
266
|
+
Image guidance: No images required.
|
|
267
|
+
|
|
268
|
+
## JSON-LD Guidance
|
|
269
|
+
|
|
270
|
+
The landing-metadata singleton uses JSON-LD structured data fields. Each field stores a complete JSON-LD object.
|
|
271
|
+
|
|
272
|
+
### Organization (always present)
|
|
273
|
+
|
|
274
|
+
Used on every landing page. Stored in the `json-ld` field.
|
|
275
|
+
|
|
276
|
+
- Required: `@context`, `@type`
|
|
277
|
+
- Recommended: `name`, `url`, `description`
|
|
278
|
+
- Optional: `sameAs` (social links array)
|
|
279
|
+
- Do NOT include `logo` unless user provides an actual URL (asset slugs fail URI validation)
|
|
280
|
+
|
|
281
|
+
```json
|
|
282
|
+
{
|
|
283
|
+
"@context": "https://schema.org",
|
|
284
|
+
"@type": "Organization",
|
|
285
|
+
"name": "Company Name",
|
|
286
|
+
"url": "https://example.com",
|
|
287
|
+
"description": "Brief company description.",
|
|
288
|
+
"sameAs": [
|
|
289
|
+
"https://twitter.com/example",
|
|
290
|
+
"https://linkedin.com/company/example"
|
|
291
|
+
]
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### FAQPage (conditional)
|
|
296
|
+
|
|
297
|
+
Only when `landing-faq-item` section is selected. Stored in the `json-ld-faq` field. Generate FAQ entries from landing-faq-item content items.
|
|
298
|
+
|
|
299
|
+
- Required: `@context`, `@type`, `mainEntity` (array of Question objects, min 1)
|
|
300
|
+
- Each Question: `@type: "Question"`, `name`, `acceptedAnswer`
|
|
301
|
+
- Each Answer: `@type: "Answer"`, `text`
|
|
302
|
+
|
|
303
|
+
```json
|
|
304
|
+
{
|
|
305
|
+
"@context": "https://schema.org",
|
|
306
|
+
"@type": "FAQPage",
|
|
307
|
+
"mainEntity": [
|
|
308
|
+
{
|
|
309
|
+
"@type": "Question",
|
|
310
|
+
"name": "What is your product?",
|
|
311
|
+
"acceptedAnswer": {
|
|
312
|
+
"@type": "Answer",
|
|
313
|
+
"text": "Our product helps you do X."
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
]
|
|
317
|
+
}
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### SoftwareApplication (conditional)
|
|
321
|
+
|
|
322
|
+
Only when `landing-pricing-tier` section is selected for a SaaS product. Stored in the `json-ld-product` field. Do NOT use `Product` type -- it requires `image` which conflicts with the no-image decision. If the product is physical (not SaaS), skip the product JSON-LD entirely.
|
|
323
|
+
|
|
324
|
+
- Required: `@context`, `@type`, `name`
|
|
325
|
+
- Recommended: `applicationCategory`, `description`, `offers` (array of Offer objects)
|
|
326
|
+
- Each Offer: `@type: "Offer"`, `price`, `priceCurrency`
|
|
327
|
+
|
|
328
|
+
```json
|
|
329
|
+
{
|
|
330
|
+
"@context": "https://schema.org",
|
|
331
|
+
"@type": "SoftwareApplication",
|
|
332
|
+
"name": "Product Name",
|
|
333
|
+
"applicationCategory": "BusinessApplication",
|
|
334
|
+
"description": "Brief product description.",
|
|
335
|
+
"offers": [
|
|
336
|
+
{
|
|
337
|
+
"@type": "Offer",
|
|
338
|
+
"price": "29",
|
|
339
|
+
"priceCurrency": "USD"
|
|
340
|
+
}
|
|
341
|
+
]
|
|
342
|
+
}
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
## Section Selection Summary
|
|
346
|
+
|
|
347
|
+
| Section | Type | Default Count | Required Images |
|
|
348
|
+
|---------|------|---------------|-----------------|
|
|
349
|
+
| landing-hero | singleton | 1 | hero-image (1920x1080) |
|
|
350
|
+
| landing-announcement | singleton | 1 | none |
|
|
351
|
+
| landing-logo | collection | 5 | logo-image (200x80) |
|
|
352
|
+
| landing-testimonial | collection | 3 | author-image (100x100, optional) |
|
|
353
|
+
| landing-stat | collection | 3 | none |
|
|
354
|
+
| landing-feature | collection | 3 | icon-image (64x64, optional) |
|
|
355
|
+
| landing-pricing-tier | collection | 3 | none |
|
|
356
|
+
| landing-team-member | collection | 3 | photo (400x400) |
|
|
357
|
+
| landing-faq-item | collection | 5 | none |
|
|
358
|
+
| landing-cta | singleton | 1 | none |
|
|
359
|
+
| landing-footer | singleton | 1 | none |
|
|
360
|
+
| landing-metadata | singleton | 1 | none |
|
|
@@ -42,7 +42,7 @@ Dev mode provides automatic validation on file save and real-time sync with the
|
|
|
42
42
|
|
|
43
43
|
### 3. Check installed skill version
|
|
44
44
|
|
|
45
|
-
Read the version from `.claude/skills/supatent/.manifest.json` (the `version` field).
|
|
45
|
+
Read the version from `.claude/skills/supatent-core/.manifest.json` (the `version` field). If that file does not exist, check `.claude/skills/supatent/.manifest.json` (legacy path).
|
|
46
46
|
|
|
47
47
|
Then check the latest published version:
|
|
48
48
|
```bash
|
|
@@ -70,7 +70,7 @@ npm view @supatent/skills version 2>/dev/null
|
|
|
70
70
|
|
|
71
71
|
**Interface determines the UI editor**, not the storage format. For example, `text` with `textInput` gives a single-line input; `text` with `textarea` gives a multi-line editor.
|
|
72
72
|
|
|
73
|
-
For full details on field validation rules, constraints, and JSON-LD structured data types, read `../references/schema-reference.md`.
|
|
73
|
+
For full details on field validation rules, constraints, and JSON-LD structured data types, read `../supatent-references/schema-reference.md`.
|
|
74
74
|
|
|
75
75
|
## Quick Reference: File Locations
|
|
76
76
|
|
|
@@ -98,7 +98,7 @@ Load these files when you need detailed information beyond the quick references
|
|
|
98
98
|
|
|
99
99
|
### Schema details
|
|
100
100
|
|
|
101
|
-
**File:** `../references/schema-reference.md`
|
|
101
|
+
**File:** `../supatent-references/schema-reference.md`
|
|
102
102
|
|
|
103
103
|
**Read when:** Creating or modifying schemas, adding fields, choosing field types and interfaces, working with JSON-LD structured data, or checking naming conventions.
|
|
104
104
|
|
|
@@ -106,7 +106,7 @@ Load these files when you need detailed information beyond the quick references
|
|
|
106
106
|
|
|
107
107
|
### Workflow details
|
|
108
108
|
|
|
109
|
-
**File:** `../references/workflow-reference.md`
|
|
109
|
+
**File:** `../supatent-references/workflow-reference.md`
|
|
110
110
|
|
|
111
111
|
**Read when:** Running CLI commands (init, dev, pull, push, validate, status, merge), troubleshooting validation errors, resolving sync conflicts, or understanding the content authoring flow.
|
|
112
112
|
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
# Schema Reference
|
|
2
|
+
|
|
3
|
+
> **Source of truth:** `packages/cli/src/constants.ts` and `packages/cli/src/types.ts` define the canonical field types, interfaces, and validation rules. `packages/jsonld-schemas/src/registry.ts` defines supported JSON-LD types. Phase 45 CI drift check will verify this file stays in sync with those sources.
|
|
4
|
+
|
|
5
|
+
## Field Types and Interfaces
|
|
6
|
+
|
|
7
|
+
Every field in a schema has a `type` and an `interface`. The type determines the data format; the interface determines the editing UI.
|
|
8
|
+
|
|
9
|
+
| Type | Interface | Value Format | Notes |
|
|
10
|
+
|------|-----------|-------------|-------|
|
|
11
|
+
| `text` | `textInput` | `string` | Single-line text input |
|
|
12
|
+
| `text` | `textarea` | `string` | Multi-line text area |
|
|
13
|
+
| `number` | `numberInput` | `number` or `null` | Numeric input; `null` represents empty (distinct from `0`) |
|
|
14
|
+
| `image` | `singleImage` | `string` or `null` | Asset slug string (e.g., `"hero-image"`), or legacy object with `assetPath` |
|
|
15
|
+
| `image` | `multiImage` | `string[]` | Array of asset slug strings (e.g., `["hero", "banner"]`) |
|
|
16
|
+
| `markdown` | `markdownEditor` | `string` | Markdown-formatted text |
|
|
17
|
+
| `jsonLd` | `jsonLdEditor` | `object` | JSON-LD object with `@context` and `@type` |
|
|
18
|
+
|
|
19
|
+
**Important:** Each interface is valid only for its corresponding type. Using `textarea` with a `number` type (or any other mismatch) will fail validation.
|
|
20
|
+
|
|
21
|
+
### Interface-Type Compatibility Map
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
text -> textInput, textarea
|
|
25
|
+
number -> numberInput
|
|
26
|
+
image -> singleImage, multiImage
|
|
27
|
+
markdown -> markdownEditor
|
|
28
|
+
jsonLd -> jsonLdEditor
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Schema File Structure
|
|
32
|
+
|
|
33
|
+
Schema files live at `.supatent/schema/{slug}.json`. The complete structure:
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"slug": "blog-post",
|
|
38
|
+
"name": "Blog Post",
|
|
39
|
+
"description": "Articles for the company blog",
|
|
40
|
+
"isSingleton": false,
|
|
41
|
+
"fields": [
|
|
42
|
+
{
|
|
43
|
+
"slug": "title",
|
|
44
|
+
"name": "Title",
|
|
45
|
+
"description": "The post headline",
|
|
46
|
+
"type": "text",
|
|
47
|
+
"interface": "textInput",
|
|
48
|
+
"order": 0
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"slug": "body",
|
|
52
|
+
"name": "Body",
|
|
53
|
+
"type": "markdown",
|
|
54
|
+
"interface": "markdownEditor",
|
|
55
|
+
"order": 1
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Property Reference
|
|
62
|
+
|
|
63
|
+
| Property | Required | Type | Description |
|
|
64
|
+
|----------|----------|------|-------------|
|
|
65
|
+
| `slug` | Yes | `string` | Must match filename (without `.json`). Lowercase alphanumeric with hyphens. |
|
|
66
|
+
| `name` | Yes | `string` | Display name. Minimum 1 character. |
|
|
67
|
+
| `description` | No | `string` | Optional description of the schema's purpose. |
|
|
68
|
+
| `isSingleton` | Yes | `boolean` | Whether this schema has exactly one content item per locale. |
|
|
69
|
+
| `fields` | Yes | `array` | Array of field definitions. |
|
|
70
|
+
|
|
71
|
+
### Field Property Reference
|
|
72
|
+
|
|
73
|
+
| Property | Required | Type | Description |
|
|
74
|
+
|----------|----------|------|-------------|
|
|
75
|
+
| `slug` | Yes | `string` | Unique within the schema. Lowercase alphanumeric with hyphens. |
|
|
76
|
+
| `name` | Yes | `string` | Display name. Minimum 1 character. |
|
|
77
|
+
| `description` | No | `string` | Optional description of the field's purpose. |
|
|
78
|
+
| `type` | Yes | `string` | One of: `text`, `number`, `image`, `markdown`, `jsonLd` |
|
|
79
|
+
| `interface` | Yes | `string` | Must be valid for the field's type (see compatibility map above). |
|
|
80
|
+
| `order` | Yes | `number` | Integer >= 0. Controls display order in the editor. |
|
|
81
|
+
|
|
82
|
+
## Validation Rules
|
|
83
|
+
|
|
84
|
+
These rules are enforced by `packages/cli/src/lib/validation.ts` using AJV (JSON Schema draft-07).
|
|
85
|
+
|
|
86
|
+
### Slug Pattern
|
|
87
|
+
|
|
88
|
+
All slugs (schema slugs, field slugs, content item slugs) must match:
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
^[a-z0-9]+(?:-[a-z0-9]+)*$
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Valid: `blog-post`, `title`, `cover-image`, `my-post-1`
|
|
95
|
+
Invalid: `Blog_Post`, `my post`, `_title`, `post--double`, `-leading`
|
|
96
|
+
|
|
97
|
+
### Required Schema Properties
|
|
98
|
+
|
|
99
|
+
The top-level object requires: `slug`, `name`, `isSingleton`, `fields`.
|
|
100
|
+
|
|
101
|
+
### Required Field Properties
|
|
102
|
+
|
|
103
|
+
Each field object requires: `slug`, `name`, `type`, `interface`, `order`.
|
|
104
|
+
|
|
105
|
+
### Additional Rules
|
|
106
|
+
|
|
107
|
+
- **Slug-filename match:** The `slug` value must match the filename (e.g., `blog-post.json` must have `"slug": "blog-post"`).
|
|
108
|
+
- **Unique field slugs:** No two fields within the same schema can share a slug.
|
|
109
|
+
- **Interface-type compatibility:** The `interface` must be valid for the given `type` (see compatibility map).
|
|
110
|
+
- **Order minimum:** The `order` field must be a number >= 0.
|
|
111
|
+
- **Name minimum length:** Both schema `name` and field `name` must have at least 1 character.
|
|
112
|
+
|
|
113
|
+
## Singleton vs Collection
|
|
114
|
+
|
|
115
|
+
### Singleton (`isSingleton: true`)
|
|
116
|
+
|
|
117
|
+
One content item per locale. The content file **must** use slug `"default"`.
|
|
118
|
+
|
|
119
|
+
File path: `.supatent/content/{schemaSlug}/default.{locale}.json`
|
|
120
|
+
|
|
121
|
+
Use for: site settings, homepage hero, footer, navigation, about page, any content that exists as a single instance.
|
|
122
|
+
|
|
123
|
+
Example schemas: `site-settings`, `homepage-hero`, `footer`, `about-page`
|
|
124
|
+
|
|
125
|
+
### Collection (`isSingleton: false`)
|
|
126
|
+
|
|
127
|
+
Multiple content items, each with its own slug.
|
|
128
|
+
|
|
129
|
+
File path: `.supatent/content/{schemaSlug}/{itemSlug}.{locale}.json`
|
|
130
|
+
|
|
131
|
+
Use for: blog posts, team members, FAQ items, product listings, testimonials, any content with multiple entries.
|
|
132
|
+
|
|
133
|
+
Example schemas: `blog-post`, `team-member`, `faq-item`, `product`
|
|
134
|
+
|
|
135
|
+
### Decision Guide
|
|
136
|
+
|
|
137
|
+
| Question | Yes -> Singleton | No -> Collection |
|
|
138
|
+
|----------|-----------------|-----------------|
|
|
139
|
+
| Is there only ever one of this? | Singleton | Collection |
|
|
140
|
+
| Would "list all X" make sense? | Collection | Singleton |
|
|
141
|
+
| Does it have its own slug/URL? | Collection | Singleton |
|
|
142
|
+
|
|
143
|
+
## Content File Structure
|
|
144
|
+
|
|
145
|
+
Content files live at `.supatent/content/{schemaSlug}/{itemSlug}.{locale}.json`.
|
|
146
|
+
|
|
147
|
+
The file is a flat JSON object where keys are field slugs from the schema:
|
|
148
|
+
|
|
149
|
+
```json
|
|
150
|
+
{
|
|
151
|
+
"title": "My First Blog Post",
|
|
152
|
+
"body": "# Welcome\n\nThis is the post content in **markdown**.",
|
|
153
|
+
"cover-image": "blog-hero",
|
|
154
|
+
"read-time": 5
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Value Types by Field Type
|
|
159
|
+
|
|
160
|
+
| Field Type | Expected Value | Example |
|
|
161
|
+
|------------|---------------|---------|
|
|
162
|
+
| `text` | `string` | `"Hello world"` |
|
|
163
|
+
| `number` | `number` or `null` | `42` or `null` |
|
|
164
|
+
| `image` (singleImage) | `string` (asset slug) or `null` | `"hero-image"` |
|
|
165
|
+
| `image` (multiImage) | `string[]` (asset slugs) | `["photo-1", "photo-2"]` |
|
|
166
|
+
| `markdown` | `string` | `"# Heading\n\nParagraph"` |
|
|
167
|
+
| `jsonLd` | `object` | `{ "@context": "https://schema.org", "@type": "Article" }` |
|
|
168
|
+
|
|
169
|
+
### File Naming
|
|
170
|
+
|
|
171
|
+
- Collection: `{itemSlug}.{locale}.json` (e.g., `my-post.en.json`, `my-post.fr.json`)
|
|
172
|
+
- Singleton: `default.{locale}.json` (e.g., `default.en.json`)
|
|
173
|
+
- Locale format: `xx` or `xx-XX` (e.g., `en`, `en-US`, `fr`, `fr-CA`)
|
|
174
|
+
|
|
175
|
+
### Content Validation Behavior
|
|
176
|
+
|
|
177
|
+
- **Unknown fields** (not in schema) produce errors with "did you mean?" suggestions using Levenshtein distance.
|
|
178
|
+
- **Missing fields** produce errors (required), except `jsonLd` fields which produce warnings.
|
|
179
|
+
- **Wrong value types** produce errors with examples of correct format.
|
|
180
|
+
|
|
181
|
+
## JSON-LD Types
|
|
182
|
+
|
|
183
|
+
Supatent supports 23 JSON-LD types for structured data, validated by the `@supatent/jsonld-schemas` package. Types are organized by category.
|
|
184
|
+
|
|
185
|
+
To use JSON-LD: add a field with `type: "jsonLd"` and `interface: "jsonLdEditor"`. The content value must include `@context` and `@type`:
|
|
186
|
+
|
|
187
|
+
```json
|
|
188
|
+
{
|
|
189
|
+
"@context": "https://schema.org",
|
|
190
|
+
"@type": "Article",
|
|
191
|
+
"headline": "My Article Title",
|
|
192
|
+
"author": { "@type": "Person", "name": "Jane Doe" }
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Commerce
|
|
197
|
+
|
|
198
|
+
| @type | Label | Description |
|
|
199
|
+
|-------|-------|-------------|
|
|
200
|
+
| `Product` | Product | Physical or digital products for sale |
|
|
201
|
+
| `SoftwareApplication` | Software App | Software applications and tools |
|
|
202
|
+
| `VacationRental` | Vacation Rental | Short-term rental properties |
|
|
203
|
+
|
|
204
|
+
### Content
|
|
205
|
+
|
|
206
|
+
| @type | Label | Description |
|
|
207
|
+
|-------|-------|-------------|
|
|
208
|
+
| `Article` | Article | News articles, blog posts, editorial content |
|
|
209
|
+
| `Recipe` | Recipe | Cooking and food preparation instructions |
|
|
210
|
+
| `FAQPage` | FAQ Page | Frequently asked questions pages |
|
|
211
|
+
| `Review` | Review | Product or service reviews |
|
|
212
|
+
| `DiscussionForumPosting` | Discussion Forum Posting | Forum threads and community posts |
|
|
213
|
+
| `QAPage` | Q&A Page | Question and answer pages |
|
|
214
|
+
|
|
215
|
+
### Local
|
|
216
|
+
|
|
217
|
+
| @type | Label | Description |
|
|
218
|
+
|-------|-------|-------------|
|
|
219
|
+
| `LocalBusiness` | Local Business | Physical business locations |
|
|
220
|
+
| `Event` | Event | Events, conferences, meetups |
|
|
221
|
+
|
|
222
|
+
### Education
|
|
223
|
+
|
|
224
|
+
| @type | Label | Description |
|
|
225
|
+
|-------|-------|-------------|
|
|
226
|
+
| `Course` | Course | Educational courses and programs |
|
|
227
|
+
| `Quiz` | Education Q&A | Educational quizzes and assessments |
|
|
228
|
+
| `MathSolver` | Math Solver | Mathematical problem solvers |
|
|
229
|
+
|
|
230
|
+
### Media
|
|
231
|
+
|
|
232
|
+
| @type | Label | Description |
|
|
233
|
+
|-------|-------|-------------|
|
|
234
|
+
| `VideoObject` | Video | Video content and clips |
|
|
235
|
+
| `Movie` | Movie | Feature films and movies |
|
|
236
|
+
| `ImageMetadata` | Image Metadata | Image licensing and attribution |
|
|
237
|
+
|
|
238
|
+
### People and Organizations
|
|
239
|
+
|
|
240
|
+
| @type | Label | Description |
|
|
241
|
+
|-------|-------|-------------|
|
|
242
|
+
| `Organization` | Organization | Companies, nonprofits, institutions |
|
|
243
|
+
| `ProfilePage` | Profile Page | Personal or professional profile pages |
|
|
244
|
+
| `EmployerAggregateRating` | Employer Rating | Aggregated employer ratings and reviews |
|
|
245
|
+
| `JobPosting` | Job Posting | Job listings and opportunities |
|
|
246
|
+
|
|
247
|
+
### Navigation
|
|
248
|
+
|
|
249
|
+
| @type | Label | Description |
|
|
250
|
+
|-------|-------|-------------|
|
|
251
|
+
| `BreadcrumbList` | Breadcrumb List | Site navigation breadcrumbs |
|
|
252
|
+
|
|
253
|
+
### Data
|
|
254
|
+
|
|
255
|
+
| @type | Label | Description |
|
|
256
|
+
|-------|-------|-------------|
|
|
257
|
+
| `Dataset` | Dataset | Structured data collections |
|
|
258
|
+
|
|
259
|
+
### JSON-LD Validation
|
|
260
|
+
|
|
261
|
+
- The `@context` field must be `"https://schema.org"`.
|
|
262
|
+
- The `@type` must be one of the 23 supported types listed above.
|
|
263
|
+
- Additional properties are validated against schema.org specifications by the `@supatent/jsonld-schemas` package (deep property checking).
|
|
264
|
+
- Deprecated types generate warnings, not errors.
|
|
265
|
+
- Empty `jsonLd` fields (missing from content) produce warnings rather than errors.
|
|
266
|
+
|
|
267
|
+
## Naming Conventions
|
|
268
|
+
|
|
269
|
+
### Schema Slugs
|
|
270
|
+
|
|
271
|
+
Use lowercase-hyphenated: `blog-post`, `site-settings`, `team-member`
|
|
272
|
+
|
|
273
|
+
Do not use: `blogPost`, `Blog_Post`, `BLOG-POST`
|
|
274
|
+
|
|
275
|
+
### Field Slugs
|
|
276
|
+
|
|
277
|
+
Use lowercase-hyphenated: `cover-image`, `read-time`, `full-name`
|
|
278
|
+
|
|
279
|
+
Do not use: `coverImage`, `cover_image`, `CoverImage`
|
|
280
|
+
|
|
281
|
+
### Display Names
|
|
282
|
+
|
|
283
|
+
Use Title Case: `"Blog Post"`, `"Cover Image"`, `"Read Time"`
|
|
284
|
+
|
|
285
|
+
### Content Item Slugs
|
|
286
|
+
|
|
287
|
+
Use lowercase-hyphenated: `my-first-post`, `about-us`, `john-doe`
|
|
288
|
+
|
|
289
|
+
Singleton items always use: `default`
|