@supatent/skills 0.4.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,308 @@
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
+ | `video` | `singleVideo` | `string` or `null` | Asset slug string (e.g., `"promo-video"`), or legacy object with `assetPath` |
17
+ | `video` | `multiVideo` | `string[]` | Array of asset slug strings (e.g., `["intro-video", "demo-video"]`) |
18
+ | `markdown` | `markdownEditor` | `string` | Markdown-formatted text |
19
+ | `jsonLd` | `jsonLdEditor` | `object` | JSON-LD object with `@context` and `@type` |
20
+
21
+ **Important:** Each interface is valid only for its corresponding type. Using `textarea` with a `number` type (or any other mismatch) will fail validation.
22
+
23
+ ### Interface-Type Compatibility Map
24
+
25
+ ```
26
+ text -> textInput, textarea
27
+ number -> numberInput
28
+ image -> singleImage, multiImage
29
+ video -> singleVideo, multiVideo
30
+ markdown -> markdownEditor
31
+ jsonLd -> jsonLdEditor
32
+ ```
33
+
34
+ ## Schema File Structure
35
+
36
+ Schema files live at `.supatent/schema/{slug}.json`. The complete structure:
37
+
38
+ ```json
39
+ {
40
+ "slug": "blog-post",
41
+ "name": "Blog Post",
42
+ "description": "Articles for the company blog",
43
+ "isSingleton": false,
44
+ "fields": [
45
+ {
46
+ "slug": "title",
47
+ "name": "Title",
48
+ "description": "The post headline",
49
+ "type": "text",
50
+ "interface": "textInput",
51
+ "order": 0
52
+ },
53
+ {
54
+ "slug": "body",
55
+ "name": "Body",
56
+ "type": "markdown",
57
+ "interface": "markdownEditor",
58
+ "order": 1
59
+ }
60
+ ]
61
+ }
62
+ ```
63
+
64
+ ### Property Reference
65
+
66
+ | Property | Required | Type | Description |
67
+ |----------|----------|------|-------------|
68
+ | `slug` | Yes | `string` | Must match filename (without `.json`). Lowercase alphanumeric with hyphens. |
69
+ | `name` | Yes | `string` | Display name. Minimum 1 character. |
70
+ | `description` | No | `string` | Optional description of the schema's purpose. |
71
+ | `isSingleton` | Yes | `boolean` | Whether this schema has exactly one content item per locale. |
72
+ | `fields` | Yes | `array` | Array of field definitions. |
73
+
74
+ ### Field Property Reference
75
+
76
+ | Property | Required | Type | Description |
77
+ |----------|----------|------|-------------|
78
+ | `slug` | Yes | `string` | Unique within the schema. Lowercase alphanumeric with hyphens. |
79
+ | `name` | Yes | `string` | Display name. Minimum 1 character. |
80
+ | `description` | No | `string` | Optional description of the field's purpose. |
81
+ | `type` | Yes | `string` | One of: `text`, `number`, `image`, `video`, `markdown`, `jsonLd` |
82
+ | `interface` | Yes | `string` | Must be valid for the field's type (see compatibility map above). |
83
+ | `order` | Yes | `number` | Integer >= 0. Controls display order in the editor. |
84
+
85
+ ## Validation Rules
86
+
87
+ These rules are enforced by `packages/cli/src/lib/validation.ts` using AJV (JSON Schema draft-07).
88
+
89
+ ### Slug Pattern
90
+
91
+ All slugs (schema slugs, field slugs, content item slugs) must match:
92
+
93
+ ```
94
+ ^[a-z0-9]+(?:-[a-z0-9]+)*$
95
+ ```
96
+
97
+ Valid: `blog-post`, `title`, `cover-image`, `my-post-1`
98
+ Invalid: `Blog_Post`, `my post`, `_title`, `post--double`, `-leading`
99
+
100
+ ### Required Schema Properties
101
+
102
+ The top-level object requires: `slug`, `name`, `isSingleton`, `fields`.
103
+
104
+ ### Required Field Properties
105
+
106
+ Each field object requires: `slug`, `name`, `type`, `interface`, `order`.
107
+
108
+ ### Additional Rules
109
+
110
+ - **Slug-filename match:** The `slug` value must match the filename (e.g., `blog-post.json` must have `"slug": "blog-post"`).
111
+ - **Unique field slugs:** No two fields within the same schema can share a slug.
112
+ - **Interface-type compatibility:** The `interface` must be valid for the given `type` (see compatibility map).
113
+ - **Order minimum:** The `order` field must be a number >= 0.
114
+ - **Name minimum length:** Both schema `name` and field `name` must have at least 1 character.
115
+
116
+ ## Singleton vs Collection
117
+
118
+ ### Singleton (`isSingleton: true`)
119
+
120
+ One content item per locale. The content file **must** use slug `"default"`.
121
+
122
+ File path: `.supatent/content/{schemaSlug}/default.{locale}.json`
123
+
124
+ Use for: site settings, homepage hero, footer, navigation, about page, any content that exists as a single instance.
125
+
126
+ Example schemas: `site-settings`, `homepage-hero`, `footer`, `about-page`
127
+
128
+ ### Collection (`isSingleton: false`)
129
+
130
+ Multiple content items, each with its own slug.
131
+
132
+ File path: `.supatent/content/{schemaSlug}/{itemSlug}.{locale}.json`
133
+
134
+ Use for: blog posts, team members, FAQ items, product listings, testimonials, any content with multiple entries.
135
+
136
+ Example schemas: `blog-post`, `team-member`, `faq-item`, `product`
137
+
138
+ ### Decision Guide
139
+
140
+ | Question | Yes -> Singleton | No -> Collection |
141
+ |----------|-----------------|-----------------|
142
+ | Is there only ever one of this? | Singleton | Collection |
143
+ | Would "list all X" make sense? | Collection | Singleton |
144
+ | Does it have its own slug/URL? | Collection | Singleton |
145
+
146
+ ## Content File Structure
147
+
148
+ Content files live at `.supatent/content/{schemaSlug}/{itemSlug}.{locale}.json`.
149
+
150
+ The file is a flat JSON object where keys are field slugs from the schema:
151
+
152
+ ```json
153
+ {
154
+ "title": "My First Blog Post",
155
+ "body": "# Welcome\n\nThis is the post content in **markdown**.",
156
+ "cover-image": "blog-hero",
157
+ "read-time": 5
158
+ }
159
+ ```
160
+
161
+ ### Value Types by Field Type
162
+
163
+ | Field Type | Expected Value | Example |
164
+ |------------|---------------|---------|
165
+ | `text` | `string` | `"Hello world"` |
166
+ | `number` | `number` or `null` | `42` or `null` |
167
+ | `image` (singleImage) | `string` (asset slug) or `null` | `"hero-image"` |
168
+ | `image` (multiImage) | `string[]` (asset slugs) | `["photo-1", "photo-2"]` |
169
+ | `video` (singleVideo) | `string` (asset slug) or `null` | `"promo-video"` |
170
+ | `video` (multiVideo) | `string[]` (asset slugs) | `["intro-video", "demo-video"]` |
171
+ | `markdown` | `string` | `"# Heading\n\nParagraph"` |
172
+ | `jsonLd` | `object` | `{ "@context": "https://schema.org", "@type": "Article" }` |
173
+
174
+ ### Markdown Asset Slug Syntax
175
+
176
+ Markdown fields support direct asset slug references. Use these forms inside markdown content:
177
+
178
+ - Image embed (resolved to optimized image URL): `![Alt text](asset-slug)`
179
+ - Asset link (resolved to asset URL): `[Download file](asset-slug)`
180
+ - HTML image tag (resolved to optimized image URL): `<img src="asset-slug" width="1200" height="630" alt="Hero">`
181
+
182
+ Rules:
183
+
184
+ - Use raw slugs only (example: `hero-image`), not full URLs and not file extensions.
185
+ - Slugs must match `^[a-z0-9]+(?:-[a-z0-9]+)*$`.
186
+ - Missing slugs produce `markdown-asset` warnings (non-blocking).
187
+
188
+ ### File Naming
189
+
190
+ - Collection: `{itemSlug}.{locale}.json` (e.g., `my-post.en.json`, `my-post.fr.json`)
191
+ - Singleton: `default.{locale}.json` (e.g., `default.en.json`)
192
+ - Locale format: `xx` or `xx-XX` (e.g., `en`, `en-US`, `fr`, `fr-CA`)
193
+
194
+ ### Content Validation Behavior
195
+
196
+ - **Unknown fields** (not in schema) produce errors with "did you mean?" suggestions using Levenshtein distance.
197
+ - **Missing fields** produce errors (required), except `jsonLd` fields which produce warnings.
198
+ - **Wrong value types** produce errors with examples of correct format.
199
+
200
+ ## JSON-LD Types
201
+
202
+ Supatent supports 23 JSON-LD types for structured data, validated by the `@supatent/jsonld-schemas` package. Types are organized by category.
203
+
204
+ To use JSON-LD: add a field with `type: "jsonLd"` and `interface: "jsonLdEditor"`. The content value must include `@context` and `@type`:
205
+
206
+ ```json
207
+ {
208
+ "@context": "https://schema.org",
209
+ "@type": "Article",
210
+ "headline": "My Article Title",
211
+ "author": { "@type": "Person", "name": "Jane Doe" }
212
+ }
213
+ ```
214
+
215
+ ### Commerce
216
+
217
+ | @type | Label | Description |
218
+ |-------|-------|-------------|
219
+ | `Product` | Product | Physical or digital products for sale |
220
+ | `SoftwareApplication` | Software App | Software applications and tools |
221
+ | `VacationRental` | Vacation Rental | Short-term rental properties |
222
+
223
+ ### Content
224
+
225
+ | @type | Label | Description |
226
+ |-------|-------|-------------|
227
+ | `Article` | Article | News articles, blog posts, editorial content |
228
+ | `Recipe` | Recipe | Cooking and food preparation instructions |
229
+ | `FAQPage` | FAQ Page | Frequently asked questions pages |
230
+ | `Review` | Review | Product or service reviews |
231
+ | `DiscussionForumPosting` | Discussion Forum Posting | Forum threads and community posts |
232
+ | `QAPage` | Q&A Page | Question and answer pages |
233
+
234
+ ### Local
235
+
236
+ | @type | Label | Description |
237
+ |-------|-------|-------------|
238
+ | `LocalBusiness` | Local Business | Physical business locations |
239
+ | `Event` | Event | Events, conferences, meetups |
240
+
241
+ ### Education
242
+
243
+ | @type | Label | Description |
244
+ |-------|-------|-------------|
245
+ | `Course` | Course | Educational courses and programs |
246
+ | `Quiz` | Education Q&A | Educational quizzes and assessments |
247
+ | `MathSolver` | Math Solver | Mathematical problem solvers |
248
+
249
+ ### Media
250
+
251
+ | @type | Label | Description |
252
+ |-------|-------|-------------|
253
+ | `VideoObject` | Video | Video content and clips |
254
+ | `Movie` | Movie | Feature films and movies |
255
+ | `ImageMetadata` | Image Metadata | Image licensing and attribution |
256
+
257
+ ### People and Organizations
258
+
259
+ | @type | Label | Description |
260
+ |-------|-------|-------------|
261
+ | `Organization` | Organization | Companies, nonprofits, institutions |
262
+ | `ProfilePage` | Profile Page | Personal or professional profile pages |
263
+ | `EmployerAggregateRating` | Employer Rating | Aggregated employer ratings and reviews |
264
+ | `JobPosting` | Job Posting | Job listings and opportunities |
265
+
266
+ ### Navigation
267
+
268
+ | @type | Label | Description |
269
+ |-------|-------|-------------|
270
+ | `BreadcrumbList` | Breadcrumb List | Site navigation breadcrumbs |
271
+
272
+ ### Data
273
+
274
+ | @type | Label | Description |
275
+ |-------|-------|-------------|
276
+ | `Dataset` | Dataset | Structured data collections |
277
+
278
+ ### JSON-LD Validation
279
+
280
+ - The `@context` field must be `"https://schema.org"`.
281
+ - The `@type` must be one of the 23 supported types listed above.
282
+ - Additional properties are validated against schema.org specifications by the `@supatent/jsonld-schemas` package (deep property checking).
283
+ - Deprecated types generate warnings, not errors.
284
+ - Empty `jsonLd` fields (missing from content) produce warnings rather than errors.
285
+
286
+ ## Naming Conventions
287
+
288
+ ### Schema Slugs
289
+
290
+ Use lowercase-hyphenated: `blog-post`, `site-settings`, `team-member`
291
+
292
+ Do not use: `blogPost`, `Blog_Post`, `BLOG-POST`
293
+
294
+ ### Field Slugs
295
+
296
+ Use lowercase-hyphenated: `cover-image`, `read-time`, `full-name`
297
+
298
+ Do not use: `coverImage`, `cover_image`, `CoverImage`
299
+
300
+ ### Display Names
301
+
302
+ Use Title Case: `"Blog Post"`, `"Cover Image"`, `"Read Time"`
303
+
304
+ ### Content Item Slugs
305
+
306
+ Use lowercase-hyphenated: `my-first-post`, `about-us`, `john-doe`
307
+
308
+ Singleton items always use: `default`
@@ -0,0 +1,359 @@
1
+ # Workflow Reference
2
+
3
+ > **Source of truth:** `packages/cli/src/commands/*.ts` define CLI command behavior and flags. `packages/cli/src/lib/validation.ts` defines error messages. This file documents the content authoring workflow for AI agents operating through the Supatent CLI.
4
+
5
+ ## Content Authoring Flow
6
+
7
+ The standard workflow for creating and managing content:
8
+
9
+ 1. **Initialize** (first time only):
10
+ ```bash
11
+ supatent init
12
+ ```
13
+ Sets up `.supatent/` directory with `config.json` and `credentials.json`.
14
+
15
+ 2. **Pull existing content:**
16
+ ```bash
17
+ supatent pull
18
+ ```
19
+ Downloads schemas, content, and assets from the remote CMS.
20
+
21
+ 3. **Start dev mode** (recommended for continuous work):
22
+ ```bash
23
+ supatent dev
24
+ ```
25
+ Enables bidirectional real-time sync via Convex WebSocket. File changes are automatically validated and pushed.
26
+
27
+ 4. **Create or edit schemas** in `.supatent/schema/` -- see schema-reference.md for field types and validation rules.
28
+
29
+ 5. **Create or edit content** in `.supatent/content/{schemaSlug}/` -- content files are flat JSON objects with field slugs as keys.
30
+
31
+ 6. **Validate** (automatic in dev mode, or manual):
32
+ ```bash
33
+ supatent validate
34
+ ```
35
+
36
+ 7. **Push** (automatic in dev mode, or manual):
37
+ ```bash
38
+ supatent push
39
+ ```
40
+
41
+ 8. **Check status** at any time:
42
+ ```bash
43
+ supatent status
44
+ ```
45
+
46
+ ## CLI Command Reference
47
+
48
+ ### `supatent init`
49
+
50
+ Initialize Supatent in the current directory. Creates `.supatent/` with configuration files.
51
+
52
+ | Flag | Description |
53
+ |------|-------------|
54
+ | `--base-url <url>` | Supatent app URL (default: `https://app.supatent.ai`) |
55
+ | `--api-key <key>` | API key for authentication |
56
+ | `--project <slug>` | Project slug to connect to |
57
+ | `-y, --yes` | Skip confirmation prompts (non-interactive mode) |
58
+
59
+ The init process auto-discovers the Convex HTTP URL via the Next.js discovery endpoint (`GET {baseUrl}/api/v1/discover`).
60
+
61
+ ### `supatent pull`
62
+
63
+ Download schemas, content, and assets from the remote CMS. Uses delta pulling -- only downloads items that have changed since last sync.
64
+
65
+ | Flag | Description |
66
+ |------|-------------|
67
+ | `--schema` | Pull schemas only |
68
+ | `--content` | Pull content only |
69
+ | `--no-assets` | Skip downloading asset binary files |
70
+ | `-f, --force` | Overwrite local changes without confirmation |
71
+ | `-v, --verbose` | Show detailed output |
72
+
73
+ ### `supatent push`
74
+
75
+ Upload local changes to the remote CMS. Validates content before pushing. Uses batch atomic push.
76
+
77
+ | Flag | Description |
78
+ |------|-------------|
79
+ | `--dry-run` | Show what would change without applying |
80
+ | `--schema` | Push schemas only |
81
+ | `--content` | Push content only |
82
+ | `-f, --force` | Overwrite remote conflicts |
83
+ | `-v, --verbose` | Show detailed output |
84
+
85
+ ### `supatent status`
86
+
87
+ Show changes between local files and the remote CMS. Compares checksums to detect additions, modifications, and deletions in both directions.
88
+
89
+ | Flag | Description |
90
+ |------|-------------|
91
+ | `--json` | Output as JSON (machine-readable) |
92
+ | `-v, --verbose` | Show unchanged files too |
93
+
94
+ ### `supatent validate`
95
+
96
+ Validate local schema, content, and asset files against the defined rules. Writes results to `.validation-status.json`.
97
+
98
+ | Flag | Description |
99
+ |------|-------------|
100
+ | `[path]` | Optional path to validate (e.g., `schema/`, `content/`, or a specific file) |
101
+ | `--json` | Output validation results as JSON |
102
+
103
+ ### `supatent dev`
104
+
105
+ Start continuous bidirectional sync with the CMS. Watches for local file changes and subscribes to remote changes via Convex WebSocket.
106
+
107
+ | Flag | Description |
108
+ |------|-------------|
109
+ | `-v, --verbose` | Show detailed output (watcher events, sync operations) |
110
+ | `--no-watch` | Disable local file watching (pull-only mode) |
111
+ | `--no-pull` | Disable remote change pulling (push-only mode) |
112
+
113
+ ### `supatent merge`
114
+
115
+ Resolve conflicts between local and remote versions. Shows diffs and prompts for resolution strategy.
116
+
117
+ | Flag | Description |
118
+ |------|-------------|
119
+ | `--schema <slug>` | Filter conflicts by schema slug |
120
+ | `--content-slug <slug>` | Target specific content item (requires `--schema`) |
121
+ | `--theirs` | Accept all remote changes (non-interactive) |
122
+ | `--mine` | Keep all local changes (non-interactive) |
123
+ | `-v, --verbose` | Show detailed output |
124
+
125
+ ## File Locations
126
+
127
+ All Supatent files live under the `.supatent/` directory in the project root:
128
+
129
+ | Path | Purpose | Git |
130
+ |------|---------|-----|
131
+ | `.supatent/config.json` | Project configuration (base URL, Convex URL, project slug) | Tracked |
132
+ | `.supatent/credentials.json` | API key storage | Gitignored |
133
+ | `.supatent/schema/{slug}.json` | Schema definitions | Tracked |
134
+ | `.supatent/content/{schemaSlug}/{itemSlug}.{locale}.json` | Content items | Tracked |
135
+ | `.supatent/assets/{slug}.{ext}` | Asset binary files | Tracked |
136
+ | `.supatent/assets/{slug}.{locale}.json` | Asset metadata sidecars (alt, title, description) | Tracked |
137
+ | `.supatent/.supatent-lock.json` | Sync state and checksums | Gitignored |
138
+ | `.supatent/.validation-status.json` | Last validation results (for AI agents) | Gitignored |
139
+
140
+ ## Common Validation Errors and Fixes
141
+
142
+ ### Slug Pattern Error
143
+
144
+ **Error:** `root: must match pattern "^[a-z0-9]+(?:-[a-z0-9]+)*$"` or `fields[N].slug: must match pattern`
145
+
146
+ **Cause:** Slug contains invalid characters (uppercase, underscores, spaces, consecutive hyphens, leading/trailing hyphens).
147
+
148
+ **Fix:** Use only lowercase letters, numbers, and single hyphens. Example: `my-field-name`, not `myFieldName` or `my_field`.
149
+
150
+ ### Missing Required Property
151
+
152
+ **Error:** `root: must have required property 'slug'` (or `name`, `isSingleton`, `fields`, `type`, `interface`, `order`)
153
+
154
+ **Cause:** A required property is missing from the schema or field definition.
155
+
156
+ **Fix:** Add the missing property. Required schema properties: `slug`, `name`, `isSingleton`, `fields`. Required field properties: `slug`, `name`, `type`, `interface`, `order`.
157
+
158
+ ### Unknown Field in Content
159
+
160
+ **Error:** `Unknown field 'fieldName' is not defined in the schema`
161
+
162
+ **Cause:** The content file contains a key that does not match any field slug in the schema.
163
+
164
+ **Fix:** Check the schema's field slugs and use the exact slug. The validator suggests close matches (e.g., "Did you mean 'title'?"). Valid fields are listed in the error message.
165
+
166
+ ### Interface Not Valid for Type
167
+
168
+ **Error:** `Field 'fieldSlug': interface 'textarea' is not valid for type 'number'`
169
+
170
+ **Cause:** The field's `interface` is not compatible with its `type`.
171
+
172
+ **Fix:** Use a compatible interface. Valid combinations:
173
+ - `text` -> `textInput`, `textarea`
174
+ - `number` -> `numberInput`
175
+ - `image` -> `singleImage`, `multiImage`
176
+ - `video` -> `singleVideo`, `multiVideo`
177
+ - `markdown` -> `markdownEditor`
178
+ - `jsonLd` -> `jsonLdEditor`
179
+
180
+ ### Filename-Slug Mismatch
181
+
182
+ **Error:** `Slug 'my-post' doesn't match filename 'blog-post.json'`
183
+
184
+ **Cause:** The `slug` value inside the JSON file does not match the filename (without `.json`).
185
+
186
+ **Fix:** Either change the `slug` property to match the filename, or rename the file to match the slug.
187
+
188
+ ### Duplicate Field Slugs
189
+
190
+ **Error:** `Duplicate field slug: 'title' (appears at index 0 and 2)`
191
+
192
+ **Cause:** Two fields in the same schema have identical slugs.
193
+
194
+ **Fix:** Rename one of the duplicate fields to a unique slug.
195
+
196
+ ### Singleton Slug Error
197
+
198
+ **Error:** `Singleton content file must use slug 'default', got 'my-settings'`
199
+
200
+ **Cause:** A content file for a singleton schema uses a slug other than `"default"`.
201
+
202
+ **Fix:** Rename the content file to `default.{locale}.json` (e.g., `default.en.json`).
203
+
204
+ ### Missing Content Field
205
+
206
+ **Error:** `Field 'body' is missing from content`
207
+
208
+ **Cause:** A field defined in the schema is not present in the content file.
209
+
210
+ **Fix:** Add the missing field to the content file with the correct value type.
211
+
212
+ ### Missing Markdown Asset Slug (Warning)
213
+
214
+ **Warning:** `Field 'body': markdown references missing asset slug 'hero-image'`
215
+
216
+ **Cause:** A markdown field references an asset slug that does not exist in local asset metadata. Checked forms include:
217
+ - `![alt](asset-slug)`
218
+ - `[text](asset-slug)`
219
+ - `<img src="asset-slug" ...>`
220
+
221
+ **Fix:** Create the asset metadata/file for that slug (for example `.supatent/assets/hero-image.en.json`) or update the markdown link to an existing slug.
222
+
223
+ **Agent note:** This is warning-only (`type: "markdown-asset"`). It appears in `supatent validate`, `supatent dev`, and pre-push validation, but does not block sync.
224
+
225
+ ### JSON-LD Validation Errors
226
+
227
+ **Error:** `Field 'structured-data': @root: Missing required property "@context"` or `Missing required property "@type"`
228
+
229
+ **Cause:** The JSON-LD object is missing required schema.org properties.
230
+
231
+ **Fix:** Ensure the object includes at minimum:
232
+ ```json
233
+ {
234
+ "@context": "https://schema.org",
235
+ "@type": "Article"
236
+ }
237
+ ```
238
+
239
+ The `@type` must be one of the 23 supported types (see schema-reference.md for the full list). Additional property validation is handled by the `@supatent/jsonld-schemas` package.
240
+
241
+ ## JSON-LD Creation Guidance
242
+
243
+ To add structured data to a schema:
244
+
245
+ 1. **Add a JSON-LD field to the schema:**
246
+ ```json
247
+ {
248
+ "slug": "structured-data",
249
+ "name": "Structured Data",
250
+ "type": "jsonLd",
251
+ "interface": "jsonLdEditor",
252
+ "order": 10
253
+ }
254
+ ```
255
+
256
+ 2. **Add the JSON-LD value in the content file:**
257
+ ```json
258
+ {
259
+ "structured-data": {
260
+ "@context": "https://schema.org",
261
+ "@type": "Article",
262
+ "headline": "My Article Title",
263
+ "author": {
264
+ "@type": "Person",
265
+ "name": "Jane Doe"
266
+ },
267
+ "datePublished": "2026-01-15"
268
+ }
269
+ }
270
+ ```
271
+
272
+ 3. **Requirements:**
273
+ - `@context` must be `"https://schema.org"` (required)
274
+ - `@type` must be one of the 23 supported types (required)
275
+ - Additional properties follow schema.org specifications for that type
276
+ - Deep property validation is handled by `@supatent/jsonld-schemas`
277
+
278
+ 4. **Common patterns:**
279
+ - Blog posts: `@type: "Article"` with `headline`, `author`, `datePublished`
280
+ - Products: `@type: "Product"` with `name`, `description`, `offers`
281
+ - FAQ sections: `@type: "FAQPage"` with `mainEntity` array of `Question` items
282
+ - Business pages: `@type: "LocalBusiness"` with `name`, `address`, `telephone`
283
+
284
+ 5. **Empty JSON-LD fields** produce warnings (not errors) -- they are optional for SEO enhancement.
285
+
286
+ ## Dev Mode Details
287
+
288
+ Dev mode (`supatent dev`) provides continuous bidirectional sync:
289
+
290
+ **Local to Remote (file watcher):**
291
+ - Uses chokidar to watch the `.supatent/` directory for file changes
292
+ - Debounces changes (300ms) to batch rapid edits
293
+ - Auto-validates before pushing -- invalid files are not pushed
294
+ - Updates the lock file after successful push
295
+
296
+ **Remote to Local (Convex WebSocket):**
297
+ - Subscribes to `draftWatch.draftChangeIndicator` reactive query via ConvexClient
298
+ - Receives change events when any draft schema, content, or asset changes remotely
299
+ - Triggers delta-pull on change, checking for conflicts first
300
+ - Updates the lock file after successful pull
301
+
302
+ **Remote checksum cache:** Dev mode caches remote checksums for 5 seconds to reduce API calls during rapid local edits. The cache is invalidated when a remote change event arrives.
303
+
304
+ **If dev mode is not running:** Use `supatent validate` to check files after editing, and `supatent push` when ready to upload.
305
+
306
+ ## Validation Status File
307
+
308
+ The `.validation-status.json` file is written by `supatent validate` and `supatent dev` after each validation run. AI agents should read this file to confirm whether their changes are valid.
309
+
310
+ **Location:** `.supatent/.validation-status.json`
311
+
312
+ **Structure:**
313
+ ```json
314
+ {
315
+ "valid": true,
316
+ "timestamp": "2026-01-15T14:30:00.000Z",
317
+ "trigger": "file-change",
318
+ "summary": {
319
+ "filesChecked": 12,
320
+ "filesValid": 12,
321
+ "filesInvalid": 0,
322
+ "errorCount": 0,
323
+ "warningCount": 2
324
+ },
325
+ "errors": [],
326
+ "warnings": [
327
+ {
328
+ "path": "content/blog/my-post",
329
+ "type": "locale",
330
+ "message": "Missing locales: fr",
331
+ "help": "Create files: my-post.fr.json"
332
+ }
333
+ ],
334
+ "localeCoverage": {
335
+ "expected": ["en", "fr"],
336
+ "stats": [
337
+ {
338
+ "schemaSlug": "blog",
339
+ "totalItems": 5,
340
+ "completeItems": 3
341
+ }
342
+ ]
343
+ }
344
+ }
345
+ ```
346
+
347
+ **Key fields for AI agents:**
348
+ - `valid`: `true` if no errors (warnings are acceptable)
349
+ - `errors[]`: Each error includes `path`, `message`, and `help` (actionable fix instruction)
350
+ - `warnings[]`: Non-blocking issues (locale coverage, empty JSON-LD fields, missing markdown asset slugs)
351
+ - `trigger`: What caused this validation (`"file-change"`, `"manual"`, or `"startup"`)
352
+
353
+ **Workflow for AI agents:**
354
+ 1. Make changes to schema or content files
355
+ 2. If dev mode is running, wait for auto-validation
356
+ 3. If dev mode is not running, execute `supatent validate`
357
+ 4. Read `.supatent/.validation-status.json`
358
+ 5. If `valid: false`, read `errors[]` and fix each issue using the `help` text
359
+ 6. Repeat until `valid: true`