@supatent/skills 0.1.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/bin/install.mjs +318 -0
- package/package.json +43 -0
- package/skills/content-blog/SKILL.md +300 -0
- package/skills/content-blog/blog-sections.md +99 -0
- package/skills/content-landing/SKILL.md +386 -0
- package/skills/content-landing/landing-sections.md +360 -0
- package/skills/core/SKILL.md +237 -0
- package/skills/references/schema-reference.md +289 -0
- package/skills/references/workflow-reference.md +345 -0
|
@@ -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`
|
|
@@ -0,0 +1,345 @@
|
|
|
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
|
+
- `markdown` -> `markdownEditor`
|
|
177
|
+
- `jsonLd` -> `jsonLdEditor`
|
|
178
|
+
|
|
179
|
+
### Filename-Slug Mismatch
|
|
180
|
+
|
|
181
|
+
**Error:** `Slug 'my-post' doesn't match filename 'blog-post.json'`
|
|
182
|
+
|
|
183
|
+
**Cause:** The `slug` value inside the JSON file does not match the filename (without `.json`).
|
|
184
|
+
|
|
185
|
+
**Fix:** Either change the `slug` property to match the filename, or rename the file to match the slug.
|
|
186
|
+
|
|
187
|
+
### Duplicate Field Slugs
|
|
188
|
+
|
|
189
|
+
**Error:** `Duplicate field slug: 'title' (appears at index 0 and 2)`
|
|
190
|
+
|
|
191
|
+
**Cause:** Two fields in the same schema have identical slugs.
|
|
192
|
+
|
|
193
|
+
**Fix:** Rename one of the duplicate fields to a unique slug.
|
|
194
|
+
|
|
195
|
+
### Singleton Slug Error
|
|
196
|
+
|
|
197
|
+
**Error:** `Singleton content file must use slug 'default', got 'my-settings'`
|
|
198
|
+
|
|
199
|
+
**Cause:** A content file for a singleton schema uses a slug other than `"default"`.
|
|
200
|
+
|
|
201
|
+
**Fix:** Rename the content file to `default.{locale}.json` (e.g., `default.en.json`).
|
|
202
|
+
|
|
203
|
+
### Missing Content Field
|
|
204
|
+
|
|
205
|
+
**Error:** `Field 'body' is missing from content`
|
|
206
|
+
|
|
207
|
+
**Cause:** A field defined in the schema is not present in the content file.
|
|
208
|
+
|
|
209
|
+
**Fix:** Add the missing field to the content file with the correct value type.
|
|
210
|
+
|
|
211
|
+
### JSON-LD Validation Errors
|
|
212
|
+
|
|
213
|
+
**Error:** `Field 'structured-data': @root: Missing required property "@context"` or `Missing required property "@type"`
|
|
214
|
+
|
|
215
|
+
**Cause:** The JSON-LD object is missing required schema.org properties.
|
|
216
|
+
|
|
217
|
+
**Fix:** Ensure the object includes at minimum:
|
|
218
|
+
```json
|
|
219
|
+
{
|
|
220
|
+
"@context": "https://schema.org",
|
|
221
|
+
"@type": "Article"
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
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.
|
|
226
|
+
|
|
227
|
+
## JSON-LD Creation Guidance
|
|
228
|
+
|
|
229
|
+
To add structured data to a schema:
|
|
230
|
+
|
|
231
|
+
1. **Add a JSON-LD field to the schema:**
|
|
232
|
+
```json
|
|
233
|
+
{
|
|
234
|
+
"slug": "structured-data",
|
|
235
|
+
"name": "Structured Data",
|
|
236
|
+
"type": "jsonLd",
|
|
237
|
+
"interface": "jsonLdEditor",
|
|
238
|
+
"order": 10
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
2. **Add the JSON-LD value in the content file:**
|
|
243
|
+
```json
|
|
244
|
+
{
|
|
245
|
+
"structured-data": {
|
|
246
|
+
"@context": "https://schema.org",
|
|
247
|
+
"@type": "Article",
|
|
248
|
+
"headline": "My Article Title",
|
|
249
|
+
"author": {
|
|
250
|
+
"@type": "Person",
|
|
251
|
+
"name": "Jane Doe"
|
|
252
|
+
},
|
|
253
|
+
"datePublished": "2026-01-15"
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
3. **Requirements:**
|
|
259
|
+
- `@context` must be `"https://schema.org"` (required)
|
|
260
|
+
- `@type` must be one of the 23 supported types (required)
|
|
261
|
+
- Additional properties follow schema.org specifications for that type
|
|
262
|
+
- Deep property validation is handled by `@supatent/jsonld-schemas`
|
|
263
|
+
|
|
264
|
+
4. **Common patterns:**
|
|
265
|
+
- Blog posts: `@type: "Article"` with `headline`, `author`, `datePublished`
|
|
266
|
+
- Products: `@type: "Product"` with `name`, `description`, `offers`
|
|
267
|
+
- FAQ sections: `@type: "FAQPage"` with `mainEntity` array of `Question` items
|
|
268
|
+
- Business pages: `@type: "LocalBusiness"` with `name`, `address`, `telephone`
|
|
269
|
+
|
|
270
|
+
5. **Empty JSON-LD fields** produce warnings (not errors) -- they are optional for SEO enhancement.
|
|
271
|
+
|
|
272
|
+
## Dev Mode Details
|
|
273
|
+
|
|
274
|
+
Dev mode (`supatent dev`) provides continuous bidirectional sync:
|
|
275
|
+
|
|
276
|
+
**Local to Remote (file watcher):**
|
|
277
|
+
- Uses chokidar to watch the `.supatent/` directory for file changes
|
|
278
|
+
- Debounces changes (300ms) to batch rapid edits
|
|
279
|
+
- Auto-validates before pushing -- invalid files are not pushed
|
|
280
|
+
- Updates the lock file after successful push
|
|
281
|
+
|
|
282
|
+
**Remote to Local (Convex WebSocket):**
|
|
283
|
+
- Subscribes to `draftWatch.draftChangeIndicator` reactive query via ConvexClient
|
|
284
|
+
- Receives change events when any draft schema, content, or asset changes remotely
|
|
285
|
+
- Triggers delta-pull on change, checking for conflicts first
|
|
286
|
+
- Updates the lock file after successful pull
|
|
287
|
+
|
|
288
|
+
**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.
|
|
289
|
+
|
|
290
|
+
**If dev mode is not running:** Use `supatent validate` to check files after editing, and `supatent push` when ready to upload.
|
|
291
|
+
|
|
292
|
+
## Validation Status File
|
|
293
|
+
|
|
294
|
+
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.
|
|
295
|
+
|
|
296
|
+
**Location:** `.supatent/.validation-status.json`
|
|
297
|
+
|
|
298
|
+
**Structure:**
|
|
299
|
+
```json
|
|
300
|
+
{
|
|
301
|
+
"valid": true,
|
|
302
|
+
"timestamp": "2026-01-15T14:30:00.000Z",
|
|
303
|
+
"trigger": "file-change",
|
|
304
|
+
"summary": {
|
|
305
|
+
"filesChecked": 12,
|
|
306
|
+
"filesValid": 12,
|
|
307
|
+
"filesInvalid": 0,
|
|
308
|
+
"errorCount": 0,
|
|
309
|
+
"warningCount": 2
|
|
310
|
+
},
|
|
311
|
+
"errors": [],
|
|
312
|
+
"warnings": [
|
|
313
|
+
{
|
|
314
|
+
"path": "content/blog/my-post",
|
|
315
|
+
"type": "locale",
|
|
316
|
+
"message": "Missing locales: fr",
|
|
317
|
+
"help": "Create files: my-post.fr.json"
|
|
318
|
+
}
|
|
319
|
+
],
|
|
320
|
+
"localeCoverage": {
|
|
321
|
+
"expected": ["en", "fr"],
|
|
322
|
+
"stats": [
|
|
323
|
+
{
|
|
324
|
+
"schemaSlug": "blog",
|
|
325
|
+
"totalItems": 5,
|
|
326
|
+
"completeItems": 3
|
|
327
|
+
}
|
|
328
|
+
]
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
**Key fields for AI agents:**
|
|
334
|
+
- `valid`: `true` if no errors (warnings are acceptable)
|
|
335
|
+
- `errors[]`: Each error includes `path`, `message`, and `help` (actionable fix instruction)
|
|
336
|
+
- `warnings[]`: Non-blocking issues (locale coverage, empty JSON-LD fields)
|
|
337
|
+
- `trigger`: What caused this validation (`"file-change"`, `"manual"`, or `"startup"`)
|
|
338
|
+
|
|
339
|
+
**Workflow for AI agents:**
|
|
340
|
+
1. Make changes to schema or content files
|
|
341
|
+
2. If dev mode is running, wait for auto-validation
|
|
342
|
+
3. If dev mode is not running, execute `supatent validate`
|
|
343
|
+
4. Read `.supatent/.validation-status.json`
|
|
344
|
+
5. If `valid: false`, read `errors[]` and fix each issue using the `help` text
|
|
345
|
+
6. Repeat until `valid: true`
|