@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.
@@ -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`