@seoagent-official/seoagent 1.124.5 → 1.126.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seoagent-official/seoagent",
3
- "version": "1.124.5",
3
+ "version": "1.126.0",
4
4
  "description": "The persistent AI SEO agent for Claude Code. Audits, keyword strategy, briefs, articles, real product screenshots from your repo, and the autopilot loop (cloud detects → CLI executes → ack closes) — other SEO tools write the prompt, SEOAgent runs it.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -108,6 +108,11 @@ Start by reading `.seoagent/inbox/README.md` (or `seoagent inbox`) to see the li
108
108
  - **Check `mode:` first.** It is the whole contract:
109
109
  - **`mode: new`** — the slug is free. Review the draft (frontmatter carries title, meta description, status), then place it where this project's content renders: repo-native (mdx_sync) → copy/adapt into the repo's content directory and `seoagent content track` it; CMS → create the entry and track it; cloud-hosted → flip frontmatter `status` to `published` and sync.
110
110
  - **`mode: revision`** — that slug **already renders live on this site** (`replaces_path` names the file). **Do not place it as a new post and do not overwrite the live file.** `diff` the two, fold in only what is genuinely new or better, and keep the live article's URL, frontmatter and dates. If the draft adds nothing, decline — that is a real answer.
111
+ - **AUTHOR RULE (the byline).** The draft's frontmatter carries `author`, `author_title`, `author_url`, `author_same_as` (and `author_key` once known) only when the site owner set a person author. The task file's **Byline** section has the full rule:
112
+ - **No `author`:** write no author fields and change no template.
113
+ - **The repo's posts already show a byline:** use that convention (the same frontmatter key, the same authors file or registry; `author_key` is how this repo already names the author). Add a missing author to the authors file once.
114
+ - **The posts show no byline:** add one to the post template in the same change: the name linked to `author_url` with `rel="author"`, and the author as a `Person` in the page's Article JSON-LD. Say so in one line of the PR or commit message.
115
+ - Pass `--author-key <the value the post's author field or authors-file entry uses>` to `content track`, so the next draft already knows it. A `mode: revision` draft keeps the live article's byline.
111
116
  - **Match the destination's frontmatter contract, not just the draft's.** The cloud draft carries `title`, `meta_description`, and `status`; the repo's content directory may require fields it does not — an `ogImage`, an `excerpt`, a `date`, a tag list — and may enforce them in CI. Read the content directory's `README`/`_README` and one neighbouring post before writing the file. **Drafts arrive with no images**, so when a hero image is required, produce one in the site's existing style and commit it alongside the post; a draft placed exactly as delivered will otherwise turn the build red.
112
117
  - **Renaming the slug is encouraged** when the generated one reads as a full sentence; a short slug is the better URL. When you rename, pass `--supersedes <the-delivered-slug>` to `content track`. That is what tells the cloud it is the SAME article under a new name — without it the cloud keeps the original as an unfinished draft and delivers it to you all over again.
113
118
  - **A rename has a second half: the draft's own identity fields.** The delivered frontmatter carries the generated `slug:` (and often a `canonical`/`url`), so copying it verbatim into a file you renamed leaves the old slug behind in the body of the post. Loaders commonly resolve identity as `frontmatter.slug || filename` while the **route** resolves from the filename, so the page renders at the new URL and declares a canonical pointing at the old one — a silent self-canonical to a 404, on the page you just chose to publish. Nothing fails loudly. **Drop `slug:` when the destination derives it from the filename**, or update it to the new slug when the destination reads it; do the same for any `canonical`/`url` field. `--supersedes` fixes the cloud's record of the rename, not the repo's.
@@ -96,7 +96,7 @@ A listicle's defining schema is **`ItemList`** (in addition to `Article`). For t
96
96
  {
97
97
  "@type": "Article",
98
98
  "headline": "{Title}",
99
- "author": { "@type": "Person", "name": "{Author}" },
99
+ "author": { "@type": "Person", "name": "{author}", "jobTitle": "{author_title}", "url": "{author_url}", "sameAs": {author_same_as} },
100
100
  "datePublished": "{ISO date}",
101
101
  "dateModified": "{ISO date}",
102
102
  "image": "https://{domain}/{hero}",
@@ -114,6 +114,8 @@ A listicle's defining schema is **`ItemList`** (in addition to `Article`). For t
114
114
  ]
115
115
  ```
116
116
 
117
+ **Author:** take it from the draft's frontmatter: `author` → `name`, `author_title` → `jobTitle`, `author_url` → `url`, `author_same_as` → `sameAs`; leave out a key the draft does not have. No `author` in the frontmatter → use the publisher Organization as the `author`. Never invent a person. The byline on the page follows the same fields (see the AUTHOR RULE in `references/inbox.md`).
118
+
117
119
  Use `itemListOrder` `…OrderAscending`/`…OrderDescending` for a true ranking; omit it (or use unordered) for an unranked "best of". See `references/schema-markup.md` for the full JSON-LD rules.
118
120
 
119
121
  ## Quality rules — a listicle is LIGHTER than a guide/pillar
@@ -88,7 +88,7 @@ twitter:
88
88
  {
89
89
  "@type": "Article",
90
90
  "headline": "{Title}",
91
- "author": { "@type": "Person", "name": "{Author}" },
91
+ "author": { "@type": "Person", "name": "{author}", "jobTitle": "{author_title}", "url": "{author_url}", "sameAs": {author_same_as} },
92
92
  "datePublished": "{ISO date}",
93
93
  "dateModified": "{ISO date}",
94
94
  "image": "https://{domain}/{hero}",
@@ -97,6 +97,8 @@ twitter:
97
97
  ]
98
98
  ```
99
99
 
100
+ **Author:** take it from the draft's frontmatter: `author` → `name`, `author_title` → `jobTitle`, `author_url` → `url`, `author_same_as` → `sameAs`; leave out a key the draft does not have. No `author` in the frontmatter → use the publisher Organization as the `author`. Never invent a person. The byline on the page follows the same fields (see the AUTHOR RULE in `references/inbox.md`).
101
+
100
102
  For "how to" long_tails, add `HowTo`:
101
103
  ```json
102
104
  {
@@ -94,7 +94,7 @@ Pillars almost always need both `Article` and `FAQPage`:
94
94
  {
95
95
  "@type": "Article",
96
96
  "headline": "{Title}",
97
- "author": { "@type": "Person", "name": "{Author Name}" },
97
+ "author": { "@type": "Person", "name": "{author}", "jobTitle": "{author_title}", "url": "{author_url}", "sameAs": {author_same_as} },
98
98
  "datePublished": "{ISO date}",
99
99
  "dateModified": "{ISO date}",
100
100
  "image": "https://{domain}/{hero-image}",
@@ -113,6 +113,8 @@ Pillars almost always need both `Article` and `FAQPage`:
113
113
  ]
114
114
  ```
115
115
 
116
+ **Author:** take it from the draft's frontmatter: `author` → `name`, `author_title` → `jobTitle`, `author_url` → `url`, `author_same_as` → `sameAs`; leave out a key the draft does not have. No `author` in the frontmatter → use the publisher Organization as the `author`. Never invent a person. The byline on the page follows the same fields (see the AUTHOR RULE in `references/inbox.md`).
117
+
116
118
  If the pillar contains step-by-step processes, also add `HowTo` schema. If it contains a glossary section, add `DefinedTermSet`.
117
119
 
118
120
  ## After Writing
@@ -29,7 +29,7 @@ Figure out the destination from the codebase first (you usually already know it
29
29
 
30
30
  The site renders content from files in this repo (Next.js `content/`, Astro `src/content/`, a `_posts/` dir, MDX routes, a static-site generator, etc.).
31
31
 
32
- - **How you publish:** **Read an existing published article first** to learn the exact location, filename convention, and frontmatter shape this site expects. Then write the article **directly into a new file in that same location** (Phase 4 step 7), matching that frontmatter exactly (their field names, their date format, their tags). Inject internal links + image refs. If a route/sitemap entry is needed and missing, add it. **The repo file is the single source of truth for the body** — do NOT also write a full-body copy into `.seoagent/`.
32
+ - **How you publish:** **Read an existing published article first** to learn the exact location, filename convention, and frontmatter shape this site expects. Then write the article **directly into a new file in that same location** (Phase 4 step 7), matching that frontmatter exactly (their field names, their date format, their tags). Inject internal links + image refs. **Byline:** when the draft's frontmatter has `author`, the post carries it the way this repo's posts carry theirs (their author key or authors file); a template with no byline gets one in the same change (the name linked to `author_url` with `rel="author"`, the author `Person` in the Article JSON-LD). No `author` → no author fields. See the AUTHOR RULE in `references/inbox.md`. If a route/sitemap entry is needed and missing, add it. **The repo file is the single source of truth for the body** — do NOT also write a full-body copy into `.seoagent/`.
33
33
  - **Register it so the cloud sees it:** after the repo file is written, run `seoagent content track --slug {slug} --url https://{domain}{blog_path}/{slug} --file {path}` (Phase 4 step 7). That's what makes the article appear on the dashboard — `sync` only walks `.seoagent/`, so a repo-only article is otherwise invisible to the cloud. The track record is a pointer, not a duplicate.
34
34
  - **First post / just-converted blog (no existing file to copy):** if the content dir is empty — a brand-new blog, or one you're converting from a DB/headless source per the guardrail above — define a simple frontmatter convention yourself (`title`, `description`, `date`, `tags`, `slug`) and, if the route doesn't yet read from files, scaffold the loader + route to read the content dir (this is the one-time setup task in "After the user picks", tracked with `setup_status: pending` until it deploys).
35
35
  - **Ship it the way the repo ships:** open a PR (or commit to a branch) so the user's existing CI/CD deploys it. Never push straight to the default branch without asking.
@@ -39,7 +39,7 @@ The site renders content from files in this repo (Next.js `content/`, Astro `src
39
39
 
40
40
  The site pulls content from a CMS. You don't need a SEOAgent adapter — **read how the repo already talks to the CMS** (the existing fetch/SDK code, the env var names) and mirror it to *create* a post.
41
41
 
42
- - **How you publish:** find the CMS client/credentials the app already uses (`.env*`, an SDK import, an API base). Map the article (`title`, `slug`, body, meta, canonical, JSON-LD) to that CMS's content model and create the entry — print the exact `curl`/SDK call for the user to run, or, with explicit consent, run it yourself using their existing credentials. Confirm the post is a draft vs. published per the user's preference. The CMS holds the body; **then `seoagent content track --slug {slug} --url {live-url}` so the dashboard tracks it** (the cloud can't see your CMS).
42
+ - **How you publish:** find the CMS client/credentials the app already uses (`.env*`, an SDK import, an API base). Map the article (`title`, `slug`, body, meta, canonical, the `author` byline when the draft has one, JSON-LD) to that CMS's content model and create the entry — print the exact `curl`/SDK call for the user to run, or, with explicit consent, run it yourself using their existing credentials. Confirm the post is a draft vs. published per the user's preference. The CMS holds the body; **then `seoagent content track --slug {slug} --url {live-url}` so the dashboard tracks it** (the cloud can't see your CMS).
43
43
  - **Mapping starting points:** Strapi → `POST /api/articles` `{data:{…}}`. Sanity → `client.create({_type:'post',…})`. Contentful → Management API `createEntry`. Webflow → `POST /collections/:id/items`. Shopify → `POST /admin/api/.../articles.json`. Ghost → Admin API `posts.add`. WordPress → `POST /wp-json/wp/v2/posts`. For anything unfamiliar, ask the user once how a post gets created, then store the mapping in `project.md` so future articles are one step.
44
44
  - **Best for:** teams with an existing CMS — keep it, just get SEOAgent's content into it.
45
45
 
@@ -30,7 +30,9 @@ JSON-LD is the recommended format. Embed in `<script type="application/ld+json">
30
30
  "author": {
31
31
  "@type": "Person",
32
32
  "name": "Jane Doe",
33
- "url": "https://example.com/authors/jane"
33
+ "jobTitle": "Founder, Acme",
34
+ "url": "https://www.linkedin.com/in/janedoe",
35
+ "sameAs": ["https://www.linkedin.com/in/janedoe", "https://janedoe.com"]
34
36
  },
35
37
  "datePublished": "2026-04-27",
36
38
  "dateModified": "2026-04-27",
@@ -49,6 +51,8 @@ JSON-LD is the recommended format. Embed in `<script type="application/ld+json">
49
51
 
50
52
  Required: `headline`, `author`, `datePublished`, `dateModified`, `image`, `publisher.logo`. Missing any of these and Google may reject the rich result.
51
53
 
54
+ **The author comes from the article's frontmatter**, never from this example: `author` → `name`, `author_title` → `jobTitle`, `author_url` → `url`, `author_same_as` → `sameAs` (SEOAgent's cloud drafts carry these when the site owner added an author). Leave out a key the article does not have. With no `author`, the `author` is the publisher Organization: never invent a person. The visible byline links the name to the same `author_url` with `rel="author"`.
55
+
52
56
  ### FAQPage (add to articles with FAQ sections)
53
57
 
54
58
  ```json
@@ -106,6 +106,12 @@ word_count: 3120
106
106
  status: drafted
107
107
  created_at: 2026-04-27T10:00:00Z
108
108
  brief: tech-seo-guide
109
+ # Byline: present only when the site owner added a person author (cloud drafts carry it).
110
+ author: "Jane Doe"
111
+ author_title: "Founder, Acme"
112
+ author_url: "https://www.linkedin.com/in/janedoe" # the byline link (profile, else website)
113
+ author_same_as: ["https://www.linkedin.com/in/janedoe", "https://janedoe.com"]
114
+ author_key: "jane-doe" # optional: how this repo names the author (learned from `content track --author-key`)
109
115
  images:
110
116
  hero:
111
117
  alt: "Diagram of the technical SEO audit flow from crawl to indexation"
@@ -123,6 +129,8 @@ json_ld:
123
129
  ---
124
130
  ```
125
131
 
132
+ **Byline fields** (`author`, `author_title`, `author_url`, `author_same_as`, `author_key`): the cloud writes them into a draft only when the site owner set a person author (Site settings → Authors, or the `site.authors.set` chat tool). No `author` means the site has no author or uses the company name: write no author fields. When you place the article, put the byline where the repo's own posts keep theirs and fill the Article JSON-LD's author `Person` from these fields (the AUTHOR RULE in `references/inbox.md`).
133
+
126
134
  ## Audit output — `.seoagent/audit/latest.md`
127
135
 
128
136
  ```markdown
@@ -85,7 +85,7 @@ twitter:
85
85
  {
86
86
  "@type": "Article",
87
87
  "headline": "{Title}",
88
- "author": { "@type": "Person", "name": "{Author}" },
88
+ "author": { "@type": "Person", "name": "{author}", "jobTitle": "{author_title}", "url": "{author_url}", "sameAs": {author_same_as} },
89
89
  "datePublished": "{ISO date}",
90
90
  "dateModified": "{ISO date}",
91
91
  "image": "https://{domain}/{hero}",
@@ -98,6 +98,8 @@ twitter:
98
98
  ]
99
99
  ```
100
100
 
101
+ **Author:** take it from the draft's frontmatter: `author` → `name`, `author_title` → `jobTitle`, `author_url` → `url`, `author_same_as` → `sameAs`; leave out a key the draft does not have. No `author` in the frontmatter → use the publisher Organization as the `author`. Never invent a person. The byline on the page follows the same fields (see the AUTHOR RULE in `references/inbox.md`).
102
+
101
103
  Add `HowTo` schema when the article is an action-oriented step-by-step (title starts with "How to..." or has a numbered checklist as the main content).
102
104
 
103
105
  ## After Writing