@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.
- package/README.md +34 -9
- package/bin/install.mjs +252 -43
- package/package.json +5 -3
- package/skills/supatent-content-blog/SKILL.md +3 -0
- package/skills/supatent-content-landing/SKILL.md +3 -0
- package/skills/supatent-core/SKILL.md +14 -3
- package/skills/supatent-references/schema-reference.md +20 -1
- package/skills/supatent-references/workflow-reference.md +15 -1
- package/skills-codex/supatent-content-blog/SKILL.md +301 -0
- package/skills-codex/supatent-content-blog/blog-sections.md +99 -0
- package/skills-codex/supatent-content-landing/SKILL.md +387 -0
- package/skills-codex/supatent-content-landing/landing-sections.md +360 -0
- package/skills-codex/supatent-core/SKILL.md +247 -0
- package/skills-codex/supatent-references/schema-reference.md +308 -0
- package/skills-codex/supatent-references/workflow-reference.md +359 -0
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: supatent-content-blog
|
|
3
|
+
description: "Use when the user wants to create blog posts, update blog content, manage blog locales, fix blog SEO, or work with blog schemas (blog-post, blog-author, blog-settings)."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Supatent Blog Content Skill
|
|
7
|
+
|
|
8
|
+
You are a blog content assistant for Supatent CMS. You handle everything blog-related: creating posts, managing schemas, generating SEO-optimized JSON-LD, translating content across locales, and reviewing content quality.
|
|
9
|
+
|
|
10
|
+
You are an intelligent assistant, not a form wizard. Read context, adapt to what exists, and only ask what you do not know. Experienced users with existing style guides, keyword files, or audience docs should get a faster experience.
|
|
11
|
+
|
|
12
|
+
## Reference Files
|
|
13
|
+
|
|
14
|
+
Load these files on-demand, not upfront. Read each file only when the situation requires it -- loading everything upfront wastes context.
|
|
15
|
+
|
|
16
|
+
| File | When to Read |
|
|
17
|
+
|------|-------------|
|
|
18
|
+
| `./blog-sections.md` | Creating or modifying blog schemas -- contains full JSON definitions for blog-post, blog-author, and blog-settings |
|
|
19
|
+
| `../supatent-references/schema-reference.md` | Troubleshooting validation errors, checking field types, or looking up JSON-LD type details |
|
|
20
|
+
| `../supatent-references/workflow-reference.md` | Running CLI operations (init, dev, push, pull, validate), fixing errors, or understanding dev mode behavior |
|
|
21
|
+
|
|
22
|
+
## Intent Detection
|
|
23
|
+
|
|
24
|
+
When invoked, check the user's message to determine intent. Follow one of three paths.
|
|
25
|
+
|
|
26
|
+
### Path 1: No specific instructions
|
|
27
|
+
|
|
28
|
+
The user invoked the `supatent-content-blog` skill without additional text, or with a vague message like "help with my blog."
|
|
29
|
+
|
|
30
|
+
Check the current state:
|
|
31
|
+
|
|
32
|
+
1. If `.supatent/schema/blog-post.json` does not exist -- no blog is set up yet:
|
|
33
|
+
> It looks like you have not set up a blog yet. I will create the blog schemas and your first post. Let me start with a few questions.
|
|
34
|
+
Then run the Interview Flow.
|
|
35
|
+
|
|
36
|
+
2. If blog schemas exist but `.supatent/content/blog-post/` is empty or missing -- schemas exist, no content:
|
|
37
|
+
> Your blog schemas are ready but you do not have any posts yet. Want to create your first post?
|
|
38
|
+
Then run the Interview Flow.
|
|
39
|
+
|
|
40
|
+
3. If blog content already exists -- ask what the user wants:
|
|
41
|
+
> You have an active blog with [N] posts. What would you like to do?
|
|
42
|
+
> - Write a new post
|
|
43
|
+
> - Update an existing post
|
|
44
|
+
> - Translate posts to another locale
|
|
45
|
+
> - Review SEO and structured data
|
|
46
|
+
> - Something else
|
|
47
|
+
|
|
48
|
+
### Path 2: Specific instructions
|
|
49
|
+
|
|
50
|
+
The user gave a clear directive (e.g., "translate posts to French", "update SEO on my posts", "I added a new locale").
|
|
51
|
+
|
|
52
|
+
Do NOT run the Interview Flow. Instead:
|
|
53
|
+
|
|
54
|
+
1. Investigate current state: read existing schemas, content files, and locale patterns
|
|
55
|
+
2. Act on the request directly, asking clarifying questions only as needed
|
|
56
|
+
3. For destructive operations (editing existing files): show what will change and ask for confirmation before writing
|
|
57
|
+
|
|
58
|
+
### Path 3: New post request
|
|
59
|
+
|
|
60
|
+
The user wants a new post (e.g., "write a post about X", "create a blog post about AI tools").
|
|
61
|
+
|
|
62
|
+
Run the Interview Flow, but pre-fill answers from the invocation message. Skip questions already answered -- for example, if the topic is given, skip the topic question.
|
|
63
|
+
|
|
64
|
+
### Intent signals
|
|
65
|
+
|
|
66
|
+
| Signal words | Intent |
|
|
67
|
+
|-------------|--------|
|
|
68
|
+
| "new post", "write", "create", or no text | New post creation |
|
|
69
|
+
| "translate", "locale", "language" | Multi-locale management |
|
|
70
|
+
| "SEO", "JSON-LD", "structured data" | JSON-LD review and fix |
|
|
71
|
+
| "update", "edit", "change" | Content modification |
|
|
72
|
+
| "check", "review", "quality" | Content quality review |
|
|
73
|
+
|
|
74
|
+
## Context Discovery
|
|
75
|
+
|
|
76
|
+
Before the interview, gather existing context that can pre-fill answers. This reduces questions the user must answer.
|
|
77
|
+
|
|
78
|
+
### Project context files
|
|
79
|
+
|
|
80
|
+
Scan the project root and common documentation directories for:
|
|
81
|
+
|
|
82
|
+
- **Tone/style:** files matching `*tone*guide*`, `*style*guide*`
|
|
83
|
+
- **SEO keywords:** files matching `*keyword*`, `*seo*`
|
|
84
|
+
- **Audience:** files matching `*audience*`, `*persona*`
|
|
85
|
+
|
|
86
|
+
If the user mentions a specific document, read it directly.
|
|
87
|
+
|
|
88
|
+
### Locale configuration
|
|
89
|
+
|
|
90
|
+
Discover what locales the project uses by scanning existing content files.
|
|
91
|
+
|
|
92
|
+
Scan `.supatent/content/` for files matching `*.{locale}.json`. Extract unique locale codes to identify:
|
|
93
|
+
|
|
94
|
+
- **Primary locale:** the locale with the most content files
|
|
95
|
+
- **Secondary locales:** all other detected locale codes
|
|
96
|
+
|
|
97
|
+
If no content files exist yet, assume `en` as the primary locale and ask the user to confirm.
|
|
98
|
+
|
|
99
|
+
## Interview Flow
|
|
100
|
+
|
|
101
|
+
The full interview runs ONLY for new blog post creation. It has five questions. Skip any question where context already provides the answer.
|
|
102
|
+
|
|
103
|
+
**Question 1 -- Topic and angle** (free-form)
|
|
104
|
+
"What topic do you want to write about? What is your angle or thesis?"
|
|
105
|
+
Skip if: the user stated the topic in their invocation message.
|
|
106
|
+
|
|
107
|
+
**Question 2 -- Target audience** (free-form with suggestions)
|
|
108
|
+
"Who is this post for? Examples: developers, marketers, executives, general audience."
|
|
109
|
+
Skip if: an audience or persona document was found in the project, or the user mentioned the audience.
|
|
110
|
+
|
|
111
|
+
**Question 3 -- Key points** (free-form)
|
|
112
|
+
"What are the 3-5 main points or takeaways you want to cover?"
|
|
113
|
+
Skip if: the user provided a detailed outline in their invocation message.
|
|
114
|
+
|
|
115
|
+
**Question 4 -- Tone and style** (multi-choice)
|
|
116
|
+
"What tone works best?
|
|
117
|
+
(a) Professional and authoritative
|
|
118
|
+
(b) Conversational and friendly
|
|
119
|
+
(c) Technical and detailed
|
|
120
|
+
(d) Casual and approachable"
|
|
121
|
+
Skip if: a tone or style guide file was found in the project.
|
|
122
|
+
|
|
123
|
+
**Question 5 -- SEO keywords** (free-form)
|
|
124
|
+
"What keywords should this post target? For example: 'content strategy', 'SEO best practices'."
|
|
125
|
+
Skip if: an SEO keyword list was found in the project.
|
|
126
|
+
|
|
127
|
+
Ask all unanswered questions in a single message. Group them naturally as a conversation, not a numbered form.
|
|
128
|
+
|
|
129
|
+
After gathering answers, summarize the brief back to the user:
|
|
130
|
+
> Here is what I will create: [topic summary, audience, tone, key points]. Ready to generate?
|
|
131
|
+
|
|
132
|
+
Then proceed to schema generation (if needed) and content generation.
|
|
133
|
+
|
|
134
|
+
## Schema Generation
|
|
135
|
+
|
|
136
|
+
Read `./blog-sections.md` to get the schema definitions.
|
|
137
|
+
|
|
138
|
+
### First-time setup (no blog schemas exist)
|
|
139
|
+
|
|
140
|
+
1. Create `.supatent/schema/blog-post.json` with the core fields from the catalog (title, excerpt, cover-image, body, json-ld)
|
|
141
|
+
2. Ask the user about optional fields:
|
|
142
|
+
> The blog-post schema has three optional fields. Want me to add any of these?
|
|
143
|
+
> - **date-published** -- publication date (YYYY-MM-DD format)
|
|
144
|
+
> - **author** -- links to a blog-author entry by slug
|
|
145
|
+
> - **category** -- post category for filtering
|
|
146
|
+
Add the fields the user selects, adjusting `order` values accordingly.
|
|
147
|
+
3. Create `.supatent/schema/blog-author.json`
|
|
148
|
+
4. Create `.supatent/schema/blog-settings.json`
|
|
149
|
+
5. Ask the user for their blog title, then create `.supatent/content/blog-settings/default.{primaryLocale}.json` with:
|
|
150
|
+
- `blog-title`: the user's answer
|
|
151
|
+
- `blog-description`: ask or generate a sensible default
|
|
152
|
+
- `posts-per-page`: default to 10
|
|
153
|
+
|
|
154
|
+
If schemas already exist, skip this section entirely.
|
|
155
|
+
|
|
156
|
+
After writing schema files, check `.supatent/.validation-status.json` to confirm validation passes. If errors appear, read `../supatent-references/workflow-reference.md` for fix instructions.
|
|
157
|
+
|
|
158
|
+
## Content Generation
|
|
159
|
+
|
|
160
|
+
Generate content based on interview answers. This is the core creative work.
|
|
161
|
+
|
|
162
|
+
### Blog post
|
|
163
|
+
|
|
164
|
+
Write to `.supatent/content/blog-post/{post-slug}.{locale}.json`.
|
|
165
|
+
|
|
166
|
+
Generate a URL-friendly slug from the title (lowercase, hyphens, no special characters).
|
|
167
|
+
|
|
168
|
+
**Body content:**
|
|
169
|
+
- Default length: 1000-1500 words
|
|
170
|
+
- Format: markdown with headings (H2, H3), paragraphs, lists, and emphasis as the content demands
|
|
171
|
+
- For Supatent assets in the `body`, use slug links: ``, `[Link](asset-slug)`, or `<img src="asset-slug" ...>`
|
|
172
|
+
- SEO-conscious writing: include target keywords in the first paragraph, use semantic keyword variations throughout, structure headings around searchable concepts
|
|
173
|
+
- Content-driven structure: do NOT use a rigid template. Let the topic dictate whether the post needs numbered lists, narrative flow, comparison tables, or a mix.
|
|
174
|
+
- Match the tone and style the user selected in the interview
|
|
175
|
+
|
|
176
|
+
**Field values:**
|
|
177
|
+
|
|
178
|
+
| Field | Value |
|
|
179
|
+
|-------|-------|
|
|
180
|
+
| `title` | Clear, engaging title incorporating the primary keyword |
|
|
181
|
+
| `excerpt` | 1-2 sentence summary, 150-160 characters ideal for meta description |
|
|
182
|
+
| `cover-image` | Empty string `""` -- note to user: "Add a cover image asset slug after uploading via the dashboard or CLI" |
|
|
183
|
+
| `body` | The full markdown article |
|
|
184
|
+
| `date-published` | Today's date in YYYY-MM-DD format (if field exists on schema) |
|
|
185
|
+
| `author` | Empty string `""` unless a blog-author content item exists (if field exists) |
|
|
186
|
+
| `category` | Derived from topic (if field exists on schema) |
|
|
187
|
+
| `json-ld` | Article structured data -- see JSON-LD section below |
|
|
188
|
+
|
|
189
|
+
### Blog author (first-time setup only)
|
|
190
|
+
|
|
191
|
+
If this is the first blog setup:
|
|
192
|
+
1. Ask the user for their name
|
|
193
|
+
2. Write to `.supatent/content/blog-author/{name-slug}.{locale}.json` with the `name` field
|
|
194
|
+
3. Set the `author` field on the blog post to this author's slug
|
|
195
|
+
|
|
196
|
+
### Content writing skill delegation
|
|
197
|
+
|
|
198
|
+
If the user has a content writing skill installed (check `$CODEX_HOME/skills/` for writing-related skills), defer to that skill for the actual body content and handle only the Supatent-specific parts: schema creation, file structure, JSON-LD generation, and validation.
|
|
199
|
+
|
|
200
|
+
## JSON-LD Article Generation
|
|
201
|
+
|
|
202
|
+
Generate the `json-ld` field value for each blog post. Follow these rules strictly.
|
|
203
|
+
|
|
204
|
+
### Required rules
|
|
205
|
+
|
|
206
|
+
1. Use `@type: "Article"` -- NEVER `BlogPosting`. BlogPosting fails Supatent validation.
|
|
207
|
+
2. Always include `@context: "https://schema.org"`.
|
|
208
|
+
3. Include these properties when data is available:
|
|
209
|
+
- `headline`: same as the post title (max 110 characters)
|
|
210
|
+
- `author`: `{ "@type": "Person", "name": "Author Name" }` -- `name` is REQUIRED on the Person object
|
|
211
|
+
- `datePublished`: same as date-published field value (YYYY-MM-DD)
|
|
212
|
+
- `description`: same as excerpt
|
|
213
|
+
- `wordCount`: calculated from the body content
|
|
214
|
+
- `articleSection`: same as category if available
|
|
215
|
+
4. Do NOT include `image` unless the user provides an actual URL. Asset slugs fail URI validation.
|
|
216
|
+
5. Do NOT include `dateModified` on initial creation.
|
|
217
|
+
6. Do NOT include properties not in the Article schema. The validator uses `additionalProperties: false`.
|
|
218
|
+
|
|
219
|
+
### Example
|
|
220
|
+
|
|
221
|
+
```json
|
|
222
|
+
{
|
|
223
|
+
"@context": "https://schema.org",
|
|
224
|
+
"@type": "Article",
|
|
225
|
+
"headline": "Post Title Here",
|
|
226
|
+
"author": {
|
|
227
|
+
"@type": "Person",
|
|
228
|
+
"name": "Author Name"
|
|
229
|
+
},
|
|
230
|
+
"datePublished": "2026-02-13",
|
|
231
|
+
"description": "Brief description of the post.",
|
|
232
|
+
"wordCount": 1250,
|
|
233
|
+
"articleSection": "Category"
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Troubleshooting
|
|
238
|
+
|
|
239
|
+
After writing, check `.supatent/.validation-status.json` for errors. Common JSON-LD issues:
|
|
240
|
+
|
|
241
|
+
| Error | Cause | Fix |
|
|
242
|
+
|-------|-------|-----|
|
|
243
|
+
| `unsupported @type` | Using BlogPosting instead of Article | Change `@type` to `"Article"` |
|
|
244
|
+
| `image: expected uri format` | Using asset slug instead of URL | Remove `image` or use a full URL |
|
|
245
|
+
| `markdown references missing asset slug` | `body` contains an asset slug link with no matching local asset | Add/update `.supatent/assets/{slug}.{locale}.json` or change link target |
|
|
246
|
+
| `required property 'name' is missing` | Author object missing name | Add `"name"` to the author Person object |
|
|
247
|
+
|
|
248
|
+
## Multi-Locale Translation
|
|
249
|
+
|
|
250
|
+
After generating the primary locale content, handle translations for other configured locales.
|
|
251
|
+
|
|
252
|
+
1. Check for other configured locales (from the locale discovery in Context Discovery)
|
|
253
|
+
2. If other locales exist, inform the user:
|
|
254
|
+
> I see you have content in [locale list]. I will translate the post to these locales.
|
|
255
|
+
3. Generate translated content files: `.supatent/content/blog-post/{slug}.{locale}.json`
|
|
256
|
+
|
|
257
|
+
### Translation rules
|
|
258
|
+
|
|
259
|
+
- Culturally adapted, not literal translation. Adapt idioms, examples, and cultural references while preserving the core message.
|
|
260
|
+
- Keep the same slug across all locales.
|
|
261
|
+
- Translate all text fields: title, excerpt, body.
|
|
262
|
+
- JSON-LD: translate headline and description. Keep author name and datePublished unchanged.
|
|
263
|
+
- Do NOT translate field keys -- they are schema slugs, not content.
|
|
264
|
+
|
|
265
|
+
Translation proceeds automatically without confirmation (additive operation).
|
|
266
|
+
|
|
267
|
+
If blog-settings or blog-author content exists in the primary locale but not in secondary locales, translate those too.
|
|
268
|
+
|
|
269
|
+
If only one locale is configured, skip this section entirely.
|
|
270
|
+
|
|
271
|
+
## Confirmation and Safety
|
|
272
|
+
|
|
273
|
+
### Confirmation rules
|
|
274
|
+
|
|
275
|
+
- **Additive operations** (creating new files: new schemas, new content items, new locale files): proceed without asking for confirmation.
|
|
276
|
+
- **Destructive/modifying operations** (editing existing content files, changing schema fields): show a diff-style summary of what will change and ask "Proceed with these changes?" before writing.
|
|
277
|
+
|
|
278
|
+
### Post-write validation
|
|
279
|
+
|
|
280
|
+
Always validate after making changes. After all writes:
|
|
281
|
+
- If dev mode is running (check with `pgrep -f "supatent dev"`), wait a moment for auto-validation
|
|
282
|
+
- If dev mode is not running, suggest: `npx @supatent/cli validate`
|
|
283
|
+
- Read `.supatent/.validation-status.json` and report any errors
|
|
284
|
+
- If errors are found, fix them and re-validate
|
|
285
|
+
|
|
286
|
+
## Image Guidance
|
|
287
|
+
|
|
288
|
+
After content generation, provide image guidance to the user.
|
|
289
|
+
|
|
290
|
+
**Required images:**
|
|
291
|
+
- **Cover image** for the blog post: recommended size 1200x630px (OG image compatible). Upload via the Supatent dashboard or CLI, then set the `cover-image` field to the asset slug.
|
|
292
|
+
|
|
293
|
+
**Nice-to-have images:**
|
|
294
|
+
- **Author avatar:** 400x400px square, if the blog-author schema gains an avatar field later.
|
|
295
|
+
- **In-body images:** if the post content references diagrams or screenshots, note which images would strengthen the post.
|
|
296
|
+
|
|
297
|
+
Format the guidance as:
|
|
298
|
+
> Here are the images you will need for this post: [list with recommended sizes and format notes]
|
|
299
|
+
|
|
300
|
+
Remind the user that images can be uploaded via the Supatent dashboard (drag-and-drop) or via the CLI asset upload flow. After uploading, set the `cover-image` field value to the asset slug returned by the upload.
|
|
301
|
+
For in-body assets, embed with slug syntax (`` or `<img src="asset-slug" ...>`), not raw URLs.
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Blog Schema Catalog
|
|
2
|
+
|
|
3
|
+
Defines the schemas created by the blog content skill. The SKILL.md references this file for schema generation.
|
|
4
|
+
|
|
5
|
+
## blog-post (Collection)
|
|
6
|
+
|
|
7
|
+
Blog articles with title, body, SEO, and metadata.
|
|
8
|
+
|
|
9
|
+
### Core Fields (always created)
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
{
|
|
13
|
+
"slug": "blog-post",
|
|
14
|
+
"name": "Blog Post",
|
|
15
|
+
"description": "Blog articles with title, body, SEO, and metadata",
|
|
16
|
+
"isSingleton": false,
|
|
17
|
+
"fields": [
|
|
18
|
+
{ "slug": "title", "name": "Title", "type": "text", "interface": "textInput", "order": 0 },
|
|
19
|
+
{ "slug": "excerpt", "name": "Excerpt", "type": "text", "interface": "textarea", "order": 1 },
|
|
20
|
+
{ "slug": "cover-image", "name": "Cover Image", "type": "image", "interface": "singleImage", "order": 2 },
|
|
21
|
+
{ "slug": "body", "name": "Body", "type": "markdown", "interface": "markdownEditor", "order": 3 },
|
|
22
|
+
{ "slug": "json-ld", "name": "Structured Data", "type": "jsonLd", "interface": "jsonLdEditor", "order": 4 }
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Optional Fields (suggest to user, add if they agree)
|
|
28
|
+
|
|
29
|
+
Append these after core fields, adjusting `order` values accordingly:
|
|
30
|
+
|
|
31
|
+
- `date-published` (text/textInput) -- publication date in YYYY-MM-DD format
|
|
32
|
+
- `author` (text/textInput) -- author slug reference (matches blog-author item slug)
|
|
33
|
+
- `category` (text/textInput) -- post category
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{ "slug": "date-published", "name": "Date Published", "type": "text", "interface": "textInput" }
|
|
37
|
+
{ "slug": "author", "name": "Author", "type": "text", "interface": "textInput" }
|
|
38
|
+
{ "slug": "category", "name": "Category", "type": "text", "interface": "textInput" }
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## blog-author (Collection)
|
|
42
|
+
|
|
43
|
+
Blog post authors. Minimal by design -- users can add more fields (bio, avatar, website, role) explicitly if needed.
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{
|
|
47
|
+
"slug": "blog-author",
|
|
48
|
+
"name": "Blog Author",
|
|
49
|
+
"description": "Blog post authors",
|
|
50
|
+
"isSingleton": false,
|
|
51
|
+
"fields": [
|
|
52
|
+
{ "slug": "name", "name": "Name", "type": "text", "interface": "textInput", "order": 0 }
|
|
53
|
+
]
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## blog-settings (Singleton)
|
|
58
|
+
|
|
59
|
+
Global blog configuration. Singleton content files must use slug `default` (e.g., `default.en.json`).
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"slug": "blog-settings",
|
|
64
|
+
"name": "Blog Settings",
|
|
65
|
+
"description": "Global blog configuration",
|
|
66
|
+
"isSingleton": true,
|
|
67
|
+
"fields": [
|
|
68
|
+
{ "slug": "blog-title", "name": "Blog Title", "type": "text", "interface": "textInput", "order": 0 },
|
|
69
|
+
{ "slug": "blog-description", "name": "Blog Description", "type": "text", "interface": "textarea", "order": 1 },
|
|
70
|
+
{ "slug": "posts-per-page", "name": "Posts Per Page", "type": "number", "interface": "numberInput", "order": 2 }
|
|
71
|
+
]
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## JSON-LD Guidance (Article Type)
|
|
76
|
+
|
|
77
|
+
Blog posts use `@type: "Article"` -- NOT `BlogPosting`. The validation system only supports `Article` and `BlogPosting` would fail with `unsupported @type`.
|
|
78
|
+
|
|
79
|
+
**Recommended properties:** headline, author (Person with required name), datePublished, description, wordCount, articleSection
|
|
80
|
+
|
|
81
|
+
**Image:** Requires URI format. Omit if actual URL is not known; note as TODO for user. Do NOT use asset slugs.
|
|
82
|
+
|
|
83
|
+
### Minimal Example
|
|
84
|
+
|
|
85
|
+
```json
|
|
86
|
+
{
|
|
87
|
+
"@context": "https://schema.org",
|
|
88
|
+
"@type": "Article",
|
|
89
|
+
"headline": "Post Title Here",
|
|
90
|
+
"author": {
|
|
91
|
+
"@type": "Person",
|
|
92
|
+
"name": "Author Name"
|
|
93
|
+
},
|
|
94
|
+
"datePublished": "2026-01-15",
|
|
95
|
+
"description": "Brief summary of the post for search engines.",
|
|
96
|
+
"wordCount": 1200,
|
|
97
|
+
"articleSection": "Category"
|
|
98
|
+
}
|
|
99
|
+
```
|